GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: bin/ksh/shf.c Lines: 360 531 67.8 %
Date: 2016-12-06 Branches: 232 420 55.2 %

Line Branch Exec Source
1
/*	$OpenBSD: shf.c,v 1.31 2016/03/20 00:01:21 krw Exp $	*/
2
3
/*
4
 *  Shell file I/O routines
5
 */
6
7
#include <sys/stat.h>
8
9
#include <ctype.h>
10
#include <errno.h>
11
#include <fcntl.h>
12
#include <limits.h>
13
#include <stdio.h>
14
#include <string.h>
15
#include <unistd.h>
16
17
#include "sh.h"
18
19
/* flags to shf_emptybuf() */
20
#define EB_READSW	0x01	/* about to switch to reading */
21
#define EB_GROW		0x02	/* grow buffer if necessary (STRING+DYNAMIC) */
22
23
/*
24
 * Replacement stdio routines.  Stdio is too flakey on too many machines
25
 * to be useful when you have multiple processes using the same underlying
26
 * file descriptors.
27
 */
28
29
static int	shf_fillbuf(struct shf *);
30
static int	shf_emptybuf(struct shf *, int);
31
32
/* Open a file.  First three args are for open(), last arg is flags for
33
 * this package.  Returns NULL if file could not be opened, or if a dup
34
 * fails.
35
 */
