GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: bin/ksh/shf.c Lines: 368 538 68.4 %
Date: 2017-11-07 Branches: 238 430 55.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
115629
	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
38543
	shf = alloc(sizeof(struct shf) + bsize, ATEMP);
45
38543
	shf->areap = ATEMP;
46
38543
	shf->buf = (unsigned char *) &shf[1];
47
38543
	shf->bsize = bsize;
48
38543
	shf->flags = SHF_ALLOCS;
49
	/* Rest filled in by reopen. */
50
51
38543
	fd = open(name, oflags, mode);
52
38543
	if (fd < 0) {
53
85
		afree(shf, shf->areap);
54
85
		return NULL;
55
	}
56
38458
	if ((sflags & SHF_MAPHI) && fd < FDBASE) {
57
		int nfd;
58
59
38458
		nfd = fcntl(fd, F_DUPFD, FDBASE);
60
38458
		close(fd);
61
38458
		if (nfd < 0) {
62
			afree(shf, shf->areap);
63
			return NULL;
64
		}
65
		fd = nfd;
66
38458
	}
67
38458
	sflags &= ~SHF_ACCMODE;
68
76916
	sflags |= (oflags & O_ACCMODE) == O_RDONLY ? SHF_RD :
69
	    ((oflags & O_ACCMODE) == O_WRONLY ? SHF_WR : SHF_RDWR);
70
71
38458
	return shf_reopen(fd, sflags, shf);
72
38543
}
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
12196867
	int bsize = sflags & SHF_UNBUF ? (sflags & SHF_RD ? 1 : 0) : SHF_BSIZE;
79
80
	/* use fcntl() to figure out correct read/write flags */
81
4064700
	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
4064700
	if (!(sflags & (SHF_RD | SHF_WR)))
103
		internal_errorf(1, "shf_fdopen: missing read/write");
104
105
4064700
	if (shf) {
106
653310
		if (bsize) {
107
653310
			shf->buf = alloc(bsize, ATEMP);
108
653310
			sflags |= SHF_ALLOCB;
109
653310
		} else
110
			shf->buf = NULL;
111
	} else {
112
3411390
		shf = alloc(sizeof(struct shf) + bsize, ATEMP);
113
3411390
		shf->buf = (unsigned char *) &shf[1];
114
3411390
		sflags |= SHF_ALLOCS;
115
	}
116
4064700
	shf->areap = ATEMP;
117
4064700
	shf->fd = fd;
118
4064700
	shf->rp = shf->wp = shf->buf;
119
4064700
	shf->rnleft = 0;
120
4064700
	shf->rbsize = bsize;
121
4064700
	shf->wnleft = 0; /* force call to shf_emptybuf() */
122
4064700
	shf->wbsize = sflags & SHF_UNBUF ? 0 : bsize;
123
4064700
	shf->flags = sflags;
124
4064700
	shf->errno_ = 0;
125
4064700
	shf->bsize = bsize;
126
4064700
	if (sflags & SHF_CLEXEC)
127
		fcntl(fd, F_SETFD, FD_CLOEXEC);
128
4064700
	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
31535204
	int bsize = sflags & SHF_UNBUF ? (sflags & SHF_RD ? 1 : 0) : SHF_BSIZE;
136
137
	/* use fcntl() to figure out correct read/write flags */
138
10509880
	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
10509880
	if (!(sflags & (SHF_RD | SHF_WR)))
160
		internal_errorf(1, "shf_reopen: missing read/write");
161

31529640
	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
10509880
	shf->fd = fd;
166
10509880
	shf->rp = shf->wp = shf->buf;
167
10509880
	shf->rnleft = 0;
168
10509880
	shf->rbsize = bsize;
169
10509880
	shf->wnleft = 0; /* force call to shf_emptybuf() */
170
10509880
	shf->wbsize = sflags & SHF_UNBUF ? 0 : bsize;
171
10509880
	shf->flags = (shf->flags & (SHF_ALLOCS | SHF_ALLOCB)) | sflags;
172
10509880
	shf->errno_ = 0;
173
10509880
	if (sflags & SHF_CLEXEC)
174
38458
		fcntl(fd, F_SETFD, FD_CLOEXEC);
175
10509880
	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

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

7667522
	if (!buf && (sflags & SHF_WR) && (sflags & SHF_DYNAMIC)) {
200
85048
		if (bsize <= 0)
201
200
			bsize = 64;
202
85048
		sflags |= SHF_ALLOCB;
203
85048
		buf = alloc(bsize, shf->areap);
204
85048
	}
