1 /*
2  *  Shell file I/O routines
3  */
4 
5 #include "sh.h"
6 #include "ksh_stat.h"
7 #include "ksh_limval.h"
8 
9 
10 /* flags to shf_emptybuf() */
11 #define EB_READSW	0x01	/* about to switch to reading */
12 #define EB_GROW		0x02	/* grow buffer if necessary (STRING+DYNAMIC) */
13 
14 /*
15  * Replacement stdio routines.  Stdio is too flakey on too many machines
16  * to be useful when you have multiple processes using the same underlying
17  * file descriptors.
18  */
19 
20 static int	shf_fillbuf	ARGS((struct shf *shf));
21 static int	shf_emptybuf	ARGS((struct shf *shf, int flags));
22 
23 /* Open a file.  First three args are for open(), last arg is flags for
24  * this package.  Returns NULL if file could not be opened, or if a dup
25  * fails.
26  */
27 struct shf *
shf_open(name,oflags,mode,sflags)28 shf_open(name, oflags, mode, sflags)
29 	const char *name;
30 	int oflags;
31 	int mode;
32 	int sflags;
33 {
34 	struct shf *shf;
35 	int bsize = sflags & SHF_UNBUF ? (sflags & SHF_RD ? 1 : 0) : SHF_BSIZE;
36 	int fd;
37 
38 	/* Done before open so if alloca fails, fd won't be lost. */
39 	shf = (struct shf *) alloc(sizeof(struct shf) + bsize, ATEMP);
40 	shf->areap = ATEMP;
41 	shf->buf = (unsigned char *) &shf[1];
42 	shf->bsize = bsize;
43 	shf->flags = SHF_ALLOCS;
44 	/* Rest filled in by reopen. */
45 
46 	fd = open(name, oflags, mode);
47 	if (fd < 0) {
48 		afree(shf, shf->areap);
49 		return NULL;
50 	}
51 	if ((sflags & SHF_MAPHI) && fd < FDBASE) {
52 		int nfd;
53 
54 		nfd = ksh_dupbase(fd, FDBASE);
55 		close(fd);
56 		if (nfd < 0) {
57 			afree(shf, shf->areap);
58 			return NULL;
59 		}
60 		fd = nfd;
61 	}
62 	sflags &= ~SHF_ACCMODE;
63 	sflags |= (oflags & O_ACCMODE) == O_RDONLY ? SHF_RD
64 		  : ((oflags & O_ACCMODE) == O_WRONLY ? SHF_WR
65 		     : SHF_RDWR);
66 
67 	return shf_reopen(fd, sflags, shf);
68 }
69 
70 /* Set up the shf structure for a file descriptor.  Doesn't fail. */
71 struct shf *
shf_fdopen(fd,sflags,shf)72 shf_fdopen(fd, sflags, shf)
73 	int fd;
74 	int sflags;
75 	struct shf *shf;
76 {
77 	int bsize = sflags & SHF_UNBUF ? (sflags & SHF_RD ? 1 : 0) : SHF_BSIZE;
78 
79 	/* use fcntl() to figure out correct read/write flags */
80 	if (sflags & SHF_GETFL) {
81 		int flags = fcntl(fd, F_GETFL, 0);
82 
83 		if (flags < 0)
84 			/* will get an error on first read/write */
85 			sflags |= SHF_RDWR;
86 		else
87 			switch (flags & O_ACCMODE) {
88 			case O_RDONLY: sflags |= SHF_RD; break;
89 			case O_WRONLY: sflags |= SHF_WR; break;
90 			case O_RDWR: sflags |= SHF_RDWR; break;
91 			}
92 	}
93 
94 	if (!(sflags & (SHF_RD | SHF_WR)))
95 		internal_errorf(1, "shf_fdopen: missing read/write");
96 
97 	if (shf) {
98 		if (bsize) {
99 			shf->buf = (unsigned char *) alloc(bsize, ATEMP);
100 			sflags |= SHF_ALLOCB;
101 		} else
102 			shf->buf = (unsigned char *) 0;
103 	} else {
104 		shf = (struct shf *) alloc(sizeof(struct shf) + bsize, ATEMP);
105 		shf->buf = (unsigned char *) &shf[1];
106 		sflags |= SHF_ALLOCS;
107 	}
108 	shf->areap = ATEMP;
109 	shf->fd = fd;
110 	shf->rp = shf->wp = shf->buf;
111 	shf->rnleft = 0;
112 	shf->rbsize = bsize;
113 	shf->wnleft = 0; /* force call to shf_emptybuf() */
114 	shf->wbsize = sflags & SHF_UNBUF ? 0 : bsize;
115 	shf->flags = sflags;
116 	shf->errno_ = 0;
117 	shf->bsize = bsize;
118 	if (sflags & SHF_CLEXEC)
119 		fd_clexec(fd);
120 	return shf;
121 }
122 
123 /* Set up an existing shf (and buffer) to use the given fd */
124 struct shf *
shf_reopen(fd,sflags,shf)125 shf_reopen(fd, sflags, shf)
126 	int fd;
127 	int sflags;
128 	struct shf *shf;
129 {
130 	int bsize = sflags & SHF_UNBUF ? (sflags & SHF_RD ? 1 : 0) : SHF_BSIZE;
131 
132 	/* use fcntl() to figure out correct read/write flags */
133 	if (sflags & SHF_GETFL) {
134 		int flags = fcntl(fd, F_GETFL, 0);
135 
136 		if (flags < 0)
137 			/* will get an error on first read/write */
138 			sflags |= SHF_RDWR;
139 		else
140 			switch (flags & O_ACCMODE) {
141 			case O_RDONLY: sflags |= SHF_RD; break;
142 			case O_WRONLY: sflags |= SHF_WR; break;
143 			case O_RDWR: sflags |= SHF_RDWR; break;
144 			}
145 	}
146 
147 	if (!(sflags & (SHF_RD | SHF_WR)))
148 		internal_errorf(1, "shf_reopen: missing read/write");
149 	if (!shf || !shf->buf || shf->bsize < bsize)
150 		internal_errorf(1, "shf_reopen: bad shf/buf/bsize");
151 
152 	/* assumes shf->buf and shf->bsize already set up */
153 	shf->fd = fd;
154 	shf->rp = shf->wp = shf->buf;
155 	shf->rnleft = 0;
156 	shf->rbsize = bsize;
157 	shf->wnleft = 0; /* force call to shf_emptybuf() */
158 	shf->wbsize = sflags & SHF_UNBUF ? 0 : bsize;
159 	shf->flags = (shf->flags & (SHF_ALLOCS | SHF_ALLOCB)) | sflags;
160 	shf->errno_ = 0;
161 	if (sflags & SHF_CLEXEC)
162 		fd_clexec(fd);
163 	return shf;
164 }
165 
166 /* Open a string for reading or writing.  If reading, bsize is the number
167  * of bytes that can be read.  If writing, bsize is the maximum number of
168  * bytes that can be written.  If shf is not null, it is filled in and
169  * returned, if it is null, shf is allocated.  If writing and buf is null
170  * and SHF_DYNAMIC is set, the buffer is allocated (if bsize > 0, it is
171  * used for the initial size).  Doesn't fail.
172  * When writing, a byte is reserved for a trailing null - see shf_sclose().
173  */
174 struct shf *
shf_sopen(buf,bsize,sflags,shf)175 shf_sopen(buf, bsize, sflags, shf)
176 	char *buf;
177 	int bsize;
178 	int sflags;
179 	struct shf *shf;
180 {
181 	/* can't have a read+write string */
182 	if (!(sflags & (SHF_RD | SHF_WR))
183 	    || (sflags & (SHF_RD | SHF_WR)) == (SHF_RD | SHF_WR))
184 		internal_errorf(1, "shf_sopen: flags 0x%x", sflags);
185 
186 	if (!shf) {
187 		shf = (struct shf *) alloc(sizeof(struct shf), ATEMP);
188 		sflags |= SHF_ALLOCS;
189 	}
190 	shf->areap = ATEMP;
191 	if (!buf && (sflags & SHF_WR) && (sflags & SHF_DYNAMIC)) {
192 		if (bsize <= 0)
193 			bsize = 64;
194 		sflags |= SHF_ALLOCB;
195 		buf = alloc(bsize, shf->areap);
196 	}
197 	shf->fd = -1;
198 	shf->buf = shf->rp = shf->wp = (unsigned char *) buf;
199 	shf->rnleft = bsize;
200 	shf->rbsize = bsize;
201 	shf->wnleft = bsize - 1;	/* space for a '\0' */
202 	shf->wbsize = bsize;
203 	shf->flags = sflags | SHF_STRING;
204 	shf->errno_ = 0;
205 	shf->bsize = bsize;
206 
207 	return shf;
208 }
209 
210 /* Flush and close file descriptor, free the shf structure */
211 int
shf_close(shf)212 shf_close(shf)
213 	struct shf *shf;
214 {
215 	int ret = 0;
216 
217 	if (shf->fd >= 0) {
218 		ret = shf_flush(shf);
219 		if (close(shf->fd) < 0)
220 			ret = EOF;
221 	}
222 	if (shf->flags & SHF_ALLOCS)
223 		afree(shf, shf->areap);
224 	else if (shf->flags & SHF_ALLOCB)
225 		afree(shf->buf, shf->areap);
226 
227 	return ret;
228 }
229 
230 /* Flush and close file descriptor, don't free file structure */
231 int
shf_fdclose(shf)232 shf_fdclose(shf)
233 	struct shf *shf;
234 {
235 	int ret = 0;
236 
237 	if (shf->fd >= 0) {
238 		ret = shf_flush(shf);
239 		if (close(shf->fd) < 0)
240 			ret = EOF;
241 		shf->rnleft = 0;
242 		shf->rp = shf->buf;
243 		shf->wnleft = 0;
244 		shf->fd = -1;
245 	}
246 
247 	return ret;
248 }
249 
250 /* Close a string - if it was opened for writing, it is null terminated;
251  * returns a pointer to the string and frees shf if it was allocated
252  * (does not free string if it was allocated).
253  */
254 char *
shf_sclose(shf)255 shf_sclose(shf)
256 	struct shf *shf;
257 {
258 	unsigned char *s = shf->buf;
259 
260 	/* null terminate */
261 	if (shf->flags & SHF_WR) {
262 		shf->wnleft++;
263 		shf_putc('\0', shf);
264 	}
265 	if (shf->flags & SHF_ALLOCS)
266 		afree(shf, shf->areap);
267 	return (char *) s;
268 }
269 
270 /* Flush and free file structure, don't close file descriptor */
271 int
shf_finish(shf)272 shf_finish(shf)
273 	struct shf *shf;
274 {
275 	int ret = 0;
276 
277 	if (shf->fd >= 0)
278 		ret = shf_flush(shf);
279 	if (shf->flags & SHF_ALLOCS)
280 		afree(shf, shf->areap);
281 	else if (shf->flags & SHF_ALLOCB)
282 		afree(shf->buf, shf->areap);
283 
284 	return ret;
285 }
286 
287 /* Un-read what has been read but not examined, or write what has been
288  * buffered.  Returns 0 for success, EOF for (write) error.
289  */
290 int
shf_flush(shf)291 shf_flush(shf)
292 	struct shf *shf;
293 {
294 	if (shf->flags & SHF_STRING)
295 		return (shf->flags & SHF_WR) ? EOF : 0;
296 
297 	if (shf->fd < 0)
298 		internal_errorf(1, "shf_flush: no fd");
299 
300 	if (shf->flags & SHF_ERROR) {
301 		errno = shf->errno_;
302 		return EOF;
303 	}
304 
305 	if (shf->flags & SHF_READING) {
306 		shf->flags &= ~(SHF_EOF | SHF_READING);
307 		if (shf->rnleft > 0) {
308 			lseek(shf->fd, (off_t) -shf->rnleft, 1);
309 			shf->rnleft = 0;
310 			shf->rp = shf->buf;
311 		}
312 		return 0;
313 	} else if (shf->flags & SHF_WRITING)
314 		return shf_emptybuf(shf, 0);
315 
316 	return 0;
317 }
318 
319 /* Write out any buffered data.  If currently reading, flushes the read
320  * buffer.  Returns 0 for success, EOF for (write) error.
321  */
322 static int
shf_emptybuf(shf,flags)323 shf_emptybuf(shf, flags)
324 	struct shf *shf;
325 	int flags;
326 {
327 	int ret = 0;
328 
329 	if (!(shf->flags & SHF_STRING) && shf->fd < 0)
330 		internal_errorf(1, "shf_emptybuf: no fd");
331 
332 	if (shf->flags & SHF_ERROR) {
333 		errno = shf->errno_;
334 		return EOF;
335 	}
336 
337 	if (shf->flags & SHF_READING) {
338 		if (flags & EB_READSW) /* doesn't happen */
339 			return 0;
340 		ret = shf_flush(shf);
341 		shf->flags &= ~SHF_READING;
342 	}
343 	if (shf->flags & SHF_STRING) {
344 		unsigned char	*nbuf;
345 
346 		/* Note that we assume SHF_ALLOCS is not set if SHF_ALLOCB
347 		 * is set... (changing the shf pointer could cause problems)
348 		 */
349 		if (!(flags & EB_GROW) || !(shf->flags & SHF_DYNAMIC)
350 		    || !(shf->flags & SHF_ALLOCB))
351 			return EOF;
352 		/* allocate more space for buffer */
353 		nbuf = (unsigned char *) aresize(shf->buf, shf->wbsize * 2,
354 						shf->areap);
355 		shf->rp = nbuf + (shf->rp - shf->buf);
356 		shf->wp = nbuf + (shf->wp - shf->buf);
357 		shf->rbsize += shf->wbsize;
358 		shf->wnleft += shf->wbsize;
359 		shf->wbsize *= 2;
360 		shf->buf = nbuf;
361 	} else {
362 		if (shf->flags & SHF_WRITING) {
363 			int ntowrite = shf->wp - shf->buf;
364 			unsigned char *buf = shf->buf;
365 			int n;
366 
367 			while (ntowrite > 0) {
368 				n = write(shf->fd, buf, ntowrite);
369 				if (n < 0) {
370 					if (errno == EINTR
371 					    && !(shf->flags & SHF_INTERRUPT))
372 						continue;
373 					shf->flags |= SHF_ERROR;
374 					shf->errno_ = errno;
375 					shf->wnleft = 0;
376 					if (buf != shf->buf) {
377 						/* allow a second flush
378 						 * to work */
379 						memmove(shf->buf, buf,
380 							ntowrite);
381 						shf->wp = shf->buf + ntowrite;
382 					}
383 					return EOF;
384 				}
385 				buf += n;
386 				ntowrite -= n;
387 			}
388 			if (flags & EB_READSW) {
389 				shf->wp = shf->buf;
390 				shf->wnleft = 0;
391 				shf->flags &= ~SHF_WRITING;
392 				return 0;
393 			}
394 		}
395 		shf->wp = shf->buf;
396 		shf->wnleft = shf->wbsize;
397 	}
398 	shf->flags |= SHF_WRITING;
399 
400 	return ret;
401 }
402 
403 /* Fill up a read buffer.  Returns EOF for a read error, 0 otherwise. */
404 static int
shf_fillbuf(shf)405 shf_fillbuf(shf)
406 	struct shf *shf;
407 {
408 	if (shf->flags & SHF_STRING)
409 		return 0;
410 
411 	if (shf->fd < 0)
412 		internal_errorf(1, "shf_fillbuf: no fd");
413 
414 	if (shf->flags & (SHF_EOF | SHF_ERROR)) {
415 		if (shf->flags & SHF_ERROR)
416 			errno = shf->errno_;
417 		return EOF;
418 	}
419 
420 	if ((shf->flags & SHF_WRITING) && shf_emptybuf(shf, EB_READSW) == EOF)
421 		return EOF;
422 
423 	shf->flags |= SHF_READING;
424 
425 	shf->rp = shf->buf;
426 	while (1) {
427 		shf->rnleft = blocking_read(shf->fd, (char *) shf->buf,
428 					    shf->rbsize);
429 		if (shf->rnleft < 0 && errno == EINTR
430 		    && !(shf->flags & SHF_INTERRUPT))
431 			continue;
432 		break;
433 	}
434 	if (shf->rnleft <= 0) {
435 		if (shf->rnleft < 0) {
436 			shf->flags |= SHF_ERROR;
437 			shf->errno_ = errno;
438 			shf->rnleft = 0;
439 			shf->rp = shf->buf;
440 			return EOF;
441 		}
442 		shf->flags |= SHF_EOF;
443 	}
444 	return 0;
445 }
446 
447 /* Seek to a new position in the file.  If writing, flushes the buffer
448  * first.  If reading, optimizes small relative seeks that stay inside the
449  * buffer.  Returns 0 for success, EOF otherwise.
450  */
451 int
shf_seek(shf,where,from)452 shf_seek(shf, where, from)
453 	struct shf *shf;
454 	off_t where;
455 	int from;
456 {
457 	if (shf->fd < 0) {
458 		errno = EINVAL;
459 		return EOF;
460 	}
461 
462 	if (shf->flags & SHF_ERROR) {
463 		errno = shf->errno_;
464 		return EOF;
465 	}
466 
467 	if ((shf->flags & SHF_WRITING) && shf_emptybuf(shf, EB_READSW) == EOF)
468 		return EOF;
469 
470 	if (shf->flags & SHF_READING) {
471 		if (from == SEEK_CUR &&
472 				(where < 0 ?
473 					-where >= shf->rbsize - shf->rnleft :
474 					where < shf->rnleft)) {
475 			shf->rnleft -= where;
476 			shf->rp += where;
477 			return 0;
478 		}
479 		shf->rnleft = 0;
480 		shf->rp = shf->buf;
481 	}
482 
483 	shf->flags &= ~(SHF_EOF | SHF_READING | SHF_WRITING);
484 
485 	if (lseek(shf->fd, where, from) < 0) {
486 		shf->errno_ = errno;
487 		shf->flags |= SHF_ERROR;
488 		return EOF;
489 	}
490 
491 	return 0;
492 }
493 
494 
495 /* Read a buffer from shf.  Returns the number of bytes read into buf,
496  * if no bytes were read, returns 0 if end of file was seen, EOF if
497  * a read error occurred.
498  */
499 int
shf_read(buf,bsize,shf)500 shf_read(buf, bsize, shf)
501 	char *buf;
502 	int bsize;
503 	struct shf *shf;
504 {
505 	int orig_bsize = bsize;
506 	int ncopy;
507 
508 	if (!(shf->flags & SHF_RD))
509 		internal_errorf(1, "shf_read: flags %x", shf->flags);
510 
511 	if (bsize <= 0)
512 		internal_errorf(1, "shf_read: bsize %d", bsize);
513 
514 	while (bsize > 0) {
515 		if (shf->rnleft == 0
516 		    && (shf_fillbuf(shf) == EOF || shf->rnleft == 0))
517 			break;
518 		ncopy = shf->rnleft;
519 		if (ncopy > bsize)
520 			ncopy = bsize;
521 		memcpy(buf, shf->rp, ncopy);
522 		buf += ncopy;
523 		bsize -= ncopy;
524 		shf->rp += ncopy;
525 		shf->rnleft -= ncopy;
526 	}
527 	/* Note: fread(3S) returns 0 for errors - this doesn't */
528 	return orig_bsize == bsize ? (shf_error(shf) ? EOF : 0)
529 				   : orig_bsize - bsize;
530 }
531 
532 /* Read up to a newline or EOF.  The newline is put in buf; buf is always
533  * null terminated.  Returns NULL on read error or if nothing was read before
534  * end of file, returns a pointer to the null byte in buf otherwise.
535  */
536 char *
shf_getse(buf,bsize,shf)537 shf_getse(buf, bsize, shf)
538 	char *buf;
539 	int bsize;
540 	struct shf *shf;
541 {
542 	unsigned char *end;
543 	int ncopy;
544 	char *orig_buf = buf;
545 
546 	if (!(shf->flags & SHF_RD))
547 		internal_errorf(1, "shf_getse: flags %x", shf->flags);
548 
549 	if (bsize <= 0)
550 		return (char *) 0;
551 
552 	--bsize;	/* save room for null */
553 	do {
554 		if (shf->rnleft == 0) {
555 			if (shf_fillbuf(shf) == EOF)
556 				return NULL;
557 			if (shf->rnleft == 0) {
558 				*buf = '\0';
559 				return buf == orig_buf ? NULL : buf;
560 			}
561 		}
562 		end = (unsigned char *) memchr((char *) shf->rp, '\n',
563 					     shf->rnleft);
564 		ncopy = end ? end - shf->rp + 1 : shf->rnleft;
565 		if (ncopy > bsize)
566 			ncopy = bsize;
567 		memcpy(buf, (char *) shf->rp, ncopy);
568 		shf->rp += ncopy;
569 		shf->rnleft -= ncopy;
570 		buf += ncopy;
571 		bsize -= ncopy;
572 #ifdef OS2
573 		if (end && buf > orig_buf + 1 && buf[-2] == '\r') {
574 			buf--;
575 			bsize++;
576 			buf[-1] = '\n';
577 		}
578 #endif
579 
580 	} while (!end && bsize);
581 	*buf = '\0';
582 	return buf;
583 }
584 
585 /* Returns the char read.  Returns EOF for error and end of file. */
586 int
shf_getchar(shf)587 shf_getchar(shf)
588 	struct shf *shf;
589 {
590 	if (!(shf->flags & SHF_RD))
591 		internal_errorf(1, "shf_getchar: flags %x", shf->flags);
592 
593 	if (shf->rnleft == 0 && (shf_fillbuf(shf) == EOF || shf->rnleft == 0))
594 		return EOF;
595 	--shf->rnleft;
596 	return *shf->rp++;
597 }
598 
599 /* Put a character back in the input stream.  Returns the character if
600  * successful, EOF if there is no room.
601  */
602 int
shf_ungetc(c,shf)603 shf_ungetc(c, shf)
604 	int c;
605 	struct shf *shf;
606 {
607 	if (!(shf->flags & SHF_RD))
608 		internal_errorf(1, "shf_ungetc: flags %x", shf->flags);
609 
610 	if ((shf->flags & SHF_ERROR) || c == EOF
611 	    || (shf->rp == shf->buf && shf->rnleft))
612 		return EOF;
613 
614 	if ((shf->flags & SHF_WRITING) && shf_emptybuf(shf, EB_READSW) == EOF)
615 		return EOF;
616 
617 	if (shf->rp == shf->buf)
618 		shf->rp = shf->buf + shf->rbsize;
619 	if (shf->flags & SHF_STRING) {
620 		/* Can unget what was read, but not something different - we
621 		 * don't want to modify a string.
622 		 */
623 		if (shf->rp[-1] != c)
624 			return EOF;
625 		shf->flags &= ~SHF_EOF;
626 		shf->rp--;
627 		shf->rnleft++;
628 		return c;
629 	}
630 	shf->flags &= ~SHF_EOF;
631 	*--(shf->rp) = c;
632 	shf->rnleft++;
633 	return c;
634 }
635 
636 /* Write a character.  Returns the character if successful, EOF if
637  * the char could not be written.
638  */
639 int
shf_putchar(c,shf)640 shf_putchar(c, shf)
641 	int c;
642 	struct shf *shf;
643 {
644 	if (!(shf->flags & SHF_WR))
645 		internal_errorf(1, "shf_putchar: flags %x", shf->flags);
646 
647 	if (c == EOF)
648 		return EOF;
649 
650 	if (shf->flags & SHF_UNBUF) {
651 		char cc = c;
652 		int n;
653 
654 		if (shf->fd < 0)
655 			internal_errorf(1, "shf_putchar: no fd");
656 		if (shf->flags & SHF_ERROR) {
657 			errno = shf->errno_;
658 			return EOF;
659 		}
660 		while ((n = write(shf->fd, &cc, 1)) != 1)
661 			if (n < 0) {
662 				if (errno == EINTR
663 				    && !(shf->flags & SHF_INTERRUPT))
664 					continue;
665 				shf->flags |= SHF_ERROR;
666 				shf->errno_ = errno;
667 				return EOF;
668 			}
669 	} else {
670 		/* Flush deals with strings and sticky errors */
671 		if (shf->wnleft == 0 && shf_emptybuf(shf, EB_GROW) == EOF)
672 			return EOF;
673 		shf->wnleft--;
674 		*shf->wp++ = c;
675 	}
676 
677 	return c;
678 }
679 
680 /* Write a string.  Returns the length of the string if successful, EOF if
681  * the string could not be written.
682  */
683 int
shf_puts(s,shf)684 shf_puts(s, shf)
685 	const char *s;
686 	struct shf *shf;
687 {
688 	if (!s)
689 		return EOF;
690 
691 	return shf_write(s, strlen(s), shf);
692 }
693 
694 /* Write a buffer.  Returns nbytes if successful, EOF if there is an error. */
695 int
shf_write(buf,nbytes,shf)696 shf_write(buf, nbytes, shf)
697 	const char *buf;
698 	int nbytes;
699 	struct shf *shf;
700 {
701 	int orig_nbytes = nbytes;
702 	int n;
703 	int ncopy;
704 
705 	if (!(shf->flags & SHF_WR))
706 		internal_errorf(1, "shf_write: flags %x", shf->flags);
707 
708 	if (nbytes < 0)
709 		internal_errorf(1, "shf_write: nbytes %d", nbytes);
710 
711 	/* Don't buffer if buffer is empty and we're writting a large amount. */
712 	if ((ncopy = shf->wnleft)
713 	    && (shf->wp != shf->buf || nbytes < shf->wnleft))
714 	{
715 		if (ncopy > nbytes)
716 			ncopy = nbytes;
717 		memcpy(shf->wp, buf, ncopy);
718 		nbytes -= ncopy;
719 		buf += ncopy;
720 		shf->wp += ncopy;
721 		shf->wnleft -= ncopy;
722 	}
723 	if (nbytes > 0) {
724 		/* Flush deals with strings and sticky errors */
725 		if (shf_emptybuf(shf, EB_GROW) == EOF)
726 			return EOF;
727 		if (nbytes > shf->wbsize) {
728 			ncopy = nbytes;
729 			if (shf->wbsize)
730 				ncopy -= nbytes % shf->wbsize;
731 			nbytes -= ncopy;
732 			while (ncopy > 0) {
733 				n = write(shf->fd, buf, ncopy);
734 				if (n < 0) {
735 					if (errno == EINTR
736 					    && !(shf->flags & SHF_INTERRUPT))
737 						continue;
738 					shf->flags |= SHF_ERROR;
739 					shf->errno_ = errno;
740 					shf->wnleft = 0;
741 					/* Note: fwrite(3S) returns 0 for
742 					 * errors - this doesn't */
743 					return EOF;
744 				}
745 				buf += n;
746 				ncopy -= n;
747 			}
748 		}
749 		if (nbytes > 0) {
750 			memcpy(shf->wp, buf, nbytes);
751 			shf->wp += nbytes;
752 			shf->wnleft -= nbytes;
753 		}
754 	}
755 
756 	return orig_nbytes;
757 }
758 
759 int
760 #ifdef HAVE_PROTOTYPES
shf_fprintf(struct shf * shf,const char * fmt,...)761 shf_fprintf(struct shf *shf, const char *fmt, ...)
762 #else
763 shf_fprintf(shf, fmt, va_alist)
764 	struct shf *shf;
765 	const char *fmt;
766 	va_dcl
767 #endif
768 {
769 	va_list args;
770 	int n;
771 
772 	SH_VA_START(args, fmt);
773 	n = shf_vfprintf(shf, fmt, args);
774 	va_end(args);
775 
776 	return n;
777 }
778 
779 int
780 #ifdef HAVE_PROTOTYPES
shf_snprintf(char * buf,int bsize,const char * fmt,...)781 shf_snprintf(char *buf, int bsize, const char *fmt, ...)
782 #else
783 shf_snprintf(buf, bsize, fmt, va_alist)
784 	char *buf;
785 	int bsize;
786 	const char *fmt;
787 	va_dcl
788 #endif
789 {
790 	struct shf shf;
791 	va_list args;
792 	int n;
793 
794 	if (!buf || bsize <= 0)
795 		internal_errorf(1, "shf_snprintf: buf %lx, bsize %d",
796 			(long) buf, bsize);
797 
798 	shf_sopen(buf, bsize, SHF_WR, &shf);
799 	SH_VA_START(args, fmt);
800 	n = shf_vfprintf(&shf, fmt, args);
801 	va_end(args);
802 	shf_sclose(&shf); /* null terminates */
803 	return n;
804 }
805 
806 char *
807 #ifdef HAVE_PROTOTYPES
shf_smprintf(const char * fmt,...)808 shf_smprintf(const char *fmt, ...)
809 #else
810 shf_smprintf(fmt, va_alist)
811 	char *fmt;
812 	va_dcl
813 #endif
814 {
815 	struct shf shf;
816 	va_list args;
817 
818 	shf_sopen((char *) 0, 0, SHF_WR|SHF_DYNAMIC, &shf);
819 	SH_VA_START(args, fmt);
820 	shf_vfprintf(&shf, fmt, args);
821 	va_end(args);
822 	return shf_sclose(&shf); /* null terminates */
823 }
824 
825 #undef FP  			/* if you want floating point stuff */
826 
827 #define BUF_SIZE	128
828 #define FPBUF_SIZE	(DMAXEXP+16)/* this must be >
829 				 *	MAX(DMAXEXP, log10(pow(2, DSIGNIF)))
830 				 *    + ceil(log10(DMAXEXP)) + 8 (I think).
831 				 * Since this is hard to express as a
832 				 * constant, just use a large buffer.
833 				 */
834 
835 /*
836  *	What kinda of machine we on?  Hopefully the C compiler will optimize
837  *  this out...
838  *
839  *	For shorts, we want sign extend for %d but not for %[oxu] - on 16 bit
840  *  machines it don't matter.  Assmumes C compiler has converted shorts to
841  *  ints before pushing them.
842  */
843 #define POP_INT(f, s, a) (((f) & FL_LONG) ?				\
844 				va_arg((a), unsigned long)		\
845 			    :						\
846 				(sizeof(int) < sizeof(long) ?		\
847 					((s) ?				\
848 						(long) va_arg((a), int)	\
849 					    :				\
850 						va_arg((a), unsigned))	\
851 				    :					\
852 					va_arg((a), unsigned)))
853 
854 #define ABIGNUM		32000	/* big numer that will fit in a short */
855 #define LOG2_10		3.321928094887362347870319429	/* log base 2 of 10 */
856 
857 #define	FL_HASH		0x001	/* `#' seen */
858 #define FL_PLUS		0x002	/* `+' seen */
859 #define FL_RIGHT	0x004	/* `-' seen */
860 #define FL_BLANK	0x008	/* ` ' seen */
861 #define FL_SHORT	0x010	/* `h' seen */
862 #define FL_LONG		0x020	/* `l' seen */
863 #define FL_ZERO		0x040	/* `0' seen */
864 #define FL_DOT		0x080	/* '.' seen */
865 #define FL_UPPER	0x100	/* format character was uppercase */
866 #define FL_NUMBER	0x200	/* a number was formated %[douxefg] */
867 
868 
869 #ifdef FP
870 #include <math.h>
871 
872 static double
my_ceil(d)873 my_ceil(d)
874 	double	d;
875 {
876 	double		i;
877 
878 	return d - modf(d, &i) + (d < 0 ? -1 : 1);
879 }
880 #endif /* FP */
881 
882 int
shf_vfprintf(shf,fmt,args)883 shf_vfprintf(shf, fmt, args)
884 	struct shf *shf;
885 	const char *fmt;
886 	va_list args;
887 {
888 	char		c, *s;
889 	int		UNINITIALIZED(tmp);
890 	int		field, precision;
891 	int		len;
892 	int		flags;
893 	unsigned long	lnum;
894 					/* %#o produces the longest output */
895 	char		numbuf[(BITS(long) + 2) / 3 + 1];
896 	/* this stuff for dealing with the buffer */
897 	int		nwritten = 0;
898 #ifdef FP
899 	/* should be in <math.h>
900 	 *  extern double frexp();
901 	 */
902 	extern char *ecvt();
903 
904 	double		fpnum;
905 	int		expo, decpt;
906 	char		style;
907 	char		fpbuf[FPBUF_SIZE];
908 #endif /* FP */
909 
910 	if (!fmt)
911 		return 0;
912 
913 	while ((c = *fmt++)) {
914 		if (c != '%') {
915 			shf_putc(c, shf);
916 			nwritten++;
917 			continue;
918 		}
919 		/*
920 		 *	This will accept flags/fields in any order - not
921 		 *  just the order specified in printf(3), but this is
922 		 *  the way _doprnt() seems to work (on bsd and sysV).
923 		 *  The only resriction is that the format character must
924 		 *  come last :-).
925 		 */
926 		flags = field = precision = 0;
927 		for ( ; (c = *fmt++) ; ) {
928 			switch (c) {
929 			case '#':
930 				flags |= FL_HASH;
931 				continue;
932 
933 			case '+':
934 				flags |= FL_PLUS;
935 				continue;
936 
937 			case '-':
938 				flags |= FL_RIGHT;
939 				continue;
940 
941 			case ' ':
942 				flags |= FL_BLANK;
943 				continue;
944 
945 			case '0':
946 				if (!(flags & FL_DOT))
947 					flags |= FL_ZERO;
948 				continue;
949 
950 			case '.':
951 				flags |= FL_DOT;
952 				precision = 0;
953 				continue;
954 
955 			case '*':
956 				tmp = va_arg(args, int);
957 				if (flags & FL_DOT)
958 					precision = tmp;
959 				else if ((field = tmp) < 0) {
960 					field = -field;
961 					flags |= FL_RIGHT;
962 				}
963 				continue;
964 
965 			case 'l':
966 				flags |= FL_LONG;
967 				continue;
968 
969 			case 'h':
970 				flags |= FL_SHORT;
971 				continue;
972 			}
973 			if (digit(c)) {
974 				tmp = c - '0';
975 				while (c = *fmt++, digit(c))
976 					tmp = tmp * 10 + c - '0';
977 				--fmt;
978 				if (tmp < 0)		/* overflow? */
979 					tmp = 0;
980 				if (flags & FL_DOT)
981 					precision = tmp;
982 				else
983 					field = tmp;
984 				continue;
985 			}
986 			break;
987 		}
988 
989 		if (precision < 0)
990 			precision = 0;
991 
992 		if (!c)		/* nasty format */
993 			break;
994 
995 		if (c >= 'A' && c <= 'Z') {
996 			flags |= FL_UPPER;
997 			c = c - 'A' + 'a';
998 		}
999 
1000 		switch (c) {
1001 		case 'p': /* pointer */
1002 			flags &= ~(FL_LONG | FL_SHORT);
1003 			if (sizeof(char *) > sizeof(int))
1004 				flags |= FL_LONG; /* hope it fits.. */
1005 			/* aaahhh... */
1006 		case 'd':
1007 		case 'i':
1008 		case 'o':
1009 		case 'u':
1010 		case 'x':
1011 			flags |= FL_NUMBER;
1012 			s = &numbuf[sizeof(numbuf)];
1013 			lnum = POP_INT(flags, c == 'd', args);
1014 			switch (c) {
1015 			case 'd':
1016 			case 'i':
1017 				if (0 > (long) lnum)
1018 					lnum = - (long) lnum, tmp = 1;
1019 				else
1020 					tmp = 0;
1021 				/* aaahhhh..... */
1022 
1023 			case 'u':
1024 				do {
1025 					*--s = lnum % 10 + '0';
1026 					lnum /= 10;
1027 				} while (lnum);
1028 
1029 				if (c != 'u') {
1030 					if (tmp)
1031 						*--s = '-';
1032 					else if (flags & FL_PLUS)
1033 						*--s = '+';
1034 					else if (flags & FL_BLANK)
1035 						*--s = ' ';
1036 				}
1037 				break;
1038 
1039 			case 'o':
1040 				do {
1041 					*--s = (lnum & 0x7) + '0';
1042 					lnum >>= 3;
1043 				} while (lnum);
1044 
1045 				if ((flags & FL_HASH) && *s != '0')
1046 					*--s = '0';
1047 				break;
1048 
1049 			case 'p':
1050 			case 'x':
1051 			    {
1052 				const char *digits = (flags & FL_UPPER) ?
1053 						  "0123456789ABCDEF"
1054 						: "0123456789abcdef";
1055 				do {
1056 					*--s = digits[lnum & 0xf];
1057 					lnum >>= 4;
1058 				} while (lnum);
1059 
1060 				if (flags & FL_HASH) {
1061 					*--s = (flags & FL_UPPER) ? 'X' : 'x';
1062 					*--s = '0';
1063 				}
1064 			    }
1065 			}
1066 			len = &numbuf[sizeof(numbuf)] - s;
1067 			if (flags & FL_DOT) {
1068 				if (precision > len) {
1069 					field = precision;
1070 					flags |= FL_ZERO;
1071 				} else
1072 					precision = len; /* no loss */
1073 			}
1074 			break;
1075 
1076 #ifdef FP
1077 		case 'e':
1078 		case 'g':
1079 		case 'f':
1080 		    {
1081 			char *p;
1082 
1083 			/*
1084 			 *	This could proabably be done better,
1085 			 *  but it seems to work.  Note that gcvt()
1086 			 *  is not used, as you cannot tell it to
1087 			 *  not strip the zeros.
1088 			 */
1089 			flags |= FL_NUMBER;
1090 			if (!(flags & FL_DOT))
1091 				precision = 6;	/* default */
1092 			/*
1093 			 *	Assumes doubles are pushed on
1094 			 *  the stack.  If this is not so, then
1095 			 *  FL_LONG/FL_SHORT should be checked.
1096 			 */
1097 			fpnum = va_arg(args, double);
1098 			s = fpbuf;
1099 			style = c;
1100 			/*
1101 			 *  This is the same as
1102 			 *	expo = ceil(log10(fpnum))
1103 			 *  but doesn't need -lm.  This is an
1104 			 *  aproximation as expo is rounded up.
1105 			 */
1106 			(void) frexp(fpnum, &expo);
1107 			expo = my_ceil(expo / LOG2_10);
1108 
1109 			if (expo < 0)
1110 				expo = 0;
1111 
1112 			p = ecvt(fpnum, precision + 1 + expo,
1113 				 &decpt, &tmp);
1114 			if (c == 'g') {
1115 				if (decpt < -4 || decpt > precision)
1116 					style = 'e';
1117 				else
1118 					style = 'f';
1119 				if (decpt > 0 && (precision -= decpt) < 0)
1120 					precision = 0;
1121 			}
1122 			if (tmp)
1123 				*s++ = '-';
1124 			else if (flags & FL_PLUS)
1125 				*s++ = '+';
1126 			else if (flags & FL_BLANK)
1127 				*s++ = ' ';
1128 
1129 			if (style == 'e')
1130 				*s++ = *p++;
1131 			else {
1132 				if (decpt > 0) {
1133 					/* Overflow check - should
1134 					 * never have this problem.
1135 					 */
1136 					if (decpt >
1137 						&fpbuf[sizeof(fpbuf)]
1138 							- s - 8)
1139 						decpt =
1140 						 &fpbuf[sizeof(fpbuf)]
1141 							- s - 8;
1142 					(void) memcpy(s, p, decpt);
1143 					s += decpt;
1144 					p += decpt;
1145 				} else
1146 					*s++ = '0';
1147 			}
1148 
1149 			/* print the fraction? */
1150 			if (precision > 0) {
1151 				*s++ = '.';
1152 				/* Overflow check - should
1153 				 * never have this problem.
1154 				 */
1155 				if (precision > &fpbuf[sizeof(fpbuf)]
1156 							- s - 7)
1157 					precision =
1158 						&fpbuf[sizeof(fpbuf)]
1159 						- s - 7;
1160 				for (tmp = decpt;  tmp++ < 0 &&
1161 					    precision > 0 ; precision--)
1162 					*s++ = '0';
1163 				tmp = strlen(p);
1164 				if (precision > tmp)
1165 					precision = tmp;
1166 				/* Overflow check - should
1167 				 * never have this problem.
1168 				 */
1169 				if (precision > &fpbuf[sizeof(fpbuf)]
1170 							- s - 7)
1171 					precision =
1172 						&fpbuf[sizeof(fpbuf)]
1173 						- s - 7;
1174 				(void) memcpy(s, p, precision);
1175 				s += precision;
1176 				/*
1177 				 *	`g' format strips trailing
1178 				 *  zeros after the decimal.
1179 				 */
1180 				if (c == 'g' && !(flags & FL_HASH)) {
1181 					while (*--s == '0')
1182 						;
1183 					if (*s != '.')
1184 						s++;
1185 				}
1186 			} else if (flags & FL_HASH)
1187 				*s++ = '.';
1188 
1189 			if (style == 'e') {
1190 				*s++ = (flags & FL_UPPER) ? 'E' : 'e';
1191 				if (--decpt >= 0)
1192 					*s++ = '+';
1193 				else {
1194 					*s++ = '-';
1195 					decpt = -decpt;
1196 				}
1197 				p = &numbuf[sizeof(numbuf)];
1198 				for (tmp = 0; tmp < 2 || decpt ; tmp++) {
1199 					*--p = '0' + decpt % 10;
1200 					decpt /= 10;
1201 				}
1202 				tmp = &numbuf[sizeof(numbuf)] - p;
1203 				(void) memcpy(s, p, tmp);
1204 				s += tmp;
1205 			}
1206 
1207 			len = s - fpbuf;
1208 			s = fpbuf;
1209 			precision = len;
1210 			break;
1211 		    }
1212 #endif /* FP */
1213 
1214 		case 's':
1215 			if (!(s = va_arg(args, char *)))
1216 				s = "(null %s)";
1217 			len = strlen(s);
1218 			break;
1219 
1220 		case 'c':
1221 			flags &= ~FL_DOT;
1222 			numbuf[0] = va_arg(args, int);
1223 			s = numbuf;
1224 			len = 1;
1225 			break;
1226 
1227 		case '%':
1228 		default:
1229 			numbuf[0] = c;
1230 			s = numbuf;
1231 			len = 1;
1232 			break;
1233 		}
1234 
1235 		/*
1236 		 *	At this point s should point to a string that is
1237 		 *  to be formatted, and len should be the length of the
1238 		 *  string.
1239 		 */
1240 		if (!(flags & FL_DOT) || len < precision)
1241 			precision = len;
1242 		if (field > precision) {
1243 			field -= precision;
1244 			if (!(flags & FL_RIGHT)) {
1245 				field = -field;
1246 				/* skip past sign or 0x when padding with 0 */
1247 				if ((flags & FL_ZERO) && (flags & FL_NUMBER)) {
1248 					if (*s == '+' || *s == '-' || *s ==' ')
1249 					{
1250 						shf_putc(*s, shf);
1251 						s++;
1252 						precision--;
1253 						nwritten++;
1254 					} else if (*s == '0') {
1255 						shf_putc(*s, shf);
1256 						s++;
1257 						nwritten++;
1258 						if (--precision > 0 &&
1259 							(*s | 0x20) == 'x')
1260 						{
1261 							shf_putc(*s, shf);
1262 							s++;
1263 							precision--;
1264 							nwritten++;
1265 						}
1266 					}
1267 					c = '0';
1268 				} else
1269 					c = flags & FL_ZERO ? '0' : ' ';
1270 				if (field < 0) {
1271 					nwritten += -field;
1272 					for ( ; field < 0 ; field++)
1273 						shf_putc(c, shf);
1274 				}
1275 			} else
1276 				c = ' ';
1277 		} else
1278 			field = 0;
1279 
1280 		if (precision > 0) {
1281 			nwritten += precision;
1282 			for ( ; precision-- > 0 ; s++)
1283 				shf_putc(*s, shf);
1284 		}
1285 		if (field > 0) {
1286 			nwritten += field;
1287 			for ( ; field > 0 ; --field)
1288 				shf_putc(c, shf);
1289 		}
1290 	}
1291 
1292 	return shf_error(shf) ? EOF : nwritten;
1293 }
1294