36
struct shf *
37
shf_open(const char *name, int oflags, int mode, int sflags)
38
159
{
39
	struct shf *shf;
40
159
	int bsize = sflags & SHF_UNBUF ? (sflags & SHF_RD ? 1 : 0) : SHF_BSIZE;
41
	int fd;
42
43
	/* Done before open so if alloca fails, fd won't be lost. */
44
159
	shf = alloc(sizeof(struct shf) + bsize, ATEMP);
45
159
	shf->areap = ATEMP;
46
159
	shf->buf = (unsigned char *) &shf[1];
47
159
	shf->bsize = bsize;
48
159
	shf->flags = SHF_ALLOCS;
49
	/* Rest filled in by reopen. */
50
51
159
	fd = open(name, oflags, mode);
52
159
	if (fd < 0) {
53
11
		afree(shf, shf->areap);
54
11
		return NULL;
55
	}
56
148
	if ((sflags & SHF_MAPHI) && fd < FDBASE) {
57
		int nfd;
58
59
148
		nfd = fcntl(fd, F_DUPFD, FDBASE);
60
148
		close(fd);
61
148
		if (nfd < 0) {
62
			afree(shf, shf->areap);
63
			return NULL;
64
		}
65
148
		fd = nfd;
66
	}
67
148
	sflags &= ~SHF_ACCMODE;
68

148
	sflags |= (oflags & O_ACCMODE) == O_RDONLY ? SHF_RD :
69
	    ((oflags & O_ACCMODE) == O_WRONLY ? SHF_WR : SHF_RDWR);
70
71
148
	return shf_reopen(fd, sflags, shf);
72
}
73
74
/* Set up the shf structure for a file descriptor.  Doesn't fail. */
75
struct shf *
76
shf_fdopen(int fd, int sflags, struct shf *shf)
77
17844
{
78
17844
	int bsize = sflags & SHF_UNBUF ? (sflags & SHF_RD ? 1 : 0) : SHF_BSIZE;
79
80
	/* use fcntl() to figure out correct read/write flags */
81
17844
	if (sflags & SHF_GETFL) {
82
		int flags = fcntl(fd, F_GETFL);
83
84
		if (flags < 0)
85
			/* will get an error on first read/write */
86
			sflags |= SHF_RDWR;
87
		else {
88
			switch (flags & O_ACCMODE) {
89
			case O_RDONLY:
90
				sflags |= SHF_RD;
91
				break;
92
			case O_WRONLY:
93
				sflags |= SHF_WR;
94
				break;
95
			case O_RDWR:
96
				sflags |= SHF_RDWR;
97
				break;
98
			}
99
		}
100
	}
101
102
17844
	if (!(sflags & (SHF_RD | SHF_WR)))
103
		internal_errorf(1, "shf_fdopen: missing read/write");
104
105
17844
	if (shf) {
106
10575
		if (bsize) {
107
10575
			shf->buf = alloc(bsize, ATEMP);
108
10575
			sflags |= SHF_ALLOCB;
109
		} else
110
			shf->buf = NULL;
111
	} else {
112
7269
		shf = alloc(sizeof(struct shf) + bsize, ATEMP);
113
7269
		shf->buf = (unsigned char *) &shf[1];
114
7269
		sflags |= SHF_ALLOCS;
115
	}
116
17844
	shf->areap = ATEMP;
117
17844
	shf->fd = fd;
118
17844
	shf->rp = shf->wp = shf->buf;
119
17844
	shf->rnleft = 0;
120
17844
	shf->rbsize = bsize;
121
17844
	shf->wnleft = 0; /* force call to shf_emptybuf() */
122
17844
	shf->wbsize = sflags & SHF_UNBUF ? 0 : bsize;
123
17844
	shf->flags = sflags;
124
17844
	shf->errno_ = 0;
125
17844
	shf->bsize = bsize;
126
17844
	if (sflags & SHF_CLEXEC)
127
		fcntl(fd, F_SETFD, FD_CLOEXEC);
128
17844
	return shf;
129
}
130
131
/* Set up an existing shf (and buffer) to use the given fd */
132
struct shf *
133
shf_reopen(int fd, int sflags, struct shf *shf)
134
165418
{
135
165418
	int bsize = sflags & SHF_UNBUF ? (sflags & SHF_RD ? 1 : 0) : SHF_BSIZE;
136
137
	/* use fcntl() to figure out correct read/write flags */
138
165418
	if (sflags & SHF_GETFL) {
139
		int flags = fcntl(fd, F_GETFL);
140
141
		if (flags < 0)
142
			/* will get an error on first read/write */
143
			sflags |= SHF_RDWR;
144
		else {
145
			switch (flags & O_ACCMODE) {
146
			case O_RDONLY:
147
				sflags |= SHF_RD;
148
				break;
149
			case O_WRONLY:
150
				sflags |= SHF_WR;
151
				break;
152
			case O_RDWR:
153
				sflags |= SHF_RDWR;
154
				break;
155
			}
156
		}
157
	}
158
159
165418
	if (!(sflags & (SHF_RD | SHF_WR)))
160
		internal_errorf(1, "shf_reopen: missing read/write");
161

165418
	if (!shf || !shf->buf || shf->bsize < bsize)
162
		internal_errorf(1, "shf_reopen: bad shf/buf/bsize");
163
164
	/* assumes shf->buf and shf->bsize already set up */
165
165418
	shf->fd = fd;
166
165418
	shf->rp = shf->wp = shf->buf;
167
165418
	shf->rnleft = 0;
168
165418
	shf->rbsize = bsize;
169
165418
	shf->wnleft = 0; /* force call to shf_emptybuf() */
170
165418
	shf->wbsize = sflags & SHF_UNBUF ? 0 : bsize;
171
165418
	shf->flags = (shf->flags & (SHF_ALLOCS | SHF_ALLOCB)) | sflags;
172
165418
	shf->errno_ = 0;
173
165418
	if (sflags & SHF_CLEXEC)
174
148
		fcntl(fd, F_SETFD, FD_CLOEXEC);
175
165418
	return shf;
176
}
177
178
/* Open a string for reading or writing.  If reading, bsize is the number
179
 * of bytes that can be read.  If writing, bsize is the maximum number of
180
 * bytes that can be written.  If shf is not null, it is filled in and
181
 * returned, if it is null, shf is allocated.  If writing and buf is null
182
 * and SHF_DYNAMIC is set, the buffer is allocated (if bsize > 0, it is
183
 * used for the initial size).  Doesn't fail.
184
 * When writing, a byte is reserved for a trailing null - see shf_sclose().
185
 */