205
7497426
	shf->fd = -1;
206
7497426
	shf->buf = shf->rp = shf->wp = (unsigned char *) buf;
207
7497426
	shf->rnleft = bsize;
208
7497426
	shf->rbsize = bsize;
209
7497426
	shf->wnleft = bsize - 1;	/* space for a '\0' */
210
7497426
	shf->wbsize = bsize;
211
7497426
	shf->flags = sflags | SHF_STRING;
212
7497426
	shf->errno_ = 0;
213
7497426
	shf->bsize = bsize;
214
215
7497426
	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
6323456
	if (shf->fd >= 0) {
225
3155188
		ret = shf_flush(shf);
226
3155188
		if (close(shf->fd) < 0)
227
			ret = EOF;
228
	}
229
3161728
	if (shf->flags & SHF_ALLOCS)
230
3161728
		afree(shf, shf->areap);
231
	else if (shf->flags & SHF_ALLOCB)
232
		afree(shf->buf, shf->areap);
233
234
3161728
	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
14502
	if (shf->fd >= 0) {
244
7251
		ret = shf_flush(shf);
245
7251
		if (close(shf->fd) < 0)
246
			ret = EOF;
247
7251
		shf->rnleft = 0;
248
7251
		shf->rp = shf->buf;
249
7251
		shf->wnleft = 0;
250
7251
		shf->fd = -1;
251
7251
	}
252
253
7251
	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
14994852
	unsigned char *s = shf->buf;
264
265
	/* null terminate */
266
7497426
	if (shf->flags & SHF_WR) {
267
7497426
		shf->wnleft++;
268
14994852
		shf_putc('\0', shf);
269
	}
270
7497426
	if (shf->flags & SHF_ALLOCS)
271
		afree(shf, shf->areap);
272
7497426
	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
35993586
	if (shf->flags & SHF_STRING)
282
		return (shf->flags & SHF_WR) ? EOF : 0;
283
284
17996793
	if (shf->fd < 0)
285
		internal_errorf(1, "shf_flush: no fd");
286
287
17996793
	if (shf->flags & SHF_ERROR) {
288
		errno = shf->errno_;
289
		return EOF;
290
	}
291
292
17996793
	if (shf->flags & SHF_READING) {
293
3095078
		shf->flags &= ~(SHF_EOF | SHF_READING);
294
3095078
		if (shf->rnleft > 0) {
295
101722
			lseek(shf->fd, (off_t) -shf->rnleft, SEEK_CUR);
296
101722
			shf->rnleft = 0;
297
101722
			shf->rp = shf->buf;
298
101722
		}
299
3095078
		return 0;
300
14901715
	} else if (shf->flags & SHF_WRITING)
301
351172
		return shf_emptybuf(shf, 0);
302
303
14550543
	return 0;
304
17996793
}
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

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

54878450
		if (!(flags & EB_GROW) || !(shf->flags & SHF_DYNAMIC) ||
335
250
		    !(shf->flags & SHF_ALLOCB))
336
27438850
			return EOF;
337
		/* allocate more space for buffer */
338
250
		nbuf = areallocarray(shf->buf, 2, shf->wbsize, shf->areap);
339
250
		shf->rp = nbuf + (shf->rp - shf->buf);
340
250
		shf->wp = nbuf + (shf->wp - shf->buf);
341
250
		shf->rbsize += shf->wbsize;
342
250
		shf->wnleft += shf->wbsize;
343
250
		shf->wbsize *= 2;
344
250
		shf->buf = nbuf;
345
250
	} else {
346
564971
		if (shf->flags & SHF_WRITING) {
347
352035
			int ntowrite = shf->wp - shf->buf;
348
			unsigned char *buf = shf->buf;
349
			int n;
350
351
1286184
			while (ntowrite > 0) {
352
291057
				n = write(shf->fd, buf, ntowrite);
353
291057
				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
291057
				buf += n;
370
291057
				ntowrite -= n;
371
			}
372
352035
			if (flags & EB_READSW) {
373
				shf->wp = shf->buf;
374
				shf->wnleft = 0;
375
				shf->flags &= ~SHF_WRITING;
376
				return 0;
377
			}
378
352035
		}
379
564971
		shf->wp = shf->buf;
380
564971
		shf->wnleft = shf->wbsize;
381
	}
382
565221
	shf->flags |= SHF_WRITING;
383
384
565221
	return ret;
