GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: bin/ksh/shf.c Lines: 361 548 65.9 %
Date: 2017-11-13 Branches: 229 430 53.3 %

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
{
39
	struct shf *shf;
40
41832
	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
13944
	shf = alloc(sizeof(struct shf) + bsize, ATEMP);
45
13944
	shf->areap = ATEMP;
46
13944
	shf->buf = (unsigned char *) &shf[1];
47
13944
	shf->bsize = bsize;
48
13944
	shf->flags = SHF_ALLOCS;
49
	/* Rest filled in by reopen. */
50
51
13944
	fd = open(name, oflags, mode);
52
13944
	if (fd < 0) {
53
20
		afree(shf, shf->areap);
54
20
		return NULL;
55
	}
56
13924
	if ((sflags & SHF_MAPHI) && fd < FDBASE) {
57
		int nfd;
58
59
13924
		nfd = fcntl(fd, F_DUPFD, FDBASE);
60
13924
		close(fd);
61
13924
		if (nfd < 0) {
62
			afree(shf, shf->areap);
63
			return NULL;
64
		}
65
		fd = nfd;
66
13924
	}
67
13924
	sflags &= ~SHF_ACCMODE;
68
27848
	sflags |= (oflags & O_ACCMODE) == O_RDONLY ? SHF_RD :
69
	    ((oflags & O_ACCMODE) == O_WRONLY ? SHF_WR : SHF_RDWR);
70
71
13924
	return shf_reopen(fd, sflags, shf);
72
13944
}
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
{
78
5378930
	int bsize = sflags & SHF_UNBUF ? (sflags & SHF_RD ? 1 : 0) : SHF_BSIZE;
79
80
	/* use fcntl() to figure out correct read/write flags */
81
1792754
	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
1792754
	if (!(sflags & (SHF_RD | SHF_WR)))
103
		internal_errorf(1, "shf_fdopen: missing read/write");
104
105
1792754
	if (shf) {
106
314289
		if (bsize) {
107
314289
			shf->buf = alloc(bsize, ATEMP);
108
314289
			sflags |= SHF_ALLOCB;
109
314289
		} else
110
			shf->buf = NULL;
111
	} else {
112
1478465
		shf = alloc(sizeof(struct shf) + bsize, ATEMP);
113
1478465
		shf->buf = (unsigned char *) &shf[1];
114
1478465
		sflags |= SHF_ALLOCS;
115
	}
116
1792754
	shf->areap = ATEMP;
117
1792754
	shf->fd = fd;
118
1792754
	shf->rp = shf->wp = shf->buf;
119
1792754
	shf->rnleft = 0;
120
1792754
	shf->rbsize = bsize;
121
1792754
	shf->wnleft = 0; /* force call to shf_emptybuf() */
122
1792754
	shf->wbsize = sflags & SHF_UNBUF ? 0 : bsize;
123
1792754
	shf->flags = sflags;
124
1792754
	shf->errno_ = 0;
125
1792754
	shf->bsize = bsize;
126
1792754
	if (sflags & SHF_CLEXEC)
127
		fcntl(fd, F_SETFD, FD_CLOEXEC);
128
1792754
	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
{
135
9648231
	int bsize = sflags & SHF_UNBUF ? (sflags & SHF_RD ? 1 : 0) : SHF_BSIZE;
136
137
	/* use fcntl() to figure out correct read/write flags */
138
3216017
	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
3216017
	if (!(sflags & (SHF_RD | SHF_WR)))
160
		internal_errorf(1, "shf_reopen: missing read/write");
161

9648051
	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
3216017
	shf->fd = fd;
166
3216017
	shf->rp = shf->wp = shf->buf;
167
3216017
	shf->rnleft = 0;
168
3216017
	shf->rbsize = bsize;
169
3216017
	shf->wnleft = 0; /* force call to shf_emptybuf() */
170
3216017
	shf->wbsize = sflags & SHF_UNBUF ? 0 : bsize;
171
3216017
	shf->flags = (shf->flags & (SHF_ALLOCS | SHF_ALLOCB)) | sflags;
172
3216017
	shf->errno_ = 0;
173
3216017
	if (sflags & SHF_CLEXEC)
174
13924
		fcntl(fd, F_SETFD, FD_CLOEXEC);
175
3216017
	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
{
189
	/* can't have a read+write string */
190

9118629
	if (!(sflags & (SHF_RD | SHF_WR)) ||
191
3039543
	    (sflags & (SHF_RD | SHF_WR)) == (SHF_RD | SHF_WR))
192
		internal_errorf(1, "shf_sopen: flags 0x%x", sflags);
193
194
3039543
	if (!shf) {
195
		shf = alloc(sizeof(struct shf), ATEMP);
196
		sflags |= SHF_ALLOCS;
197
	}
198
3039543
	shf->areap = ATEMP;
199

3092107
	if (!buf && (sflags & SHF_WR) && (sflags & SHF_DYNAMIC)) {
200
26282
		if (bsize <= 0)
201
48
			bsize = 64;
202
26282
		sflags |= SHF_ALLOCB;
203
26282
		buf = alloc(bsize, shf->areap);
204
26282
	}
205
3039543
	shf->fd = -1;
206
3039543
	shf->buf = shf->rp = shf->wp = (unsigned char *) buf;
207
3039543
	shf->rnleft = bsize;
208
3039543
	shf->rbsize = bsize;
209
3039543
	shf->wnleft = bsize - 1;	/* space for a '\0' */
210
3039543
	shf->wbsize = bsize;
211
3039543
	shf->flags = sflags | SHF_STRING;
212
3039543
	shf->errno_ = 0;
213
3039543
	shf->bsize = bsize;
214
215
3039543
	return shf;
216
}
217
218
/* Flush and close file descriptor, free the shf structure */
219
int
220
shf_close(struct shf *shf)
221
{
222
	int ret = 0;
223
224
2723278
	if (shf->fd >= 0) {
225
1360053
		ret = shf_flush(shf);
226
1360053
		if (close(shf->fd) < 0)
227
			ret = EOF;
228
	}
229
1361639
	if (shf->flags & SHF_ALLOCS)
230
1361639
		afree(shf, shf->areap);
231
	else if (shf->flags & SHF_ALLOCB)
232
		afree(shf->buf, shf->areap);
233
234
1361639
	return ret;
235
}
236
237
/* Flush and close file descriptor, don't free file structure */
238
int
239
shf_fdclose(struct shf *shf)
240
{
241
	int ret = 0;
242
243
3754
	if (shf->fd >= 0) {
244
1877
		ret = shf_flush(shf);
245
1877
		if (close(shf->fd) < 0)
246
			ret = EOF;
247
1877
		shf->rnleft = 0;
248
1877
		shf->rp = shf->buf;
249
1877
		shf->wnleft = 0;
250
1877
		shf->fd = -1;
251
1877
	}
252
253
1877
	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
{
263
6079086
	unsigned char *s = shf->buf;
264
265
	/* null terminate */
266
3039543
	if (shf->flags & SHF_WR) {
267
3039543
		shf->wnleft++;
268
6079086
		shf_putc('\0', shf);
269
	}
270
3039543
	if (shf->flags & SHF_ALLOCS)
271
		afree(shf, shf->areap);
272
3039543
	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
{
281
12468026
	if (shf->flags & SHF_STRING)
282
		return (shf->flags & SHF_WR) ? EOF : 0;
283
284
6234013
	if (shf->fd < 0)
285
		internal_errorf(1, "shf_flush: no fd");
286
287
6234013
	if (shf->flags & SHF_ERROR) {
288
		errno = shf->errno_;
289
		return EOF;
290
	}
291
292
6234013
	if (shf->flags & SHF_READING) {
293
1384679
		shf->flags &= ~(SHF_EOF | SHF_READING);
294
1384679
		if (shf->rnleft > 0) {
295
13119
			lseek(shf->fd, (off_t) -shf->rnleft, SEEK_CUR);
296
13119
			shf->rnleft = 0;
297
13119
			shf->rp = shf->buf;
298
13119
		}
299
1384679
		return 0;
300
4849334
	} else if (shf->flags & SHF_WRITING)
301
59819
		return shf_emptybuf(shf, 0);
302
303
4789515
	return 0;
304
6234013
}
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
{
312
	int ret = 0;
313
314

11484877
	if (!(shf->flags & SHF_STRING) && shf->fd < 0)
315
		internal_errorf(1, "shf_emptybuf: no fd");
316
317
5709606
	if (shf->flags & SHF_ERROR) {
318
		errno = shf->errno_;
319
		return EOF;
320
	}
321
322
5709606
	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
5709606
	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

11287882
		if (!(flags & EB_GROW) || !(shf->flags & SHF_DYNAMIC) ||
335
		    !(shf->flags & SHF_ALLOCB))
336
5643941
			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
65665
		if (shf->flags & SHF_WRITING) {
347
59819
			int ntowrite = shf->wp - shf->buf;
348
			unsigned char *buf = shf->buf;
349
			int n;
350
351
185832
			while (ntowrite > 0) {
352
33097
				n = write(shf->fd, buf, ntowrite);
353
33097
				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
33097
				buf += n;
370
33097
				ntowrite -= n;
371
			}
372
59819
			if (flags & EB_READSW) {
373
				shf->wp = shf->buf;
374
				shf->wnleft = 0;
375
				shf->flags &= ~SHF_WRITING;
376
				return 0;
377
			}
378
59819
		}
379
65665
		shf->wp = shf->buf;
380
65665
		shf->wnleft = shf->wbsize;
381
	}
382
65665
	shf->flags |= SHF_WRITING;
383
384
65665
	return ret;
385
5709606
}
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
{
391
6658158
	if (shf->flags & SHF_STRING)
392
		return 0;
393
394
3329079
	if (shf->fd < 0)
395
		internal_errorf(1, "shf_fillbuf: no fd");
396
397
3329079
	if (shf->flags & (SHF_EOF | SHF_ERROR)) {
398
18
		if (shf->flags & SHF_ERROR)
399
			errno = shf->errno_;
400
18
		return EOF;
401
	}
402
403

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

11092581
		if (shf->rnleft < 0 && errno == EINTR &&
413
2587840
		    !(shf->flags & SHF_INTERRUPT))
414
2587840
			continue;
415
		break;
416
	}
417
3329061
	if (shf->rnleft <= 0) {
418
1361184
		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
1361184
		shf->flags |= SHF_EOF;
426
1361184
	}
427
3329061
	return 0;
428
3329079
}
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
{
471
	unsigned char *end;
472
	int ncopy;
473
	char *orig_buf = buf;
474
475
3041470
	if (!(shf->flags & SHF_RD))
476
		internal_errorf(1, "shf_getse: flags %x", shf->flags);
477
478
1520735
	if (bsize <= 0)
479
		return NULL;
480
481
1520735
	--bsize;	/* save room for null */
482
1520735
	do {
483
1867415
		if (shf->rnleft == 0) {
484
383650
			if (shf_fillbuf(shf) == EOF)
485
18
				return NULL;
486
383632
			if (shf->rnleft == 0) {
487
3131
				*buf = '\0';
488
3131
				return buf == orig_buf ? NULL : buf;
489
			}
490
		}
491
3728532
		end = (unsigned char *) memchr((char *) shf->rp, '\n',
492
1864266
		    shf->rnleft);
493
5592798
		ncopy = end ? end - shf->rp + 1 : shf->rnleft;
494
1864266
		if (ncopy > bsize)
495
6
			ncopy = bsize;
496
1864266
		memcpy(buf, (char *) shf->rp, ncopy);
497
1864266
		shf->rp += ncopy;
498
1864266
		shf->rnleft -= ncopy;
499
1864266
		buf += ncopy;
500
1864266
		bsize -= ncopy;
501
1864266
	} while (!end && bsize);
502
1517586
	*buf = '\0';
503
1517586
	return buf;
504
1520735
}
505
506
/* Returns the char read.  Returns EOF for error and end of file. */
507
int
508
shf_getchar(struct shf *shf)
509
{
510
5890858
	if (!(shf->flags & SHF_RD))
511
		internal_errorf(1, "shf_getchar: flags %x", shf->flags);
512
513

8836287
	if (shf->rnleft == 0 && (shf_fillbuf(shf) == EOF || shf->rnleft == 0))
514
1358053
		return EOF;
515
1587376
	--shf->rnleft;
516
1587376
	return *shf->rp++;
517
2945429
}
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
{
525
2664316
	if (!(shf->flags & SHF_RD))
526
		internal_errorf(1, "shf_ungetc: flags %x", shf->flags);
527
528

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

1332158
	if ((shf->flags & SHF_WRITING) && shf_emptybuf(shf, EB_READSW) == EOF)
533
		return EOF;
534
535
1332158
	if (shf->rp == shf->buf)
536
		shf->rp = shf->buf + shf->rbsize;
537
1332158
	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
1332158
	shf->flags &= ~SHF_EOF;
549
1332158
	*--(shf->rp) = c;
550
1332158
	shf->rnleft++;
551
1332158
	return c;
552
1332158
}
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
{
560
113945094
	if (!(shf->flags & SHF_WR))
561
		internal_errorf(1, "shf_putchar: flags %x", shf->flags);
562
563
56972547
	if (c == EOF)
564
		return EOF;
565
566
56972547
	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

62619378
		if (shf->wnleft == 0 && shf_emptybuf(shf, EB_GROW) == EOF)
588
5643069
			return EOF;
589
51329478
		shf->wnleft--;
590
51329478
		*shf->wp++ = c;
591
	}
592
593
51329478
	return c;
594
56972547
}
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
{
602
8408
	if (!s)
603
		return EOF;
604
605
4204
	return shf_write(s, strlen(s), shf);
606
4204
}
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
{
612
	int orig_nbytes = nbytes;
613
	int n;
614
	int ncopy;
615
616
8468
	if (!(shf->flags & SHF_WR))
617
		internal_errorf(1, "shf_write: flags %x", shf->flags);
618
619
4234
	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

4258
	if ((ncopy = shf->wnleft) &&
624
2170
	    (shf->wp != shf->buf || nbytes < shf->wnleft)) {
625
2146
		if (ncopy > nbytes)
626
1278
			ncopy = nbytes;
627
2146
		memcpy(shf->wp, buf, ncopy);
628
2146
		nbytes -= ncopy;
629
2146
		buf += ncopy;
630
2146
		shf->wp += ncopy;
631
2146
		shf->wnleft -= ncopy;
632
2146
	}
633
4234
	if (nbytes > 0) {
634
		/* Flush deals with strings and sticky errors */
635
2956
		if (shf_emptybuf(shf, EB_GROW) == EOF)
636
872
			return EOF;
637
2084
		if (nbytes > shf->wbsize) {
638
			ncopy = nbytes;
639
34
			if (shf->wbsize)
640
34
				ncopy -= nbytes % shf->wbsize;
641
34
			nbytes -= ncopy;
642
136
			while (ncopy > 0) {
643
34
				n = write(shf->fd, buf, ncopy);
644
34
				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
34
				buf += n;
656
34
				ncopy -= n;
657
			}
658
		}
659
2084
		if (nbytes > 0) {
660
2084
			memcpy(shf->wp, buf, nbytes);
661
2084
			shf->wp += nbytes;
662
2084
			shf->wnleft -= nbytes;
663
2084
		}
664
	}
665
666
3362
	return orig_nbytes;
667
4234
}
668
669
int
670
shf_fprintf(struct shf *shf, const char *fmt, ...)
671
{
672
151896
	va_list args;
673
	int n;
674
675
75948
	va_start(args, fmt);
676
75948
	n = shf_vfprintf(shf, fmt, args);
677
75948
	va_end(args);
678
679
75948
	return n;
680
75948
}
681
682
int
683
shf_snprintf(char *buf, int bsize, const char *fmt, ...)
684
{
685
4156
	struct shf shf;
686
2078
	va_list args;
687
	int n;
688
689
2078
	if (!buf || bsize <= 0)
690
		internal_errorf(1, "shf_snprintf: buf %lx, bsize %d",
691
			(long) buf, bsize);
692
693
2078
	shf_sopen(buf, bsize, SHF_WR, &shf);
694
2078
	va_start(args, fmt);
695
2078
	n = shf_vfprintf(&shf, fmt, args);
696
2078
	va_end(args);
697
2078
	shf_sclose(&shf); /* null terminates */
698
2078
	return n;
699
2078
}
700
701
char *
702
shf_smprintf(const char *fmt, ...)
703
{
704
96
	struct shf shf;
705
48
	va_list args;
706
707
48
	shf_sopen(NULL, 0, SHF_WR|SHF_DYNAMIC, &shf);
708
48
	va_start(args, fmt);
709
48
	shf_vfprintf(&shf, fmt, args);
710
48
	va_end(args);
711
96
	return shf_sclose(&shf); /* null terminates */
712
48
}
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
{
729
	char		c, *s;
730
	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
164060
	char		numbuf[(BITS(long long) + 2) / 3 + 1];
737
	/* this stuff for dealing with the buffer */
738
	int		nwritten = 0;
739
740
82030
	if (!fmt)
741
		return 0;
742
743
502694
	while ((c = *fmt++)) {
744
194059
		if (c != '%') {
745
98968
			shf_putc(c, shf);
746
49484
			nwritten++;
747
49484
			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
		flags = field = precision = 0;
757
320942
		for ( ; (c = *fmt++) ; ) {
758


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

289150
		if (c >= 'A' && c <= 'Z') {
830
			flags |= FL_UPPER;
831
			c = c - 'A' + 'a';
832
		}
833
834


144575
		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
12530
			flags |= FL_NUMBER;
845
12530
			s = &numbuf[sizeof(numbuf)];
846
12530
			if (flags & FL_LLONG)
847
23814
				llnum = va_arg(args, unsigned long long);
848
4592
			else if (flags & FL_LONG) {
849

3969
				if (c == 'd' || c == 'i')
850
11907
					llnum = va_arg(args, long);
851
				else
852
					llnum = va_arg(args, unsigned long);
853
			} else {
854

633
				if (c == 'd' || c == 'i')
855
1839
					llnum = va_arg(args, int);
856
				else
857
30
					llnum = va_arg(args, unsigned int);
858
			}
859

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

20
				if ((flags & FL_HASH) && *s != '0')
891
10
					*--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
12530
			len = &numbuf[sizeof(numbuf)] - s;
912
12530
			if (flags & FL_DOT) {
913
10
				if (precision > len) {
914
					field = precision;
915
					flags |= FL_ZERO;
916
				} else
917
					precision = len; /* no loss */
918
			}
919
			break;
920
921
		case 's':
922
395991
			if (!(s = va_arg(args, char *)))
923
				s = "(null %s)";
924
131997
			len = strlen(s);
925
131997
			break;
926
927
		case 'c':
928
48
			flags &= ~FL_DOT;
929
144
			numbuf[0] = va_arg(args, int);
930
48
			s = numbuf;
931
			len = 1;
932
48
			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

144585
		if (!(flags & FL_DOT) || len < precision)
948
144565
			precision = len;
949
144575
		if (field > precision) {
950
9246
			field -= precision;
951
9246
			if (!(flags & FL_RIGHT)) {
952
9246
				field = -field;
953
				/* skip past sign or 0x when padding with 0 */
954

14523
				if ((flags & FL_ZERO) && (flags & FL_NUMBER)) {
955

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

3704
						if (--precision > 0 &&
965
						    (*s | 0x20) == 'x') {
966
							shf_putc(*s, shf);
967
							s++;
968
							precision--;
969
							nwritten++;
970
						}
971
					}
972
					c = '0';
973
5277
				} else
974
3969
					c = flags & FL_ZERO ? '0' : ' ';
975
9246
				if (field < 0) {
976
9246
					nwritten += -field;
977
60798
					for ( ; field < 0 ; field++)
978
42306
						shf_putc(c, shf);
979
				}
980
			} else
981
				c = ' ';
982
		} else
983
			field = 0;
984
985
144575
		if (precision > 0) {
986
136768
			nwritten += precision;
987
1479850
			for ( ; precision-- > 0 ; s++)
988
1206314
				shf_putc(*s, shf);
989
		}
990
144575
		if (field > 0) {
991
			nwritten += field;
992
			for ( ; field > 0 ; --field)
993
				shf_putc(c, shf);
994
		}
995
	}
996
997
82030
	return shf_error(shf) ? EOF : nwritten;
998
82030
}