186
struct shf *
187
shf_sopen(char *buf, int bsize, int sflags, struct shf *shf)
188
15672
{
189
	/* can't have a read+write string */
190
15672
	if (!(sflags & (SHF_RD | SHF_WR)) ||
191
	    (sflags & (SHF_RD | SHF_WR)) == (SHF_RD | SHF_WR))
192
		internal_errorf(1, "shf_sopen: flags 0x%x", sflags);
193
194
15672
	if (!shf) {
195
		shf = alloc(sizeof(struct shf), ATEMP);
196
		sflags |= SHF_ALLOCS;
197
	}
198
15672
	shf->areap = ATEMP;
199

15672
	if (!buf && (sflags & SHF_WR) && (sflags & SHF_DYNAMIC)) {
200
374
		if (bsize <= 0)
201
16
			bsize = 64;
202
374
		sflags |= SHF_ALLOCB;
203
374
		buf = alloc(bsize, shf->areap);
204
	}
205
15672
	shf->fd = -1;
206
15672
	shf->buf = shf->rp = shf->wp = (unsigned char *) buf;
207
15672
	shf->rnleft = bsize;
208
15672
	shf->rbsize = bsize;
209
15672
	shf->wnleft = bsize - 1;	/* space for a '\0' */
210
15672
	shf->wbsize = bsize;
211
15672
	shf->flags = sflags | SHF_STRING;
212
15672
	shf->errno_ = 0;
213
15672
	shf->bsize = bsize;
214
215
15672
	return shf;
216
}
217
218
/* Flush and close file descriptor, free the shf structure */
219
int
220
shf_close(struct shf *shf)
221
3389
{
222
3389
	int ret = 0;
223
224
3389
	if (shf->fd >= 0) {
225
3322
		ret = shf_flush(shf);
226
3322
		if (close(shf->fd) < 0)
227
			ret = EOF;
228
	}
229
3389
	if (shf->flags & SHF_ALLOCS)
230
3389
		afree(shf, shf->areap);
231
	else if (shf->flags & SHF_ALLOCB)
232
		afree(shf->buf, shf->areap);
233
234
3389
	return ret;
235
}
236
237
/* Flush and close file descriptor, don't free file structure */
238
int
239
shf_fdclose(struct shf *shf)
240
104
{
241
104
	int ret = 0;
242
243
104
	if (shf->fd >= 0) {
244
104
		ret = shf_flush(shf);
245
104
		if (close(shf->fd) < 0)
246
			ret = EOF;
247
104
		shf->rnleft = 0;
248
104
		shf->rp = shf->buf;
249
104
		shf->wnleft = 0;
250
104
		shf->fd = -1;
251
	}
252
253
104
	return ret;
254
}
255
256
/* Close a string - if it was opened for writing, it is null terminated;
257
 * returns a pointer to the string and frees shf if it was allocated
258
 * (does not free string if it was allocated).
259
 */
260
char *
261
shf_sclose(struct shf *shf)
262
15672
{
263
15672
	unsigned char *s = shf->buf;
264
265
	/* null terminate */
266
15672
	if (shf->flags & SHF_WR) {
267
15672
		shf->wnleft++;
268
15672
		shf_putc('\0', shf);
269
	}
270
15672
	if (shf->flags & SHF_ALLOCS)
271
		afree(shf, shf->areap);
272
15672
	return (char *) s;
273
}
274
275
/* Un-read what has been read but not examined, or write what has been
276
 * buffered.  Returns 0 for success, EOF for (write) error.
277
 */
278
int
279
shf_flush(struct shf *shf)
280
190867
{
281
190867
	if (shf->flags & SHF_STRING)
282
		return (shf->flags & SHF_WR) ? EOF : 0;
283
284
190867
	if (shf->fd < 0)
285
		internal_errorf(1, "shf_flush: no fd");
286
287
190867
	if (shf->flags & SHF_ERROR) {
288
		errno = shf->errno_;
289
		return EOF;
290
	}
291
292
190867
	if (shf->flags & SHF_READING) {
293
5626
		shf->flags &= ~(SHF_EOF | SHF_READING);
294
5626
		if (shf->rnleft > 0) {
295
2202
			lseek(shf->fd, (off_t) -shf->rnleft, SEEK_CUR);
296
2202
			shf->rnleft = 0;
297
2202
			shf->rp = shf->buf;
298
		}
299
5626
		return 0;
300
185241
	} else if (shf->flags & SHF_WRITING)
301
3048
		return shf_emptybuf(shf, 0);
302
303
182193
	return 0;
304
}
305
306
/* Write out any buffered data.  If currently reading, flushes the read
307
 * buffer.  Returns 0 for success, EOF for (write) error.
308
 */