385
28004071
}
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
16810802
	if (shf->flags & SHF_STRING)
392
		return 0;
393
394
8405401
	if (shf->fd < 0)
395
		internal_errorf(1, "shf_fillbuf: no fd");
396
397
8405401
	if (shf->flags & (SHF_EOF | SHF_ERROR)) {
398
75
		if (shf->flags & SHF_ERROR)
399
			errno = shf->errno_;
400
75
		return EOF;
401
	}
402
403

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

23820781
		if (shf->rnleft < 0 && errno == EINTR &&
413
5138485
		    !(shf->flags & SHF_INTERRUPT))
414
			continue;
415
		break;
416
	}
417
8405326
	if (shf->rnleft <= 0) {
418
2964941
		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
2964941
		shf->flags |= SHF_EOF;
426
2964941
	}
427
8405326
	return 0;
428
8405401
}
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
40145188
	if (!(shf->flags & SHF_RD))
476
		internal_errorf(1, "shf_getse: flags %x", shf->flags);
477
478
20072594
	if (bsize <= 0)
479
		return NULL;
480
481
20072594
	--bsize;	/* save room for null */
482
20072594
	do {
483
21652215
		if (shf->rnleft == 0) {
484
1721738
			if (shf_fillbuf(shf) == EOF)
485
75
				return NULL;
486
1721663
			if (shf->rnleft == 0) {
487
12440
				*buf = '\0';
488
12440
				return buf == orig_buf ? NULL : buf;
489
			}
490
		}
491
43279400
		end = (unsigned char *) memchr((char *) shf->rp, '\n',
492
21639700
		    shf->rnleft);
493
64919100
		ncopy = end ? end - shf->rp + 1 : shf->rnleft;
494
21639700
		if (ncopy > bsize)
495
25
			ncopy = bsize;
496
21639700
		memcpy(buf, (char *) shf->rp, ncopy);
497
21639700
		shf->rp += ncopy;
498
21639700
		shf->rnleft -= ncopy;
499
21639700
		buf += ncopy;
500
21639700
		bsize -= ncopy;
501
21639700
	} while (!end && bsize);
502
20060079
	*buf = '\0';
503
20060079
	return buf;
504
20072594
}
505
506
/* Returns the char read.  Returns EOF for error and end of file. */
507
int
508
shf_getchar(struct shf *shf)
509
{
510
13367326
	if (!(shf->flags & SHF_RD))
511
		internal_errorf(1, "shf_getchar: flags %x", shf->flags);
512
513

20050989
	if (shf->rnleft == 0 && (shf_fillbuf(shf) == EOF || shf->rnleft == 0))
514
2952501
		return EOF;
515
3731162
	--shf->rnleft;
516
3731162
	return *shf->rp++;
517
6683663
}
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
9405470
	if (!(shf->flags & SHF_RD))
526
		internal_errorf(1, "shf_ungetc: flags %x", shf->flags);
527
528

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

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

202360142
		if (shf->wnleft == 0 && shf_emptybuf(shf, EB_GROW) == EOF)
588
27239971
			return EOF;
589
147868957
		shf->wnleft--;
590
147868957
		*shf->wp++ = c;
591
	}
592
593
147868957
	return c;
594
175108928
}
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
811556
	if (!s)
603
		return EOF;
604
605
405778
	return shf_write(s, strlen(s), shf);
606
405778
}
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
811806
	if (!(shf->flags & SHF_WR))
617
		internal_errorf(1, "shf_write: flags %x", shf->flags);
618
619
405903
	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

406003
	if ((ncopy = shf->wnleft) &&
624
147159
	    (shf->wp != shf->buf || nbytes < shf->wnleft)) {
625
147059
		if (ncopy > nbytes)
626
4200
			ncopy = nbytes;
627
147059
		memcpy(shf->wp, buf, ncopy);
628
147059
		nbytes -= ncopy;
629
147059
		buf += ncopy;
630
147059
		shf->wp += ncopy;
631
147059
		shf->wnleft -= ncopy;
632
147059
	}
