nexmon – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 /* source: xiotransfer.c */
2 /* Copyright Gerhard Rieger 2007-2012 */
3 /* Published under the GNU General Public License V.2, see file COPYING */
4  
5 /* this is the source file of the data transfer function */
6  
7 #include "xiosysincludes.h"
8  
9 #include "mytypes.h"
10 #include "compat.h"
11 #include "error.h"
12  
13 #include "sycls.h"
14 #include "xio.h"
15  
16 static
17 int cv_newline(unsigned char **buff, ssize_t *bytes, int lineterm1, int lineterm2);
18  
19  
20 #define MAXTIMESTAMPLEN 128
21 /* prints the timestamp to the buffer and terminates it with '\0'. This buffer
22 should be at least MAXTIMESTAMPLEN bytes long.
23 returns 0 on success or -1 if an error occurred */
24 int gettimestamp(char *timestamp) {
25 size_t bytes;
26 #if HAVE_GETTIMEOFDAY || 1
27 struct timeval now;
28 int result;
29 time_t nowt;
30 #else /* !HAVE_GETTIMEOFDAY */
31 time_t now;
32 #endif /* !HAVE_GETTIMEOFDAY */
33  
34 #if HAVE_GETTIMEOFDAY || 1
35 result = gettimeofday(&now, NULL);
36 if (result < 0) {
37 return result;
38 } else {
39 nowt = now.tv_sec;
40 #if HAVE_STRFTIME
41 bytes = strftime(timestamp, 20, "%Y/%m/%d %H:%M:%S", localtime(&nowt));
42 bytes += sprintf(timestamp+19, "."F_tv_usec" ", now.tv_usec);
43 #else
44 strcpy(timestamp, ctime(&nowt));
45 bytes = strlen(timestamp);
46 #endif
47 }
48 #else /* !HAVE_GETTIMEOFDAY */
49 now = time(NULL); if (now == (time_t)-1) {
50 return -1;
51 } else {
52 #if HAVE_STRFTIME
53 bytes = strftime(timestamp, 21, "%Y/%m/%d %H:%M:%S ", localtime(&now));
54 #else
55 strcpy(timestamp, ctime(&now));
56 bytes = strlen(timestamp);
57 #endif
58 }
59 #endif /* !HAVE_GETTIMEOFDAY */
60 return 0;
61 }
62  
63  
64 static const char *prefixltor = "> ";
65 static const char *prefixrtol = "< ";
66 static unsigned long numltor;
67 static unsigned long numrtol;
68 /* print block header (during verbose or hex dump)
69 returns 0 on success or -1 if an error occurred */
70 static int
71 xioprintblockheader(FILE *file, size_t bytes, bool righttoleft) {
72 char timestamp[MAXTIMESTAMPLEN];
73 char buff[128+MAXTIMESTAMPLEN];
74 if (gettimestamp(timestamp) < 0) {
75 return -1;
76 }
77 if (righttoleft) {
78 sprintf(buff, "%s%s length="F_Zu" from=%lu to=%lu\n",
79 prefixrtol, timestamp, bytes, numrtol, numrtol+bytes-1);
80 numrtol+=bytes;
81 } else {
82 sprintf(buff, "%s%s length="F_Zu" from=%lu to=%lu\n",
83 prefixltor, timestamp, bytes, numltor, numltor+bytes-1);
84 numltor+=bytes;
85 }
86 fputs(buff, file);
87 return 0;
88 }
89  
90  
91 /* inpipe is suspected to have read data available; read at most bufsiz bytes
92 and transfer them to outpipe. Perform required data conversions.
93 buff must be a malloc()'ed storage and might be realloc()'ed in this
94 function if more space is required after conversions.
95 Returns the number of bytes written, or 0 on EOF or <0 if an
96 error occurred or when data was read but none written due to conversions
97 (with EAGAIN). EAGAIN also occurs when reading from a nonblocking FD where
98 the file has a mandatory lock.
99 If 0 bytes were read (EOF), it does NOT shutdown or close a channel, and it
100 does NOT write a zero bytes block.
101 */
102 /* inpipe, outpipe must be single descriptors (not dual!) */
103 int xiotransfer(xiofile_t *inpipe, xiofile_t *outpipe,
104 unsigned char **buff, size_t bufsiz, bool righttoleft) {
105 ssize_t bytes, writt = 0;
106  
107 bytes = xioread(inpipe, *buff, bufsiz);
108 if (bytes < 0) {
109 if (errno != EAGAIN)
110 XIO_RDSTREAM(inpipe)->eof = 2;
111 /*xioshutdown(inpipe, SHUT_RD);*/
112 return -1;
113 }
114 if (bytes == 0 && XIO_RDSTREAM(inpipe)->ignoreeof &&
115 !inpipe->stream.closing) {
116 ;
117 } else if (bytes == 0) {
118 XIO_RDSTREAM(inpipe)->eof = 2;
119 inpipe->stream.closing = MAX(inpipe->stream.closing, 1);
120 }
121  
122 if (bytes > 0) {
123 /* handle escape char */
124 if (XIO_RDSTREAM(inpipe)->escape != -1) {
125 /* check input data for escape char */
126 unsigned char *ptr = *buff;
127 size_t ctr = 0;
128 while (ctr < bytes) {
129 if (*ptr == XIO_RDSTREAM(inpipe)->escape) {
130 /* found: set flag, truncate input data */
131 XIO_RDSTREAM(inpipe)->actescape = true;
132 bytes = ctr;
133 Info("escape char found in input");
134 break;
135 }
136 ++ptr; ++ctr;
137 }
138 if (ctr != bytes) {
139 XIO_RDSTREAM(inpipe)->eof = 2;
140 }
141 }
142 }
143  
144 if (XIO_RDSTREAM(inpipe)->lineterm !=
145 XIO_WRSTREAM(outpipe)->lineterm) {
146 cv_newline(buff, &bytes,
147 XIO_RDSTREAM(inpipe)->lineterm,
148 XIO_WRSTREAM(outpipe)->lineterm);
149 }
150 if (bytes == 0) {
151 /*errno = EAGAIN; return -1;*/
152 return bytes;
153 }
154  
155 if (xioparams->verbose && xioparams->verbhex) {
156 /* Hack-o-rama */
157 size_t i = 0;
158 size_t j;
159 size_t N = 16;
160 const unsigned char *end, *s, *t;
161 s = *buff;
162 end = (*buff)+bytes;
163 xioprintblockheader(stderr, bytes, righttoleft);
164 while (s < end) {
165 /*! prefix? */
166 j = Min(N, (size_t)(end-s));
167  
168 /* print hex */
169 t = s;
170 i = 0;
171 while (i < j) {
172 int c = *t++;
173 fprintf(stderr, " %02x", c);
174 ++i;
175 if (c == '\n') break;
176 }
177  
178 /* fill hex column */
179 while (i < N) {
180 fputs(" ", stderr);
181 ++i;
182 }
183 fputs(" ", stderr);
184  
185 /* print acsii */
186 t = s;
187 i = 0;
188 while (i < j) {
189 int c = *t++;
190 if (c == '\n') {
191 fputc('.', stderr);
192 break;
193 }
194 if (!isprint(c))
195 c = '.';
196 fputc(c, stderr);
197 ++i;
198 }
199  
200 fputc('\n', stderr);
201 s = t;
202 }
203 fputs("--\n", stderr);
204 } else if (xioparams->verbose) {
205 size_t i = 0;
206 xioprintblockheader(stderr, bytes, righttoleft);
207 while (i < (size_t)bytes) {
208 int c = (*buff)[i];
209 if (i > 0 && (*buff)[i-1] == '\n')
210 /*! prefix? */;
211 switch (c) {
212 case '\a' : fputs("\\a", stderr); break;
213 case '\b' : fputs("\\b", stderr); break;
214 case '\t' : fputs("\t", stderr); break;
215 case '\n' : fputs("\n", stderr); break;
216 case '\v' : fputs("\\v", stderr); break;
217 case '\f' : fputs("\\f", stderr); break;
218 case '\r' : fputs("\\r", stderr); break;
219 case '\\' : fputs("\\\\", stderr); break;
220 default:
221 if (!isprint(c))
222 c = '.';
223 fputc(c, stderr);
224 break;
225 }
226 ++i;
227 }
228 } else if (xioparams->verbhex) {
229 int i;
230 /* print prefix */
231 xioprintblockheader(stderr, bytes, righttoleft);
232 for (i = 0; i < bytes; ++i) {
233 fprintf(stderr, " %02x", (*buff)[i]);
234 }
235 fputc('\n', stderr);
236 }
237  
238 writt = xiowrite(outpipe, *buff, bytes);
239 if (writt < 0) {
240 /* EAGAIN when nonblocking but a mandatory lock is on file.
241 the problem with EAGAIN is that the read cannot be repeated,
242 so we need to buffer the data and try to write it later
243 again. not yet implemented, sorry. */
244 #if 0
245 if (errno == EPIPE) {
246 return 0; /* can no longer write; handle like EOF */
247 }
248 #endif
249 return -1;
250 } else {
251 Info3("transferred "F_Zu" bytes from %d to %d",
252 writt, XIO_GETRDFD(inpipe), XIO_GETWRFD(outpipe));
253 }
254 return writt;
255 }
256  
257 #define CR '\r'
258 #define LF '\n'
259  
260  
261 static int cv_newline(unsigned char **buff, ssize_t *bytes,
262 int lineterm1, int lineterm2) {
263 /* must perform newline changes */
264 if (lineterm1 <= LINETERM_CR && lineterm2 <= LINETERM_CR) {
265 /* no change in data length */
266 unsigned char from, to, *p, *z;
267 if (lineterm1 == LINETERM_RAW) {
268 from = '\n'; to = '\r';
269 } else {
270 from = '\r'; to = '\n';
271 }
272 z = *buff + *bytes;
273 p = *buff;
274 while (p < z) {
275 if (*p == from) *p = to;
276 ++p;
277 }
278  
279 } else if (lineterm1 == LINETERM_CRNL) {
280 /* buffer becomes shorter */
281 unsigned char to, *s, *t, *z;
282 if (lineterm2 == LINETERM_RAW) {
283 to = '\n';
284 } else {
285 to = '\r';
286 }
287 z = *buff + *bytes;
288 s = t = *buff;
289 while (s < z) {
290 if (*s == '\r') {
291 ++s;
292 continue;
293 }
294 if (*s == '\n') {
295 *t++ = to; ++s;
296 } else {
297 *t++ = *s++;
298 }
299 }
300 *bytes = t - *buff;
301 } else {
302 /* buffer becomes longer, must alloc another space */
303 unsigned char *buf2;
304 unsigned char from; unsigned char *s, *t, *z;
305 if (lineterm1 == LINETERM_RAW) {
306 from = '\n';
307 } else {
308 from = '\r';
309 }
310 if ((buf2 = Malloc(2*xioparams->bufsiz + 1)) == NULL) {
311 return -1;
312 }
313 s = *buff; t = buf2; z = *buff + *bytes;
314 while (s < z) {
315 if (*s == from) {
316 *t++ = '\r'; *t++ = '\n';
317 ++s;
318 continue;
319 } else {
320 *t++ = *s++;
321 }
322 }
323 free(*buff);
324 *buff = buf2;
325 *bytes = t - buf2;;
326 }
327 return 0;
328 }