309
static int
310
shf_emptybuf(struct shf *shf, int flags)
311
292470
{
312
292470
	int ret = 0;
313
314

292470
	if (!(shf->flags & SHF_STRING) && shf->fd < 0)
315
		internal_errorf(1, "shf_emptybuf: no fd");
316
317
292470
	if (shf->flags & SHF_ERROR) {
318
		errno = shf->errno_;
319
		return EOF;
320
	}
321
322
292470
	if (shf->flags & SHF_READING) {
323
		if (flags & EB_READSW) /* doesn't happen */
324
			return 0;
325
		ret = shf_flush(shf);
326
		shf->flags &= ~SHF_READING;
327
	}
328
292470
	if (shf->flags & SHF_STRING) {
329
		unsigned char	*nbuf;
330
331
		/* Note that we assume SHF_ALLOCS is not set if SHF_ALLOCB
332
		 * is set... (changing the shf pointer could cause problems)
333
		 */
334

287297
		if (!(flags & EB_GROW) || !(shf->flags & SHF_DYNAMIC) ||
335
		    !(shf->flags & SHF_ALLOCB))
336
287297
			return EOF;
337
		/* allocate more space for buffer */
338
		nbuf = areallocarray(shf->buf, 2, shf->wbsize, shf->areap);
339
		shf->rp = nbuf + (shf->rp - shf->buf);
340
		shf->wp = nbuf + (shf->wp - shf->buf);
341
		shf->rbsize += shf->wbsize;
342
		shf->wnleft += shf->wbsize;
343
		shf->wbsize *= 2;
344
		shf->buf = nbuf;
345
	} else {
346
5173
		if (shf->flags & SHF_WRITING) {
347
3455
			int ntowrite = shf->wp - shf->buf;
348
3455
			unsigned char *buf = shf->buf;
349
			int n;
350
351
9390
			while (ntowrite > 0) {
352
2480
				n = write(shf->fd, buf, ntowrite);
353
2480
				if (n < 0) {
354
					if (errno == EINTR &&
355
					    !(shf->flags & SHF_INTERRUPT))
356
						continue;
357
					shf->flags |= SHF_ERROR;
358
					shf->errno_ = errno;
359
					shf->wnleft = 0;
360
					if (buf != shf->buf) {
361
						/* allow a second flush
362
						 * to work */
363
						memmove(shf->buf, buf,
364
						    ntowrite);
365
						shf->wp = shf->buf + ntowrite;
366
					}
367
					return EOF;
368
				}
369
2480
				buf += n;
370
2480
				ntowrite -= n;
371
			}
372
3455
			if (flags & EB_READSW) {
373
				shf->wp = shf->buf;
374
				shf->wnleft = 0;
375
				shf->flags &= ~SHF_WRITING;
376
				return 0;
377
			}
378
		}
379
5173
		shf->wp = shf->buf;
380
5173
		shf->wnleft = shf->wbsize;
381
	}
382
5173
	shf->flags |= SHF_WRITING;
383
384
5173
	return ret;
385
}
386
387
/* Fill up a read buffer.  Returns EOF for a read error, 0 otherwise. */
388
static int
389
shf_fillbuf(struct shf *shf)
390
13276
{
391
13276
	if (shf->flags & SHF_STRING)
392
		return 0;
393
394
13276
	if (shf->fd < 0)
395
		internal_errorf(1, "shf_fillbuf: no fd");
396
397
13276
	if (shf->flags & (SHF_EOF | SHF_ERROR)) {
398
6
		if (shf->flags & SHF_ERROR)
399
			errno = shf->errno_;
400
6
		return EOF;
401
	}
402
403

13270
	if ((shf->flags & SHF_WRITING) && shf_emptybuf(shf, EB_READSW) == EOF)
404
		return EOF;
405
406
13270
	shf->flags |= SHF_READING;
407
408
13270
	shf->rp = shf->buf;
409
	while (1) {
410
16032
		shf->rnleft = blocking_read(shf->fd, (char *) shf->buf,
411
		    shf->rbsize);
412

16032
		if (shf->rnleft < 0 && errno == EINTR &&
413
		    !(shf->flags & SHF_INTERRUPT))
414
2762
			continue;
415
		break;
416
	}
417
13270
	if (shf->rnleft <= 0) {
418
2966
		if (shf->rnleft < 0) {
419
			shf->flags |= SHF_ERROR;
420
			shf->errno_ = errno;
421
			shf->rnleft = 0;
422
			shf->rp = shf->buf;
423
			return EOF;
424
		}
425
2966
		shf->flags |= SHF_EOF;
426
	}
427
13270
	return 0;
428
}
429
430
/* Read a buffer from shf.  Returns the number of bytes read into buf,
431
 * if no bytes were read, returns 0 if end of file was seen, EOF if
432
 * a read error occurred.
433
 */
434
int
435
shf_read(char *buf, int bsize, struct shf *shf)
436
{
437
	int orig_bsize = bsize;
438
	int ncopy;
439
440
	if (!(shf->flags & SHF_RD))
441
		internal_errorf(1, "shf_read: flags %x", shf->flags);
442
443
	if (bsize <= 0)
444
		internal_errorf(1, "shf_read: bsize %d", bsize);
445
446
	while (bsize > 0) {
447
		if (shf->rnleft == 0 &&
448
		    (shf_fillbuf(shf) == EOF || shf->rnleft == 0))
449
			break;
450
		ncopy = shf->rnleft;
451
		if (ncopy > bsize)
452
			ncopy = bsize;
453
		memcpy(buf, shf->rp, ncopy);
454
		buf += ncopy;
455
		bsize -= ncopy;
456
		shf->rp += ncopy;
457
		shf->rnleft -= ncopy;
458
	}
459
	/* Note: fread(3S) returns 0 for errors - this doesn't */
460
	return orig_bsize == bsize ? (shf_error(shf) ? EOF : 0) :
461
	    orig_bsize - bsize;
462
}
463
464
/* Read up to a newline or EOF.  The newline is put in buf; buf is always
465
 * null terminated.  Returns NULL on read error or if nothing was read before
466
 * end of file, returns a pointer to the null byte in buf otherwise.
467
 */