633
405903
	if (nbytes > 0) {
634
		/* Flush deals with strings and sticky errors */
635
401685
		if (shf_emptybuf(shf, EB_GROW) == EOF)
636
198879
			return EOF;
637
202806
		if (nbytes > shf->wbsize) {
638
			ncopy = nbytes;
639
50622
			if (shf->wbsize)
640
50622
				ncopy -= nbytes % shf->wbsize;
641
50622
			nbytes -= ncopy;
642
202488
			while (ncopy > 0) {
643
50622
				n = write(shf->fd, buf, ncopy);
644
50622
				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
50622
				buf += n;
656
50622
				ncopy -= n;
657
			}
658
		}
659
202806
		if (nbytes > 0) {
660
202806
			memcpy(shf->wp, buf, nbytes);
661
202806
			shf->wp += nbytes;
662
202806
			shf->wnleft -= nbytes;
663
202806
		}
664
	}
665
666
207024
	return orig_nbytes;
667
405903
}
668
669
int
670
shf_fprintf(struct shf *shf, const char *fmt, ...)
671
{
672
289348
	va_list args;
673
	int n;
674
675
144674
	va_start(args, fmt);
676
144674
	n = shf_vfprintf(shf, fmt, args);
677
144674
	va_end(args);
678
679
144674
	return n;
680
144674
}
681
682
int
683
shf_snprintf(char *buf, int bsize, const char *fmt, ...)
684
{
685
409990
	struct shf shf;
686
204995
	va_list args;
687
	int n;
688
689
204995
	if (!buf || bsize <= 0)
690
		internal_errorf(1, "shf_snprintf: buf %lx, bsize %d",
691
			(long) buf, bsize);
692
693
204995
	shf_sopen(buf, bsize, SHF_WR, &shf);
694
204995
	va_start(args, fmt);
695
204995
	n = shf_vfprintf(&shf, fmt, args);
696
204995
	va_end(args);
697
204995
	shf_sclose(&shf); /* null terminates */
698
204995
	return n;
699
204995
}
700
701
char *
702
shf_smprintf(const char *fmt, ...)
703
{
704
400
	struct shf shf;
705
200
	va_list args;
706
707
200
	shf_sopen(NULL, 0, SHF_WR|SHF_DYNAMIC, &shf);
708
200
	va_start(args, fmt);
709
200
	shf_vfprintf(&shf, fmt, args);
710
200
	va_end(args);
711
400
	return shf_sclose(&shf); /* null terminates */
712
200
}
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
847922
	char		numbuf[(BITS(long long) + 2) / 3 + 1];
737
	/* this stuff for dealing with the buffer */
738
	int		nwritten = 0;
739
740
423961
	if (!fmt)
741
		return 0;
742
743
3300411
	while ((c = *fmt++)) {
744
2876450
		if (c != '%') {
745
4758312
			shf_putc(c, shf);
746
2379156
			nwritten++;
747
2379156
			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
1049697
		for ( ; (c = *fmt++) ; ) {
758


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

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


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

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

2107
				if (c == 'd' || c == 'i')
855
6117
					llnum = va_arg(args, int);
856
				else
857
102
					llnum = va_arg(args, unsigned int);
858
			}
859

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

68
				if ((flags & FL_HASH) && *s != '0')
891
34
					*--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
19803
			len = &numbuf[sizeof(numbuf)] - s;
912
19803
			if (flags & FL_DOT) {
913
34
				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
1431873
			if (!(s = va_arg(args, char *)))
923
				s = "(null %s)";
924
477291
			len = strlen(s);
925
477291
			break;
926
927
		case 'c':
928
200
			flags &= ~FL_DOT;
929
600
			numbuf[0] = va_arg(args, int);
930
200
			s = numbuf;
931
			len = 1;
932
200
			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

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

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

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

5491
						if (--precision > 0 &&
965
						    (*s | 0x20) == 'x') {
966
							shf_putc(*s, shf);
967
							s++;
968
							precision--;
969
							nwritten++;
970
						}
971
					}
972
					c = '0';
973
8021
				} else
974
7395
					c = flags & FL_ZERO ? '0' : ' ';
975
15416
				if (field < 0) {
976
15416
					nwritten += -field;
977
97468
					for ( ; field < 0 ; field++)
978
66636
						shf_putc(c, shf);
979
				}
980
			} else
981
				c = ' ';
982
		} else
983
			field = 0;
984
985
497294
		if (precision > 0) {
986
480953
			nwritten += precision;
987
5422784
			for ( ; precision-- > 0 ; s++)
988
4460878
				shf_putc(*s, shf);
989
		}
990
497294
		if (field > 0) {
991
3026
			nwritten += field;
992
31436
			for ( ; field > 0 ; --field)
993
25384
				shf_putc(c, shf);
994
		}
995
	}
996
997
423961
	return shf_error(shf) ? EOF : nwritten;
998
423961
}