1 /* $OpenBSD: shf.c,v 1.16 2013/04/19 17:36:09 millert Exp $ */
2
3 /*-
4 * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2011,
5 * 2012, 2013, 2015, 2016, 2017, 2018, 2019
6 * mirabilos <m@mirbsd.org>
7 * Copyright (c) 2015
8 * Daniel Richard G. <skunk@iSKUNK.ORG>
9 *
10 * Provided that these terms and disclaimer and all copyright notices
11 * are retained or reproduced in an accompanying document, permission
12 * is granted to deal in this work without restriction, including un-
13 * limited rights to use, publicly perform, distribute, sell, modify,
14 * merge, give away, or sublicence.
15 *
16 * This work is provided "AS IS" and WITHOUT WARRANTY of any kind, to
17 * the utmost extent permitted by applicable law, neither express nor
18 * implied; without malicious intent or gross negligence. In no event
19 * may a licensor, author or contributor be held liable for indirect,
20 * direct, other damage, loss, or other issues arising in any way out
21 * of dealing in the work, even if advised of the possibility of such
22 * damage or existence of a defect, except proven that it results out
23 * of said person's immediate fault when using the work as intended.
24 *-
25 * Use %zX instead of %p and floating point isn't supported at all.
26 */
27
28 #include "sh.h"
29
30 __RCSID("$MirOS: src/bin/mksh/shf.c,v 1.102 2020/06/22 17:11:03 tg Exp $");
31
32 /* flags to shf_emptybuf() */
33 #define EB_READSW 0x01 /* about to switch to reading */
34 #define EB_GROW 0x02 /* grow buffer if necessary (STRING+DYNAMIC) */
35
36 /*
37 * Replacement stdio routines. Stdio is too flakey on too many machines
38 * to be useful when you have multiple processes using the same underlying
39 * file descriptors.
40 */
41
42 static int shf_fillbuf(struct shf *);
43 static int shf_emptybuf(struct shf *, int);
44
45 /*
46 * Open a file. First three args are for open(), last arg is flags for
47 * this package. Returns NULL if file could not be opened, or if a dup
48 * fails.
49 */
50 struct shf *
shf_open(const char * name,int oflags,int mode,int sflags)51 shf_open(const char *name, int oflags, int mode, int sflags)
52 {
53 struct shf *shf;
54 ssize_t bsize =
55 /* at most 512 */
56 sflags & SHF_UNBUF ? (sflags & SHF_RD ? 1 : 0) : SHF_BSIZE;
57 int fd, eno;
58
59 /* Done before open so if alloca fails, fd won't be lost. */
60 shf = alloc(sizeof(struct shf) + bsize, ATEMP);
61 shf->areap = ATEMP;
62 shf->buf = (unsigned char *)&shf[1];
63 shf->bsize = bsize;
64 shf->flags = SHF_ALLOCS;
65 /* Rest filled in by reopen. */
66
67 fd = binopen3(name, oflags, mode);
68 if (fd < 0) {
69 eno = errno;
70 afree(shf, shf->areap);
71 errno = eno;
72 return (NULL);
73 }
74 if ((sflags & SHF_MAPHI) && fd < FDBASE) {
75 int nfd;
76
77 nfd = fcntl(fd, F_DUPFD, FDBASE);
78 eno = errno;
79 close(fd);
80 if (nfd < 0) {
81 afree(shf, shf->areap);
82 errno = eno;
83 return (NULL);
84 }
85 fd = nfd;
86 }
87 sflags &= ~SHF_ACCMODE;
88 sflags |= (oflags & O_ACCMODE) == O_RDONLY ? SHF_RD :
89 ((oflags & O_ACCMODE) == O_WRONLY ? SHF_WR : SHF_RDWR);
90
91 return (shf_reopen(fd, sflags, shf));
92 }
93
94 /* helper function for shf_fdopen and shf_reopen */
95 static void
shf_open_hlp(int fd,int * sflagsp,const char * where)96 shf_open_hlp(int fd, int *sflagsp, const char *where)
97 {
98 int sflags = *sflagsp;
99
100 /* use fcntl() to figure out correct read/write flags */
101 if (sflags & SHF_GETFL) {
102 int flags = fcntl(fd, F_GETFL, 0);
103
104 if (flags < 0)
105 /* will get an error on first read/write */
106 sflags |= SHF_RDWR;
107 else {
108 switch (flags & O_ACCMODE) {
109 case O_RDONLY:
110 sflags |= SHF_RD;
111 break;
112 case O_WRONLY:
113 sflags |= SHF_WR;
114 break;
115 case O_RDWR:
116 sflags |= SHF_RDWR;
117 break;
118 }
119 }
120 *sflagsp = sflags;
121 }
122
123 if (!(sflags & (SHF_RD | SHF_WR)))
124 internal_errorf(Tf_sD_s, where, "missing read/write");
125 }
126
127 /* Set up the shf structure for a file descriptor. Doesn't fail. */
128 struct shf *
shf_fdopen(int fd,int sflags,struct shf * shf)129 shf_fdopen(int fd, int sflags, struct shf *shf)
130 {
131 ssize_t bsize =
132 /* at most 512 */
133 sflags & SHF_UNBUF ? (sflags & SHF_RD ? 1 : 0) : SHF_BSIZE;
134
135 shf_open_hlp(fd, &sflags, "shf_fdopen");
136 if (shf) {
137 if (bsize) {
138 shf->buf = alloc(bsize, ATEMP);
139 sflags |= SHF_ALLOCB;
140 } else
141 shf->buf = NULL;
142 } else {
143 shf = alloc(sizeof(struct shf) + bsize, ATEMP);
144 shf->buf = (unsigned char *)&shf[1];
145 sflags |= SHF_ALLOCS;
146 }
147 shf->areap = ATEMP;
148 shf->fd = fd;
149 shf->rp = shf->wp = shf->buf;
150 shf->rnleft = 0;
151 shf->rbsize = bsize;
152 shf->wnleft = 0; /* force call to shf_emptybuf() */
153 shf->wbsize = sflags & SHF_UNBUF ? 0 : bsize;
154 shf->flags = sflags;
155 shf->errnosv = 0;
156 shf->bsize = bsize;
157 if (sflags & SHF_CLEXEC)
158 fcntl(fd, F_SETFD, FD_CLOEXEC);
159 return (shf);
160 }
161
162 /* Set up an existing shf (and buffer) to use the given fd */
163 struct shf *
shf_reopen(int fd,int sflags,struct shf * shf)164 shf_reopen(int fd, int sflags, struct shf *shf)
165 {
166 ssize_t bsize =
167 /* at most 512 */
168 sflags & SHF_UNBUF ? (sflags & SHF_RD ? 1 : 0) : SHF_BSIZE;
169
170 shf_open_hlp(fd, &sflags, "shf_reopen");
171 if (!shf || !shf->buf || shf->bsize < bsize)
172 internal_errorf(Tf_sD_s, "shf_reopen", Tbad_bsize);
173
174 /* assumes shf->buf and shf->bsize already set up */
175 shf->fd = fd;
176 shf->rp = shf->wp = shf->buf;
177 shf->rnleft = 0;
178 shf->rbsize = bsize;
179 shf->wnleft = 0; /* force call to shf_emptybuf() */
180 shf->wbsize = sflags & SHF_UNBUF ? 0 : bsize;
181 shf->flags = (shf->flags & (SHF_ALLOCS | SHF_ALLOCB)) | sflags;
182 shf->errnosv = 0;
183 if (sflags & SHF_CLEXEC)
184 fcntl(fd, F_SETFD, FD_CLOEXEC);
185 return (shf);
186 }
187
188 /*
189 * Open a string for reading or writing. If reading, bsize is the number
190 * of bytes that can be read. If writing, bsize is the maximum number of
191 * bytes that can be written. If shf is not NULL, it is filled in and
192 * returned, if it is NULL, shf is allocated. If writing and buf is NULL
193 * and SHF_DYNAMIC is set, the buffer is allocated (if bsize > 0, it is
194 * used for the initial size). Doesn't fail.
195 * When writing, a byte is reserved for a trailing NUL - see shf_sclose().
196 */
197 struct shf *
shf_sopen(char * buf,ssize_t bsize,int sflags,struct shf * shf)198 shf_sopen(char *buf, ssize_t bsize, int sflags, struct shf *shf)
199 {
200 /* can't have a read+write string */
201 if (!(!(sflags & SHF_RD) ^ !(sflags & SHF_WR)))
202 internal_errorf(Tf_flags, "shf_sopen",
203 (unsigned int)sflags);
204
205 if (!shf) {
206 shf = alloc(sizeof(struct shf), ATEMP);
207 sflags |= SHF_ALLOCS;
208 }
209 shf->areap = ATEMP;
210 if (!buf && (sflags & SHF_WR) && (sflags & SHF_DYNAMIC)) {
211 if (bsize <= 0)
212 bsize = 64;
213 sflags |= SHF_ALLOCB;
214 buf = alloc(bsize, shf->areap);
215 }
216 shf->fd = -1;
217 shf->buf = shf->rp = shf->wp = (unsigned char *)buf;
218 shf->rnleft = bsize;
219 shf->rbsize = bsize;
220 shf->wnleft = bsize - 1; /* space for a '\0' */
221 shf->wbsize = bsize;
222 shf->flags = sflags | SHF_STRING;
223 shf->errnosv = 0;
224 shf->bsize = bsize;
225
226 return (shf);
227 }
228
229 /* Flush and close file descriptor, free the shf structure */
230 int
shf_close(struct shf * shf)231 shf_close(struct shf *shf)
232 {
233 int ret = 0;
234
235 if (shf->fd >= 0) {
236 ret = shf_flush(shf);
237 if (close(shf->fd) < 0)
238 ret = -1;
239 }
240 if (shf->flags & SHF_ALLOCS)
241 afree(shf, shf->areap);
242 else if (shf->flags & SHF_ALLOCB)
243 afree(shf->buf, shf->areap);
244
245 return (ret);
246 }
247
248 /* Flush and close file descriptor, don't free file structure */
249 int
shf_fdclose(struct shf * shf)250 shf_fdclose(struct shf *shf)
251 {
252 int ret = 0;
253
254 if (shf->fd >= 0) {
255 ret = shf_flush(shf);
256 if (close(shf->fd) < 0)
257 ret = -1;
258 shf->rnleft = 0;
259 shf->rp = shf->buf;
260 shf->wnleft = 0;
261 shf->fd = -1;
262 }
263
264 return (ret);
265 }
266
267 /*
268 * Close a string - if it was opened for writing, it is NUL terminated;
269 * returns a pointer to the string and frees shf if it was allocated
270 * (does not free string if it was allocated).
271 */
272 char *
shf_sclose(struct shf * shf)273 shf_sclose(struct shf *shf)
274 {
275 unsigned char *s = shf->buf;
276
277 /* NUL terminate */
278 if (shf->flags & SHF_WR) {
279 shf->wnleft++;
280 shf_putc('\0', shf);
281 }
282 if (shf->flags & SHF_ALLOCS)
283 afree(shf, shf->areap);
284 return ((char *)s);
285 }
286
287 /*
288 * Un-read what has been read but not examined, or write what has been
289 * buffered. Returns 0 for success, -1 for (write) error.
290 */
291 int
shf_flush(struct shf * shf)292 shf_flush(struct shf *shf)
293 {
294 int rv = 0;
295
296 if (shf->flags & SHF_STRING)
297 rv = (shf->flags & SHF_WR) ? -1 : 0;
298 else if (shf->fd < 0)
299 internal_errorf(Tf_sD_s, "shf_flush", "no fd");
300 else if (shf->flags & SHF_ERROR) {
301 errno = shf->errnosv;
302 rv = -1;
303 } else if (shf->flags & SHF_READING) {
304 shf->flags &= ~(SHF_EOF | SHF_READING);
305 if (shf->rnleft > 0) {
306 if (lseek(shf->fd, (off_t)-shf->rnleft,
307 SEEK_CUR) == -1) {
308 shf->flags |= SHF_ERROR;
309 shf->errnosv = errno;
310 rv = -1;
311 }
312 shf->rnleft = 0;
313 shf->rp = shf->buf;
314 }
315 } else if (shf->flags & SHF_WRITING)
316 rv = shf_emptybuf(shf, 0);
317
318 return (rv);
319 }
320
321 /*
322 * Write out any buffered data. If currently reading, flushes the read
323 * buffer. Returns 0 for success, -1 for (write) error.
324 */
325 static int
shf_emptybuf(struct shf * shf,int flags)326 shf_emptybuf(struct shf *shf, int flags)
327 {
328 int ret = 0;
329
330 if (!(shf->flags & SHF_STRING) && shf->fd < 0)
331 internal_errorf(Tf_sD_s, "shf_emptybuf", "no fd");
332
333 if (shf->flags & SHF_ERROR) {
334 errno = shf->errnosv;
335 return (-1);
336 }
337
338 if (shf->flags & SHF_READING) {
339 if (flags & EB_READSW)
340 /* doesn't happen */
341 return (0);
342 ret = shf_flush(shf);
343 shf->flags &= ~SHF_READING;
344 }
345 if (shf->flags & SHF_STRING) {
346 unsigned char *nbuf;
347
348 /*
349 * Note that we assume SHF_ALLOCS is not set if
350 * SHF_ALLOCB is set... (changing the shf pointer could
351 * cause problems)
352 */
353 if (!(flags & EB_GROW) || !(shf->flags & SHF_DYNAMIC) ||
354 !(shf->flags & SHF_ALLOCB))
355 return (-1);
356 /* allocate more space for buffer */
357 nbuf = aresize2(shf->buf, 2, shf->wbsize, shf->areap);
358 shf->rp = nbuf + (shf->rp - shf->buf);
359 shf->wp = nbuf + (shf->wp - shf->buf);
360 shf->rbsize += shf->wbsize;
361 shf->wnleft += shf->wbsize;
362 shf->wbsize <<= 1;
363 shf->buf = nbuf;
364 } else {
365 if (shf->flags & SHF_WRITING) {
366 ssize_t n, ntowrite = shf->wp - shf->buf;
367 unsigned char *buf = shf->buf;
368
369 while (ntowrite > 0) {
370 n = write(shf->fd, buf, ntowrite);
371 if (n < 0) {
372 if (errno == EINTR &&
373 !(shf->flags & SHF_INTERRUPT))
374 continue;
375 shf->flags |= SHF_ERROR;
376 shf->errnosv = errno;
377 shf->wnleft = 0;
378 if (buf != shf->buf) {
379 /*
380 * allow a second flush
381 * to work
382 */
383 memmove(shf->buf, buf,
384 ntowrite);
385 shf->wp = shf->buf + ntowrite;
386 }
387 return (-1);
388 }
389 buf += n;
390 ntowrite -= n;
391 }
392 if (flags & EB_READSW) {
393 shf->wp = shf->buf;
394 shf->wnleft = 0;
395 shf->flags &= ~SHF_WRITING;
396 return (0);
397 }
398 }
399 shf->wp = shf->buf;
400 shf->wnleft = shf->wbsize;
401 }
402 shf->flags |= SHF_WRITING;
403
404 return (ret);
405 }
406
407 /* Fill up a read buffer. Returns -1 for a read error, 0 otherwise. */
408 static int
shf_fillbuf(struct shf * shf)409 shf_fillbuf(struct shf *shf)
410 {
411 ssize_t n;
412
413 if (shf->flags & SHF_STRING)
414 return (0);
415
416 if (shf->fd < 0)
417 internal_errorf(Tf_sD_s, "shf_fillbuf", "no fd");
418
419 if (shf->flags & (SHF_EOF | SHF_ERROR)) {
420 if (shf->flags & SHF_ERROR)
421 errno = shf->errnosv;
422 return (-1);
423 }
424
425 if ((shf->flags & SHF_WRITING) && shf_emptybuf(shf, EB_READSW) == -1)
426 return (-1);
427
428 shf->flags |= SHF_READING;
429
430 shf->rp = shf->buf;
431 while (/* CONSTCOND */ 1) {
432 n = blocking_read(shf->fd, (char *)shf->buf, shf->rbsize);
433 if (n < 0 && errno == EINTR && !(shf->flags & SHF_INTERRUPT))
434 continue;
435 break;
436 }
437 if (n < 0) {
438 shf->flags |= SHF_ERROR;
439 shf->errnosv = errno;
440 shf->rnleft = 0;
441 shf->rp = shf->buf;
442 return (-1);
443 }
444 if ((shf->rnleft = n) == 0)
445 shf->flags |= SHF_EOF;
446 return (0);
447 }
448
449 /*
450 * Read a buffer from shf. Returns the number of bytes read into buf, if
451 * no bytes were read, returns 0 if end of file was seen, -1 if a read
452 * error occurred.
453 */
454 ssize_t
shf_read(char * buf,ssize_t bsize,struct shf * shf)455 shf_read(char *buf, ssize_t bsize, struct shf *shf)
456 {
457 ssize_t ncopy, orig_bsize = bsize;
458
459 if (!(shf->flags & SHF_RD))
460 internal_errorf(Tf_flags, Tshf_read,
461 (unsigned int)shf->flags);
462
463 if (bsize <= 0)
464 internal_errorf(Tf_szs, Tshf_read, bsize, Tbsize);
465
466 while (bsize > 0) {
467 if (shf->rnleft == 0 &&
468 (shf_fillbuf(shf) == -1 || shf->rnleft == 0))
469 break;
470 ncopy = shf->rnleft;
471 if (ncopy > bsize)
472 ncopy = bsize;
473 memcpy(buf, shf->rp, ncopy);
474 buf += ncopy;
475 bsize -= ncopy;
476 shf->rp += ncopy;
477 shf->rnleft -= ncopy;
478 }
479 /* Note: fread(3S) returns 0 for errors - this doesn't */
480 return (orig_bsize == bsize ? (shf_error(shf) ? -1 : 0) :
481 orig_bsize - bsize);
482 }
483
484 /*
485 * Read up to a newline or -1. The newline is put in buf; buf is always
486 * NUL terminated. Returns NULL on read error or if nothing was read
487 * before end of file, returns a pointer to the NUL byte in buf
488 * otherwise.
489 */
490 char *
shf_getse(char * buf,ssize_t bsize,struct shf * shf)491 shf_getse(char *buf, ssize_t bsize, struct shf *shf)
492 {
493 unsigned char *end;
494 ssize_t ncopy;
495 char *orig_buf = buf;
496
497 if (!(shf->flags & SHF_RD))
498 internal_errorf(Tf_flags, "shf_getse",
499 (unsigned int)shf->flags);
500
501 if (bsize <= 0)
502 return (NULL);
503
504 /* save room for NUL */
505 --bsize;
506 do {
507 if (shf->rnleft == 0) {
508 if (shf_fillbuf(shf) == -1)
509 return (NULL);
510 if (shf->rnleft == 0) {
511 *buf = '\0';
512 return (buf == orig_buf ? NULL : buf);
513 }
514 }
515 end = (unsigned char *)memchr((char *)shf->rp, '\n',
516 shf->rnleft);
517 ncopy = end ? end - shf->rp + 1 : shf->rnleft;
518 if (ncopy > bsize)
519 ncopy = bsize;
520 memcpy(buf, (char *) shf->rp, ncopy);
521 shf->rp += ncopy;
522 shf->rnleft -= ncopy;
523 buf += ncopy;
524 bsize -= ncopy;
525 #ifdef MKSH_WITH_TEXTMODE
526 if (buf > orig_buf + 1 && ord(buf[-2]) == ORD('\r') &&
527 ord(buf[-1]) == ORD('\n')) {
528 buf--;
529 bsize++;
530 buf[-1] = '\n';
531 }
532 #endif
533 } while (!end && bsize);
534 #ifdef MKSH_WITH_TEXTMODE
535 if (!bsize && ord(buf[-1]) == ORD('\r')) {
536 int c = shf_getc(shf);
537 if (ord(c) == ORD('\n'))
538 buf[-1] = '\n';
539 else if (c != -1)
540 shf_ungetc(c, shf);
541 }
542 #endif
543 *buf = '\0';
544 return (buf);
545 }
546
547 /* Returns the char read. Returns -1 for error and end of file. */
548 int
shf_getchar(struct shf * shf)549 shf_getchar(struct shf *shf)
550 {
551 if (!(shf->flags & SHF_RD))
552 internal_errorf(Tf_flags, "shf_getchar",
553 (unsigned int)shf->flags);
554
555 if (shf->rnleft == 0 && (shf_fillbuf(shf) == -1 || shf->rnleft == 0))
556 return (-1);
557 --shf->rnleft;
558 return (ord(*shf->rp++));
559 }
560
561 /*
562 * Put a character back in the input stream. Returns the character if
563 * successful, -1 if there is no room.
564 */
565 int
shf_ungetc(int c,struct shf * shf)566 shf_ungetc(int c, struct shf *shf)
567 {
568 if (!(shf->flags & SHF_RD))
569 internal_errorf(Tf_flags, "shf_ungetc",
570 (unsigned int)shf->flags);
571
572 if ((shf->flags & SHF_ERROR) || c == -1 ||
573 (shf->rp == shf->buf && shf->rnleft))
574 return (-1);
575
576 if ((shf->flags & SHF_WRITING) && shf_emptybuf(shf, EB_READSW) == -1)
577 return (-1);
578
579 if (shf->rp == shf->buf)
580 shf->rp = shf->buf + shf->rbsize;
581 if (shf->flags & SHF_STRING) {
582 /*
583 * Can unget what was read, but not something different;
584 * we don't want to modify a string.
585 */
586 if ((int)(shf->rp[-1]) != c)
587 return (-1);
588 shf->flags &= ~SHF_EOF;
589 shf->rp--;
590 shf->rnleft++;
591 return (c);
592 }
593 shf->flags &= ~SHF_EOF;
594 *--(shf->rp) = c;
595 shf->rnleft++;
596 return (c);
597 }
598
599 /*
600 * Write a character. Returns the character if successful, -1 if the
601 * char could not be written.
602 */
603 int
shf_putchar(int c,struct shf * shf)604 shf_putchar(int c, struct shf *shf)
605 {
606 if (!(shf->flags & SHF_WR))
607 internal_errorf(Tf_flags, "shf_putchar",
608 (unsigned int)shf->flags);
609
610 if (c == -1)
611 return (-1);
612
613 if (shf->flags & SHF_UNBUF) {
614 unsigned char cc = (unsigned char)c;
615 ssize_t n;
616
617 if (shf->fd < 0)
618 internal_errorf(Tf_sD_s, "shf_putchar", "no fd");
619 if (shf->flags & SHF_ERROR) {
620 errno = shf->errnosv;
621 return (-1);
622 }
623 while ((n = write(shf->fd, &cc, 1)) != 1)
624 if (n < 0) {
625 if (errno == EINTR &&
626 !(shf->flags & SHF_INTERRUPT))
627 continue;
628 shf->flags |= SHF_ERROR;
629 shf->errnosv = errno;
630 return (-1);
631 }
632 } else {
633 /* Flush deals with strings and sticky errors */
634 if (shf->wnleft == 0 && shf_emptybuf(shf, EB_GROW) == -1)
635 return (-1);
636 shf->wnleft--;
637 *shf->wp++ = c;
638 }
639
640 return (c);
641 }
642
643 /*
644 * Write a string. Returns the length of the string if successful, -1
645 * if the string could not be written.
646 */
647 ssize_t
shf_puts(const char * s,struct shf * shf)648 shf_puts(const char *s, struct shf *shf)
649 {
650 if (!s)
651 return (-1);
652
653 return (shf_write(s, strlen(s), shf));
654 }
655
656 /* Write a buffer. Returns nbytes if successful, -1 if there is an error. */
657 ssize_t
shf_write(const char * buf,ssize_t nbytes,struct shf * shf)658 shf_write(const char *buf, ssize_t nbytes, struct shf *shf)
659 {
660 ssize_t n, ncopy, orig_nbytes = nbytes;
661
662 if (!(shf->flags & SHF_WR))
663 internal_errorf(Tf_flags, Tshf_write,
664 (unsigned int)shf->flags);
665
666 if (nbytes < 0)
667 internal_errorf(Tf_szs, Tshf_write, nbytes, Tbytes);
668
669 /* don't buffer if buffer is empty and we're writing a large amount */
670 if ((ncopy = shf->wnleft) &&
671 (shf->wp != shf->buf || nbytes < shf->wnleft)) {
672 if (ncopy > nbytes)
673 ncopy = nbytes;
674 memcpy(shf->wp, buf, ncopy);
675 nbytes -= ncopy;
676 buf += ncopy;
677 shf->wp += ncopy;
678 shf->wnleft -= ncopy;
679 }
680 if (nbytes > 0) {
681 if (shf->flags & SHF_STRING) {
682 /* resize buffer until there's enough space left */
683 while (nbytes > shf->wnleft)
684 if (shf_emptybuf(shf, EB_GROW) == -1)
685 return (-1);
686 /* then write everything into the buffer */
687 } else {
688 /* flush deals with sticky errors */
689 if (shf_emptybuf(shf, EB_GROW) == -1)
690 return (-1);
691 /* write chunks larger than window size directly */
692 if (nbytes > shf->wbsize) {
693 ncopy = nbytes;
694 if (shf->wbsize)
695 ncopy -= nbytes % shf->wbsize;
696 nbytes -= ncopy;
697 while (ncopy > 0) {
698 n = write(shf->fd, buf, ncopy);
699 if (n < 0) {
700 if (errno == EINTR &&
701 !(shf->flags & SHF_INTERRUPT))
702 continue;
703 shf->flags |= SHF_ERROR;
704 shf->errnosv = errno;
705 shf->wnleft = 0;
706 /*
707 * Note: fwrite(3) returns 0
708 * for errors - this doesn't
709 */
710 return (-1);
711 }
712 buf += n;
713 ncopy -= n;
714 }
715 }
716 /* ... and buffer the rest */
717 }
718 if (nbytes > 0) {
719 /* write remaining bytes to buffer */
720 memcpy(shf->wp, buf, nbytes);
721 shf->wp += nbytes;
722 shf->wnleft -= nbytes;
723 }
724 }
725
726 return (orig_nbytes);
727 }
728
729 ssize_t
shf_fprintf(struct shf * shf,const char * fmt,...)730 shf_fprintf(struct shf *shf, const char *fmt, ...)
731 {
732 va_list args;
733 ssize_t n;
734
735 va_start(args, fmt);
736 n = shf_vfprintf(shf, fmt, args);
737 va_end(args);
738
739 return (n);
740 }
741
742 ssize_t
shf_snprintf(char * buf,ssize_t bsize,const char * fmt,...)743 shf_snprintf(char *buf, ssize_t bsize, const char *fmt, ...)
744 {
745 struct shf shf;
746 va_list args;
747 ssize_t n;
748
749 if (!buf || bsize <= 0)
750 internal_errorf("shf_snprintf: buf %zX, bsize %zd",
751 (size_t)buf, bsize);
752
753 shf_sopen(buf, bsize, SHF_WR, &shf);
754 va_start(args, fmt);
755 n = shf_vfprintf(&shf, fmt, args);
756 va_end(args);
757 /* NUL terminates */
758 shf_sclose(&shf);
759 return (n);
760 }
761
762 char *
shf_smprintf(const char * fmt,...)763 shf_smprintf(const char *fmt, ...)
764 {
765 struct shf shf;
766 va_list args;
767
768 shf_sopen(NULL, 0, SHF_WR|SHF_DYNAMIC, &shf);
769 va_start(args, fmt);
770 shf_vfprintf(&shf, fmt, args);
771 va_end(args);
772 /* NUL terminates */
773 return (shf_sclose(&shf));
774 }
775
776 #define FL_HASH 0x001 /* '#' seen */
777 #define FL_PLUS 0x002 /* '+' seen */
778 #define FL_RIGHT 0x004 /* '-' seen */
779 #define FL_BLANK 0x008 /* ' ' seen */
780 #define FL_SHORT 0x010 /* 'h' seen */
781 #define FL_LONG 0x020 /* 'l' seen */
782 #define FL_ZERO 0x040 /* '0' seen */
783 #define FL_DOT 0x080 /* '.' seen */
784 #define FL_UPPER 0x100 /* format character was uppercase */
785 #define FL_NUMBER 0x200 /* a number was formatted %[douxefg] */
786 #define FL_SIZET 0x400 /* 'z' seen */
787 #define FM_SIZES 0x430 /* h/l/z mask */
788
789 ssize_t
shf_vfprintf(struct shf * shf,const char * fmt,va_list args)790 shf_vfprintf(struct shf *shf, const char *fmt, va_list args)
791 {
792 const char *s;
793 char c, *cp;
794 int tmp = 0, flags;
795 size_t field, precision, len;
796 unsigned long lnum;
797 /* %#o produces the longest output */
798 char numbuf[(8 * sizeof(long) + 2) / 3 + 1 + /* NUL */ 1];
799 /* this stuff for dealing with the buffer */
800 ssize_t nwritten = 0;
801
802 #define VA(type) va_arg(args, type)
803
804 if (!fmt)
805 return (0);
806
807 while ((c = *fmt++)) {
808 if (c != '%') {
809 shf_putc(c, shf);
810 nwritten++;
811 continue;
812 }
813 /*
814 * This will accept flags/fields in any order - not just
815 * the order specified in printf(3), but this is the way
816 * _doprnt() seems to work (on BSD and SYSV). The only
817 * restriction is that the format character must come
818 * last :-).
819 */
820 flags = 0;
821 field = precision = 0;
822 while ((c = *fmt++)) {
823 switch (c) {
824 case '#':
825 flags |= FL_HASH;
826 continue;
827
828 case '+':
829 flags |= FL_PLUS;
830 continue;
831
832 case '-':
833 flags |= FL_RIGHT;
834 continue;
835
836 case ' ':
837 flags |= FL_BLANK;
838 continue;
839
840 case '0':
841 if (!(flags & FL_DOT))
842 flags |= FL_ZERO;
843 continue;
844
845 case '.':
846 flags |= FL_DOT;
847 precision = 0;
848 continue;
849
850 case '*':
851 tmp = VA(int);
852 if (tmp < 0) {
853 if (flags & FL_DOT)
854 precision = 0;
855 else {
856 field = (unsigned int)-tmp;
857 flags |= FL_RIGHT;
858 }
859 } else if (flags & FL_DOT)
860 precision = (unsigned int)tmp;
861 else
862 field = (unsigned int)tmp;
863 continue;
864
865 case 'l':
866 flags &= ~FM_SIZES;
867 flags |= FL_LONG;
868 continue;
869
870 case 'h':
871 flags &= ~FM_SIZES;
872 flags |= FL_SHORT;
873 continue;
874
875 case 'z':
876 flags &= ~FM_SIZES;
877 flags |= FL_SIZET;
878 continue;
879 }
880 if (ctype(c, C_DIGIT)) {
881 bool overflowed = false;
882
883 tmp = ksh_numdig(c);
884 while (ctype((c = *fmt++), C_DIGIT))
885 if (notok2mul(2147483647, tmp, 10))
886 overflowed = true;
887 else
888 tmp = tmp * 10 + ksh_numdig(c);
889 --fmt;
890 if (overflowed)
891 tmp = 0;
892 if (flags & FL_DOT)
893 precision = (unsigned int)tmp;
894 else
895 field = (unsigned int)tmp;
896 continue;
897 }
898 break;
899 }
900
901 if (!c)
902 /* nasty format */
903 break;
904
905 if (ctype(c, C_UPPER)) {
906 flags |= FL_UPPER;
907 c = ksh_tolower(c);
908 }
909
910 switch (c) {
911 case 'd':
912 case 'i':
913 if (flags & FL_SIZET)
914 lnum = (long)VA(ssize_t);
915 else if (flags & FL_LONG)
916 lnum = VA(long);
917 else if (flags & FL_SHORT)
918 lnum = (long)(short)VA(int);
919 else
920 lnum = (long)VA(int);
921 goto integral;
922
923 case 'o':
924 case 'u':
925 case 'x':
926 if (flags & FL_SIZET)
927 lnum = VA(size_t);
928 else if (flags & FL_LONG)
929 lnum = VA(unsigned long);
930 else if (flags & FL_SHORT)
931 lnum = (unsigned long)(unsigned short)VA(int);
932 else
933 lnum = (unsigned long)VA(unsigned int);
934
935 integral:
936 flags |= FL_NUMBER;
937 cp = numbuf + sizeof(numbuf);
938 *--cp = '\0';
939
940 switch (c) {
941 case 'd':
942 case 'i':
943 if (0 > (long)lnum) {
944 lnum = -(long)lnum;
945 tmp = 1;
946 } else
947 tmp = 0;
948 /* FALLTHROUGH */
949 case 'u':
950 do {
951 *--cp = digits_lc[lnum % 10];
952 lnum /= 10;
953 } while (lnum);
954
955 if (c != 'u') {
956 if (tmp)
957 *--cp = '-';
958 else if (flags & FL_PLUS)
959 *--cp = '+';
960 else if (flags & FL_BLANK)
961 *--cp = ' ';
962 }
963 break;
964
965 case 'o':
966 do {
967 *--cp = digits_lc[lnum & 0x7];
968 lnum >>= 3;
969 } while (lnum);
970
971 if ((flags & FL_HASH) && *cp != '0')
972 *--cp = '0';
973 break;
974
975 case 'x': {
976 const char *digits = (flags & FL_UPPER) ?
977 digits_uc : digits_lc;
978 do {
979 *--cp = digits[lnum & 0xF];
980 lnum >>= 4;
981 } while (lnum);
982
983 if (flags & FL_HASH) {
984 *--cp = (flags & FL_UPPER) ? 'X' : 'x';
985 *--cp = '0';
986 }
987 }
988 }
989 len = numbuf + sizeof(numbuf) - 1 - (s = cp);
990 if (flags & FL_DOT) {
991 if (precision > len) {
992 field = precision;
993 flags |= FL_ZERO;
994 } else
995 /* no loss */
996 precision = len;
997 }
998 break;
999
1000 case 's':
1001 if ((s = VA(const char *)) == NULL)
1002 s = "(null)";
1003 else if (flags & FL_HASH) {
1004 print_value_quoted(shf, s);
1005 continue;
1006 }
1007 len = utf_mbswidth(s);
1008 break;
1009
1010 case 'c':
1011 flags &= ~FL_DOT;
1012 c = (char)(VA(int));
1013 /* FALLTHROUGH */
1014
1015 case '%':
1016 default:
1017 numbuf[0] = c;
1018 numbuf[1] = 0;
1019 s = numbuf;
1020 len = 1;
1021 break;
1022 }
1023
1024 /*
1025 * At this point s should point to a string that is to be
1026 * formatted, and len should be the length of the string.
1027 */
1028 if (!(flags & FL_DOT) || len < precision)
1029 precision = len;
1030 if (field > precision) {
1031 field -= precision;
1032 if (!(flags & FL_RIGHT)) {
1033 /* skip past sign or 0x when padding with 0 */
1034 if ((flags & FL_ZERO) && (flags & FL_NUMBER)) {
1035 if (ctype(*s, C_SPC | C_PLUS | C_MINUS)) {
1036 shf_putc(*s, shf);
1037 s++;
1038 precision--;
1039 nwritten++;
1040 } else if (*s == '0') {
1041 shf_putc(*s, shf);
1042 s++;
1043 nwritten++;
1044 if (--precision &&
1045 ksh_eq(*s, 'X', 'x')) {
1046 shf_putc(*s, shf);
1047 s++;
1048 precision--;
1049 nwritten++;
1050 }
1051 }
1052 c = '0';
1053 } else
1054 c = flags & FL_ZERO ? '0' : ' ';
1055 nwritten += field;
1056 while (field--)
1057 shf_putc(c, shf);
1058 field = 0;
1059 } else
1060 c = ' ';
1061 } else
1062 field = 0;
1063
1064 nwritten += precision;
1065 precision = utf_skipcols(s, precision, &tmp) - s;
1066 while (precision--)
1067 shf_putc(*s++, shf);
1068
1069 nwritten += field;
1070 while (field--)
1071 shf_putc(c, shf);
1072 }
1073
1074 return (shf_error(shf) ? -1 : nwritten);
1075 }
1076
1077 #ifdef MKSH_SHF_NO_INLINE
1078 int
shf_getc(struct shf * shf)1079 shf_getc(struct shf *shf)
1080 {
1081 return (shf_getc_i(shf));
1082 }
1083
1084 int
shf_putc(int c,struct shf * shf)1085 shf_putc(int c, struct shf *shf)
1086 {
1087 return (shf_putc_i(c, shf));
1088 }
1089 #endif
1090
1091 #ifdef DEBUG
1092 const char *
cstrerror(int errnum)1093 cstrerror(int errnum)
1094 {
1095 #undef strerror
1096 return (strerror(errnum));
1097 #define strerror dontuse_strerror /* poisoned */
1098 }
1099 #elif !HAVE_STRERROR
1100
1101 #if HAVE_SYS_ERRLIST
1102 #if !HAVE_SYS_ERRLIST_DECL
1103 extern const int sys_nerr;
1104 extern const char * const sys_errlist[];
1105 #endif
1106 #endif
1107
1108 const char *
cstrerror(int errnum)1109 cstrerror(int errnum)
1110 {
1111 /* "Unknown error: " + sign + rough estimate + NUL */
1112 static char errbuf[15 + 1 + (8 * sizeof(int) + 2) / 3 + 1];
1113
1114 #if HAVE_SYS_ERRLIST
1115 if (errnum > 0 && errnum < sys_nerr && sys_errlist[errnum])
1116 return (sys_errlist[errnum]);
1117 #endif
1118
1119 switch (errnum) {
1120 case 0:
1121 return ("Undefined error: 0");
1122 case EPERM:
1123 return ("Operation not permitted");
1124 case ENOENT:
1125 return ("No such file or directory");
1126 #ifdef ESRCH
1127 case ESRCH:
1128 return ("No such process");
1129 #endif
1130 #ifdef E2BIG
1131 case E2BIG:
1132 return ("Argument list too long");
1133 #endif
1134 case ENOEXEC:
1135 return ("Exec format error");
1136 case EBADF:
1137 return ("Bad file descriptor");
1138 #ifdef ENOMEM
1139 case ENOMEM:
1140 return ("Cannot allocate memory");
1141 #endif
1142 case EACCES:
1143 return ("Permission denied");
1144 case EEXIST:
1145 return ("File exists");
1146 case ENOTDIR:
1147 return ("Not a directory");
1148 #ifdef EINVAL
1149 case EINVAL:
1150 return ("Invalid argument");
1151 #endif
1152 #ifdef ELOOP
1153 case ELOOP:
1154 return ("Too many levels of symbolic links");
1155 #endif
1156 default:
1157 shf_snprintf(errbuf, sizeof(errbuf),
1158 "Unknown error: %d", errnum);
1159 return (errbuf);
1160 }
1161 }
1162 #endif
1163
1164 /* fast character classes */
1165 const uint32_t tpl_ctypes[128] = {
1166 /* 0x00 */
1167 CiNUL, CiCNTRL, CiCNTRL, CiCNTRL,
1168 CiCNTRL, CiCNTRL, CiCNTRL, CiCNTRL,
1169 CiCNTRL, CiTAB, CiNL, CiSPX,
1170 CiSPX, CiCR, CiCNTRL, CiCNTRL,
1171 /* 0x10 */
1172 CiCNTRL, CiCNTRL, CiCNTRL, CiCNTRL,
1173 CiCNTRL, CiCNTRL, CiCNTRL, CiCNTRL,
1174 CiCNTRL, CiCNTRL, CiCNTRL, CiCNTRL,
1175 CiCNTRL, CiCNTRL, CiCNTRL, CiCNTRL,
1176 /* 0x20 */
1177 CiSP, CiALIAS | CiVAR1, CiQC, CiHASH,
1178 CiSS, CiPERCT, CiQCL, CiQC,
1179 CiQCL, CiQCL, CiQCX | CiVAR1, CiPLUS,
1180 CiALIAS, CiMINUS, CiALIAS, CiQCM,
1181 /* 0x30 */
1182 CiOCTAL, CiOCTAL, CiOCTAL, CiOCTAL,
1183 CiOCTAL, CiOCTAL, CiOCTAL, CiOCTAL,
1184 CiDIGIT, CiDIGIT, CiCOLON, CiQCL,
1185 CiANGLE, CiEQUAL, CiANGLE, CiQUEST,
1186 /* 0x40 */
1187 CiALIAS | CiVAR1, CiUPPER | CiHEXLT,
1188 CiUPPER | CiHEXLT, CiUPPER | CiHEXLT,
1189 CiUPPER | CiHEXLT, CiUPPER | CiHEXLT,
1190 CiUPPER | CiHEXLT, CiUPPER,
1191 CiUPPER, CiUPPER, CiUPPER, CiUPPER,
1192 CiUPPER, CiUPPER, CiUPPER, CiUPPER,
1193 /* 0x50 */
1194 CiUPPER, CiUPPER, CiUPPER, CiUPPER,
1195 CiUPPER, CiUPPER, CiUPPER, CiUPPER,
1196 CiUPPER, CiUPPER, CiUPPER, CiQCX | CiBRACK,
1197 CiQCX, CiBRACK, CiQCM, CiUNDER,
1198 /* 0x60 */
1199 CiGRAVE, CiLOWER | CiHEXLT,
1200 CiLOWER | CiHEXLT, CiLOWER | CiHEXLT,
1201 CiLOWER | CiHEXLT, CiLOWER | CiHEXLT,
1202 CiLOWER | CiHEXLT, CiLOWER,
1203 CiLOWER, CiLOWER, CiLOWER, CiLOWER,
1204 CiLOWER, CiLOWER, CiLOWER, CiLOWER,
1205 /* 0x70 */
1206 CiLOWER, CiLOWER, CiLOWER, CiLOWER,
1207 CiLOWER, CiLOWER, CiLOWER, CiLOWER,
1208 CiLOWER, CiLOWER, CiLOWER, CiCURLY,
1209 CiQCL, CiCURLY, CiQCM, CiCNTRL
1210 };
1211
1212 void
set_ifs(const char * s)1213 set_ifs(const char *s)
1214 {
1215 #if defined(MKSH_EBCDIC) || defined(MKSH_FAUX_EBCDIC)
1216 int i = 256;
1217
1218 memset(ksh_ctypes, 0, sizeof(ksh_ctypes));
1219 while (i--)
1220 if (ebcdic_map[i] < 0x80U)
1221 ksh_ctypes[i] = tpl_ctypes[ebcdic_map[i]];
1222 #else
1223 memcpy(ksh_ctypes, tpl_ctypes, sizeof(tpl_ctypes));
1224 memset((char *)ksh_ctypes + sizeof(tpl_ctypes), '\0',
1225 sizeof(ksh_ctypes) - sizeof(tpl_ctypes));
1226 #endif
1227 ifs0 = *s;
1228 while (*s)
1229 ksh_ctypes[ord(*s++)] |= CiIFS;
1230 }
1231
1232 #if defined(MKSH_EBCDIC) || defined(MKSH_FAUX_EBCDIC)
1233 #include <locale.h>
1234
1235 /*
1236 * Many headaches with EBCDIC:
1237 * 1. There are numerous EBCDIC variants, and it is not feasible for us
1238 * to support them all. But we can support the EBCDIC code pages that
1239 * contain all (most?) of the characters in ASCII, and these
1240 * usually tend to agree on the code points assigned to the ASCII
1241 * subset. If you need a representative example, look at EBCDIC 1047,
1242 * which is first among equals in the IBM MVS development
1243 * environment: https://en.wikipedia.org/wiki/EBCDIC_1047
1244 * Unfortunately, the square brackets are not consistently mapped,
1245 * and for certain reasons, we need an unambiguous bijective
1246 * mapping between EBCDIC and "extended ASCII".
1247 * 2. Character ranges that are contiguous in ASCII, like the letters
1248 * in [A-Z], are broken up into segments (i.e. [A-IJ-RS-Z]), so we
1249 * can't implement e.g. islower() as { return c >= 'a' && c <= 'z'; }
1250 * because it will also return true for a handful of extraneous
1251 * characters (like the plus-minus sign at 0x8F in EBCDIC 1047, a
1252 * little after 'i'). But at least '_' is not one of these.
1253 * 3. The normal [0-9A-Za-z] characters are at codepoints beyond 0x80.
1254 * Not only do they require all 8 bits instead of 7, if chars are
1255 * signed, they will have negative integer values! Something like
1256 * (c - 'A') could actually become (c + 63)! Use the ord() macro to
1257 * ensure you're getting a value in [0, 255] (ORD for constants).
1258 * 4. '\n' is actually NL (0x15, U+0085) instead of LF (0x25, U+000A).
1259 * EBCDIC has a proper newline character instead of "emulating" one
1260 * with line feeds, although this is mapped to LF for our purposes.
1261 * 5. Note that it is possible to compile programs in ASCII mode on IBM
1262 * mainframe systems, using the -qascii option to the XL C compiler.
1263 * We can determine the build mode by looking at __CHARSET_LIB:
1264 * 0 == EBCDIC, 1 == ASCII
1265 */
1266
1267 void
ebcdic_init(void)1268 ebcdic_init(void)
1269 {
1270 int i = 256;
1271 unsigned char t;
1272 bool mapcache[256];
1273
1274 while (i--)
1275 ebcdic_rtt_toascii[i] = i;
1276 memset(ebcdic_rtt_fromascii, 0xFF, sizeof(ebcdic_rtt_fromascii));
1277 setlocale(LC_ALL, "");
1278 #ifdef MKSH_EBCDIC
1279 if (__etoa_l(ebcdic_rtt_toascii, 256) != 256) {
1280 write(2, "mksh: could not map EBCDIC to ASCII\n", 36);
1281 exit(255);
1282 }
1283 #endif
1284
1285 memset(mapcache, 0, sizeof(mapcache));
1286 i = 256;
1287 while (i--) {
1288 t = ebcdic_rtt_toascii[i];
1289 /* ensure unique round-trip capable mapping */
1290 if (mapcache[t]) {
1291 write(2, "mksh: duplicate EBCDIC to ASCII mapping\n", 40);
1292 exit(255);
1293 }
1294 /*
1295 * since there are 256 input octets, this also ensures
1296 * the other mapping direction is completely filled
1297 */
1298 mapcache[t] = true;
1299 /* fill the complete round-trip map */
1300 ebcdic_rtt_fromascii[t] = i;
1301 /*
1302 * Only use the converted value if it's in the range
1303 * [0x00; 0x7F], which I checked; the "extended ASCII"
1304 * characters can be any encoding, not just Latin1,
1305 * and the C1 control characters other than NEL are
1306 * hopeless, but we map EBCDIC NEL to ASCII LF so we
1307 * cannot even use C1 NEL.
1308 * If ever we map to UCS, bump the table width to
1309 * an unsigned int, and or the raw unconverted EBCDIC
1310 * values with 0x01000000 instead.
1311 */
1312 if (t < 0x80U)
1313 ebcdic_map[i] = (unsigned short)ord(t);
1314 else
1315 ebcdic_map[i] = (unsigned short)(0x100U | ord(i));
1316 }
1317 if (ebcdic_rtt_toascii[0] || ebcdic_rtt_fromascii[0] || ebcdic_map[0]) {
1318 write(2, "mksh: NUL not at position 0\n", 28);
1319 exit(255);
1320 }
1321 }
1322 #endif
1323