468
char *
469
shf_getse(char *buf, int bsize, struct shf *shf)
470
66823
{
471
	unsigned char *end;
472
	int ncopy;
473
66823
	char *orig_buf = buf;
474
475
66823
	if (!(shf->flags & SHF_RD))
476
		internal_errorf(1, "shf_getse: flags %x", shf->flags);
477
478
66823
	if (bsize <= 0)
479
		return NULL;
480
481
66823
	--bsize;	/* save room for null */
482
	do {
483
70099
		if (shf->rnleft == 0) {
484
6695
			if (shf_fillbuf(shf) == EOF)
485
6
				return NULL;
486
6689
			if (shf->rnleft == 0) {
487
514
				*buf = '\0';
488
514
				return buf == orig_buf ? NULL : buf;
489
			}
490
		}
491
69579
		end = (unsigned char *) memchr((char *) shf->rp, '\n',
492
		    shf->rnleft);
493
69579
		ncopy = end ? end - shf->rp + 1 : shf->rnleft;
494
69579
		if (ncopy > bsize)
495
4
			ncopy = bsize;
496
69579
		memcpy(buf, (char *) shf->rp, ncopy);
497
69579
		shf->rp += ncopy;
498
69579
		shf->rnleft -= ncopy;
499
69579
		buf += ncopy;
500
69579
		bsize -= ncopy;
501
69579
	} while (!end && bsize);
502
66303
	*buf = '\0';
503
66303
	return buf;
504
}
505
506
/* Returns the char read.  Returns EOF for error and end of file. */
507
int
508
shf_getchar(struct shf *shf)
509
6581
{
510
6581
	if (!(shf->flags & SHF_RD))
511
		internal_errorf(1, "shf_getchar: flags %x", shf->flags);
512
513

6581
	if (shf->rnleft == 0 && (shf_fillbuf(shf) == EOF || shf->rnleft == 0))
514
2452
		return EOF;
515
4129
	--shf->rnleft;
516
4129
	return *shf->rp++;
517
}
518
519
/* Put a character back in the input stream.  Returns the character if
520
 * successful, EOF if there is no room.
521
 */
522
int
523
shf_ungetc(int c, struct shf *shf)
524
30618
{
525
30618
	if (!(shf->flags & SHF_RD))
526
		internal_errorf(1, "shf_ungetc: flags %x", shf->flags);
527
528

30618
	if ((shf->flags & SHF_ERROR) || c == EOF ||
529
	    (shf->rp == shf->buf && shf->rnleft))
530
		return EOF;
531
532

30618
	if ((shf->flags & SHF_WRITING) && shf_emptybuf(shf, EB_READSW) == EOF)
533
		return EOF;
534
535
30618
	if (shf->rp == shf->buf)
536
		shf->rp = shf->buf + shf->rbsize;
537
30618
	if (shf->flags & SHF_STRING) {
538
		/* Can unget what was read, but not something different - we
539
		 * don't want to modify a string.
540
		 */
541
		if (shf->rp[-1] != c)
542
			return EOF;
543
		shf->flags &= ~SHF_EOF;
544
		shf->rp--;
545
		shf->rnleft++;
546
		return c;
547
	}
548
30618
	shf->flags &= ~SHF_EOF;
549
30618
	*--(shf->rp) = c;
550
30618
	shf->rnleft++;
551
30618
	return c;
552
}
553
554
/* Write a character.  Returns the character if successful, EOF if
555
 * the char could not be written.
556
 */
557
int
558
shf_putchar(int c, struct shf *shf)
559
716076
{
560
716076
	if (!(shf->flags & SHF_WR))
561
		internal_errorf(1, "shf_putchar: flags %x", shf->flags);
562
563
716076
	if (c == EOF)
564
		return EOF;
565
566
716076
	if (shf->flags & SHF_UNBUF) {
567
		char cc = c;
568
		int n;
569
570
		if (shf->fd < 0)
571
			internal_errorf(1, "shf_putchar: no fd");
572
		if (shf->flags & SHF_ERROR) {
573
			errno = shf->errno_;
574
			return EOF;
575
		}
576
		while ((n = write(shf->fd, &cc, 1)) != 1)
577
			if (n < 0) {
578
				if (errno == EINTR &&
579
				    !(shf->flags & SHF_INTERRUPT))
580
					continue;
581
				shf->flags |= SHF_ERROR;
582
				shf->errno_ = errno;
583
				return EOF;
584
			}
585
	} else {
586
		/* Flush deals with strings and sticky errors */
587

716076
		if (shf->wnleft == 0 && shf_emptybuf(shf, EB_GROW) == EOF)
588
286543
			return EOF;
589
429533
		shf->wnleft--;
590
429533
		*shf->wp++ = c;
591
	}
592
593
429533
	return c;
594
}
595
596
/* Write a string.  Returns the length of the string if successful, EOF if
597
 * the string could not be written.
598
 */
599
int
600
shf_puts(const char *s, struct shf *shf)
601
1689
{
602
1689
	if (!s)
603
		return EOF;
604
605
1689
	return shf_write(s, strlen(s), shf);
606
}
607
608
/* Write a buffer.  Returns nbytes if successful, EOF if there is an error. */
609
int
610
shf_write(const char *buf, int nbytes, struct shf *shf)
611
1699
{
612
1699
	int orig_nbytes = nbytes;
613
	int n;
614
	int ncopy;
615
616
1699
	if (!(shf->flags & SHF_WR))
617
		internal_errorf(1, "shf_write: flags %x", shf->flags);
618
619
1699
	if (nbytes < 0)
620
		internal_errorf(1, "shf_write: nbytes %d", nbytes);
621
622
	/* Don't buffer if buffer is empty and we're writting a large amount. */
623

1699
	if ((ncopy = shf->wnleft) &&
624
	    (shf->wp != shf->buf || nbytes < shf->wnleft)) {
625
661
		if (ncopy > nbytes)
626
98
			ncopy = nbytes;
627
661
		memcpy(shf->wp, buf, ncopy);
628
661
		nbytes -= ncopy;
629
661
		buf += ncopy;
630
661
		shf->wp += ncopy;
631
661
		shf->wnleft -= ncopy;
632
	}
633
1699
	if (nbytes > 0) {
634
		/* Flush deals with strings and sticky errors */
635
1599
		if (shf_emptybuf(shf, EB_GROW) == EOF)
636
754
			return EOF;
637
845
		if (nbytes > shf->wbsize) {
638
207
			ncopy = nbytes;
639
207
			if (shf->wbsize)
640
207
				ncopy -= nbytes % shf->wbsize;
641
207
			nbytes -= ncopy;
642
621
			while (ncopy > 0) {
643
207
				n = write(shf->fd, buf, ncopy);
644
207
				if (n < 0) {
645
					if (errno == EINTR &&
646
					    !(shf->flags & SHF_INTERRUPT))
647
						continue;
648
					shf->flags |= SHF_ERROR;
649
					shf->errno_ = errno;
650
					shf->wnleft = 0;
651
					/* Note: fwrite(3S) returns 0 for
652
					 * errors - this doesn't */
653
					return EOF;
654
				}
655
207
				buf += n;
656
207
				ncopy -= n;
657
			}
658
		}
659
845
		if (nbytes > 0) {
660
845
			memcpy(shf->wp, buf, nbytes);
661
845
			shf->wp += nbytes;
662
845
			shf->wnleft -= nbytes;
663
		}
664
	}
665
666
945
	return orig_nbytes;
667
}
668
669
int
670
shf_fprintf(struct shf *shf, const char *fmt, ...)
671
1841
{
672
	va_list args;
673
	int n;
674
675
1841
	va_start(args, fmt);
676
1841
	n = shf_vfprintf(shf, fmt, args);
677
1841
	va_end(args);
678
679
1841
	return n;
680
}
681
682
int
683
shf_snprintf(char *buf, int bsize, const char *fmt, ...)
684
1123
{
685
	struct shf shf;
686
	va_list args;
687
	int n;
688
689
1123
	if (!buf || bsize <= 0)
690
		internal_errorf(1, "shf_snprintf: buf %lx, bsize %d",
691
			(long) buf, bsize);
692
693
1123
	shf_sopen(buf, bsize, SHF_WR, &shf);
694
1123
	va_start(args, fmt);
695
1123
	n = shf_vfprintf(&shf, fmt, args);
696
1123
	va_end(args);
697
1123
	shf_sclose(&shf); /* null terminates */
698
1123
	return n;
699
}
700
701
char *
702
shf_smprintf(const char *fmt, ...)
703
16
{
704
	struct shf shf;
705
	va_list args;
706
707
16
	shf_sopen(NULL, 0, SHF_WR|SHF_DYNAMIC, &shf);
708
16
	va_start(args, fmt);
709
16
	shf_vfprintf(&shf, fmt, args);
710
16
	va_end(args);
711
16
	return shf_sclose(&shf); /* null terminates */
712
}
713
714
#define	FL_HASH		0x001	/* `#' seen */
715
#define FL_PLUS		0x002	/* `+' seen */
716
#define FL_RIGHT	0x004	/* `-' seen */
717
#define FL_BLANK	0x008	/* ` ' seen */
718
#define FL_SHORT	0x010	/* `h' seen */
719
#define FL_LONG		0x020	/* `l' seen */
720
#define FL_LLONG	0x040	/* `ll' seen */
721
#define FL_ZERO		0x080	/* `0' seen */
722
#define FL_DOT		0x100	/* '.' seen */
723
#define FL_UPPER	0x200	/* format character was uppercase */
724
#define FL_NUMBER	0x400	/* a number was formated %[douxefg] */
725
726
int
727
shf_vfprintf(struct shf *shf, const char *fmt, va_list args)
728
31771
{
729
	char		c, *s;
730
31771
	int		tmp = 0;
731
	int		field, precision;
732
	int		len;
733
	int		flags;
734
	unsigned long long	llnum;
735
					/* %#o produces the longest output */
736
	char		numbuf[(BITS(long long) + 2) / 3 + 1];
737
	/* this stuff for dealing with the buffer */
738
31771
	int		nwritten = 0;
739
740
31771
	if (!fmt)
741
		return 0;
742
743
79159
	while ((c = *fmt++)) {
744
47388
		if (c != '%') {
745
32183
			shf_putc(c, shf);
746
32183
			nwritten++;
747
32183
			continue;
748
		}
749
		/*
750
		 *	This will accept flags/fields in any order - not
751
		 *  just the order specified in printf(3), but this is
752
		 *  the way _doprnt() seems to work (on bsd and sysV).
753
		 *  The only restriction is that the format character must
754
		 *  come last :-).
755
		 */
756
15205
		flags = field = precision = 0;
757
31802
		for ( ; (c = *fmt++) ; ) {
758


16597
			switch (c) {
759
			case '#':
760
2
				flags |= FL_HASH;
761
2
				continue;
762
763
			case '+':
764
				flags |= FL_PLUS;
765
				continue;
766
767
			case '-':
768
560
				flags |= FL_RIGHT;
769
560
				continue;
770
771
			case ' ':
772
				flags |= FL_BLANK;
773
				continue;
774
775
			case '0':
776
12
				if (!(flags & FL_DOT))
777
12
					flags |= FL_ZERO;
778
				continue;
779
780
			case '.':
781
2
				flags |= FL_DOT;
782
2
				precision = 0;
783
2
				continue;
784
785
			case '*':
786
782
				tmp = va_arg(args, int);
787
782
				if (flags & FL_DOT)
788
					precision = tmp;
789
782
				else if ((field = tmp) < 0) {
790
					field = -field;
791
					flags |= FL_RIGHT;
792
				}
793
				continue;
794
795
			case 'l':
796
18
				if (*fmt == 'l') {
797
12
					fmt++;
798
12
					flags |= FL_LLONG;
799
				} else
800
6
					flags |= FL_LONG;
801
				continue;
802
803
			case 'h':
804
				flags |= FL_SHORT;
805
				continue;
806
			}
807
15221
			if (digit(c)) {
808
16
				tmp = c - '0';
809
32
				while (c = *fmt++, digit(c))
810
					tmp = tmp * 10 + c - '0';
811
16
				--fmt;
812
16
				if (tmp < 0)		/* overflow? */
813
					tmp = 0;
814
16
				if (flags & FL_DOT)
815
2
					precision = tmp;
816
				else
817
14
					field = tmp;
818
				continue;
819
			}
820
			break;
821
		}
822
823
15205
		if (precision < 0)
824
			precision = 0;
825
826
15205
		if (!c)		/* nasty format */
827
			break;
828
829
15205
		if (c >= 'A' && c <= 'Z') {
830
			flags |= FL_UPPER;
831
			c = c - 'A' + 'a';
832
		}
833
834

15205
		switch (c) {
835
		case 'p': /* pointer */
836
			flags &= ~(FL_LLONG | FL_SHORT);
837
			flags |= FL_LONG;
838
			/* aaahhh... */
839
		case 'd':
840
		case 'i':
841
		case 'o':
842
		case 'u':
843
		case 'x':
844
163
			flags |= FL_NUMBER;
845
163
			s = &numbuf[sizeof(numbuf)];
846
163
			if (flags & FL_LLONG)
847
12
				llnum = va_arg(args, unsigned long long);
848
151
			else if (flags & FL_LONG) {
849
6
				if (c == 'd' || c == 'i')
850
6
					llnum = va_arg(args, long);
851
				else
852
					llnum = va_arg(args, unsigned long);
853
			} else {
854
145
				if (c == 'd' || c == 'i')
855
143
					llnum = va_arg(args, int);
856
				else
857
2
					llnum = va_arg(args, unsigned int);
858
			}
859

163
			switch (c) {
860
			case 'd':
861
			case 'i':
862
161
				if (0 > (long long) llnum)
863
					llnum = - (long long) llnum, tmp = 1;
864
				else
865
161
					tmp = 0;
866
				/* aaahhhh..... */
867
868
			case 'u':
869
				do {
870
210
					*--s = llnum % 10 + '0';
871
210
					llnum /= 10;
872
210
				} while (llnum);
873
874
161
				if (c != 'u') {
875
161
					if (tmp)
876
						*--s = '-';
877
161
					else if (flags & FL_PLUS)
878
						*--s = '+';
879
161
					else if (flags & FL_BLANK)
880
						*--s = ' ';
881
				}
882
				break;
883
884
			case 'o':
885
				do {
886
6
					*--s = (llnum & 0x7) + '0';
887
6
					llnum >>= 3;
888
6
				} while (llnum);
889
890

2
				if ((flags & FL_HASH) && *s != '0')
891
2
					*--s = '0';
892
				break;
893
894
			case 'p':
895
			case 'x':
896
			    {
897
				const char *digits = (flags & FL_UPPER) ?
898
				    "0123456789ABCDEF" :
899
				    "0123456789abcdef";
900
				do {
901
					*--s = digits[llnum & 0xf];
902
					llnum >>= 4;
903
				} while (llnum);
904
905
				if (flags & FL_HASH) {
906
					*--s = (flags & FL_UPPER) ? 'X' : 'x';
907
					*--s = '0';
908
				}
909
			    }
910
			}
911
163
			len = &numbuf[sizeof(numbuf)] - s;
912
163
			if (flags & FL_DOT) {
913
2
				if (precision > len) {
914
					field = precision;
915
					flags |= FL_ZERO;
916
				} else
917
2
					precision = len; /* no loss */
918
			}
919
			break;
920
921
		case 's':
922

15026
			if (!(s = va_arg(args, char *)))
923
				s = "(null %s)";
924
15026
			len = strlen(s);
925
15026
			break;
926
927
		case 'c':
928
16
			flags &= ~FL_DOT;
929
16
			numbuf[0] = va_arg(args, int);
930
16
			s = numbuf;
931
16
			len = 1;
932
16
			break;
933
934
		case '%':
935
		default:
936
			numbuf[0] = c;
937
			s = numbuf;
938
			len = 1;
939
			break;
940
		}
941
942
		/*
943
		 *	At this point s should point to a string that is
944
		 *  to be formatted, and len should be the length of the
945
		 *  string.
946
		 */
947
15205
		if (!(flags & FL_DOT) || len < precision)
948
15203
			precision = len;
949
15205
		if (field > precision) {
950
778
			field -= precision;
951
778
			if (!(flags & FL_RIGHT)) {
952
234
				field = -field;
953
				/* skip past sign or 0x when padding with 0 */
954
234
				if ((flags & FL_ZERO) && (flags & FL_NUMBER)) {
955

12
					if (*s == '+' || *s == '-' || *s ==' ') {
956
						shf_putc(*s, shf);
957
						s++;
958
						precision--;
959
						nwritten++;
960
12
					} else if (*s == '0') {
961
10
						shf_putc(*s, shf);
962
10
						s++;
963
10
						nwritten++;
964

10
						if (--precision > 0 &&
965
						    (*s | 0x20) == 'x') {
966
							shf_putc(*s, shf);
967
							s++;
968
							precision--;
969
							nwritten++;
970
						}
971
					}
972
12
					c = '0';
973
				} else
974
222
					c = flags & FL_ZERO ? '0' : ' ';
975
234
				if (field < 0) {
976
234
					nwritten += -field;
977
486
					for ( ; field < 0 ; field++)
978
252
						shf_putc(c, shf);
979
				}
980
			} else
981
544
				c = ' ';
982
		} else
983
14427
			field = 0;
984
985
15205
		if (precision > 0) {
986
13772
			nwritten += precision;
987
163342
			for ( ; precision-- > 0 ; s++)
988
149570
				shf_putc(*s, shf);
989
		}
990
15205
		if (field > 0) {
991
544
			nwritten += field;
992
2698
			for ( ; field > 0 ; --field)
993
2154
				shf_putc(c, shf);
994
		}
995
	}
996
997
31771
	return shf_error(shf) ? EOF : nwritten;
998
}