still broken
This commit is contained in:
		
							parent
							
								
									71612d7308
								
							
						
					
					
						commit
						159f95a975
					
				
							
								
								
									
										282
									
								
								dj/dj.c
									
									
									
									
									
								
							
							
						
						
									
										282
									
								
								dj/dj.c
									
									
									
									
									
								
							| @ -7,10 +7,60 @@ | |||||||
| #include <sysexits.h> /* EX_OK, EX_USAGE */ | #include <sysexits.h> /* EX_OK, EX_USAGE */ | ||||||
| #include <unistd.h> /* close(2), getopt(3), lseek(2), read(2), write(2), | #include <unistd.h> /* close(2), getopt(3), lseek(2), read(2), write(2), | ||||||
|                        optarg, optind, STDIN_FILENO, STDOUT_FILENO */ |                        optarg, optind, STDIN_FILENO, STDOUT_FILENO */ | ||||||
|  | extern int errno; | ||||||
| 
 | 
 | ||||||
| /* Macro to use the appropriate string for argv[0] in the case that
 | /* dj uses two structures that respectively correspond to the reading and
 | ||||||
|  * argc == 0. */ |  * writing ends of its jockeyed "pipe". User-configurable members are noted | ||||||
| #define ARGV0(argv0) ((argv0) == NULL ? program_name : (argv0)) |  * with their relevant options. */ | ||||||
|  | struct Io{ | ||||||
|  | 	int bs;			/* buffer size (-bB) */ | ||||||
|  | 	size_t bufuse;	/* buffer usage */ | ||||||
|  | 	char *buf;		/* buffer */ | ||||||
|  | 	int bytes;		/* bytes processed */ | ||||||
|  | 	int fd;			/* file descriptor */ | ||||||
|  | 	int fl;			/* file opening flags */ | ||||||
|  | 	char *fn;		/* file name (may be stdin_name or stdout_name) (-io) */ | ||||||
|  | 	int prec;		/* partial records processed */ | ||||||
|  | 	int rec;		/* records processed */ | ||||||
|  | 	long seek;		/* bytes to seek/skip (will be 0 after skippage) (-sS) */ | ||||||
|  | } ep[2]; /* "engineered pipe"; also "extended play", for the deejay */ | ||||||
|  | 
 | ||||||
|  | /* Additionally, the following global variables are used to store user options.
 | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | /* (-a)  */ static int align; /* Only the lower 8b are used but align is
 | ||||||
|  |                                * negative if no alignment is being done. */ | ||||||
|  | 
 | ||||||
|  | /* (-c)  */ static int count; /* 0 if dj(1) runs until no more reads are
 | ||||||
|  |                                * possible. */ | ||||||
|  | 
 | ||||||
|  | /* ASCII field separator delimited statistics */ | ||||||
|  |             static char *fmt_asv   = "%d\037%d\036%d\037%d\035%d\036%d\034"; | ||||||
|  | /* human-readable statistics */ | ||||||
|  |             static char *fmt_human = "%d+%d > %d+%d; %d > %d\n"; | ||||||
|  | /* pointer to chosen formatting */ | ||||||
|  | /* (-H)  */ static char *fmt_output; /* fmt_asv (default) or fmt_human (-H) */ | ||||||
|  | 
 | ||||||
|  | /* (-dq) */ static char debug;       /*
 | ||||||
|  |  *  -d  increments             dj -qq | 0 - no diagnostic output whatsoever | ||||||
|  |  *   -q decrements             dj -q  | 1 - typical output without | ||||||
|  |  *                                    |     notifications on partial reads or | ||||||
|  |  *                                    |     writes | ||||||
|  |  *                             dj     | 2 - typical output (default) | ||||||
|  |  *                             dj -d  | 3 - verbose status messages */ | ||||||
|  | 
 | ||||||
|  | /* (-f)  */ static char noerror;     /* 0 - exits on partial reads or writes
 | ||||||
|  |                                       *     (default) | ||||||
|  |                                       * 1 - retries on partial reads/writes | ||||||
|  |                                       *     (-f) */ | ||||||
|  | 
 | ||||||
|  | /* Non-configurable defaults. */ | ||||||
|  | #define bs_default 1024 | ||||||
|  | static char *program_name = "<no argv[0]>"; | ||||||
|  | static char *stdin_name = "<stdin>"; | ||||||
|  | static char *stdout_name = "<stdout>"; | ||||||
|  | static int read_flags = O_RDONLY; | ||||||
|  | static int write_flags = O_WRONLY | O_CREAT; | ||||||
| 
 | 
 | ||||||
| #define MIN(a, b) (((a) < (b)) ? (a) : (b)) | #define MIN(a, b) (((a) < (b)) ? (a) : (b)) | ||||||
| 
 | 
 | ||||||
| @ -20,6 +70,18 @@ | |||||||
| 		|| (fd) == STDOUT_FILENO \ | 		|| (fd) == STDOUT_FILENO \ | ||||||
| 		|| (fd) == STDERR_FILENO) | 		|| (fd) == STDERR_FILENO) | ||||||
| 
 | 
 | ||||||
|  | /* Macro to set defaults for user-configurable options. */ | ||||||
|  | #define setdefaults do{ \ | ||||||
|  | 	align = -1; \ | ||||||
|  | 	count = 0; \ | ||||||
|  | 	debug = 2; \ | ||||||
|  | 	fmt_output = fmt_asv; \ | ||||||
|  | 	noerror = 0; \ | ||||||
|  | 	ep[0].fl = read_flags; \ | ||||||
|  | 	Io_setdefaults(&ep[0]); \ | ||||||
|  | 	ep[1].fl = write_flags; \ | ||||||
|  | 	Io_setdefaults(&ep[1]); }while(0) | ||||||
|  | 
 | ||||||
| /* Macro to call the cleanup functions that operate on struct io on the
 | /* Macro to call the cleanup functions that operate on struct io on the
 | ||||||
|  * particular io[2] used in main. Error conditions are not checked because this |  * particular io[2] used in main. Error conditions are not checked because this | ||||||
|  * is only used when the program is about to terminate (hence its name). */ |  * is only used when the program is about to terminate (hence its name). */ | ||||||
| @ -29,31 +91,7 @@ | |||||||
| 	Io_fdclose(&(io)[0]); \ | 	Io_fdclose(&(io)[0]); \ | ||||||
| 	Io_fdclose(&(io)[1]); }while(0) | 	Io_fdclose(&(io)[1]); }while(0) | ||||||
| 
 | 
 | ||||||
| extern int errno; | /* Allocates *io's buffer. Returns NULL if unsuccessful. */ | ||||||
| static char *fmt_asv = "%d\037%d\036%d\037%d\035%d\036%d\034"; |  | ||||||
| static char *fmt_human = "%d+%d > %d+%d; %d > %d\n"; |  | ||||||
| static char *fmt_output; |  | ||||||
| static char *program_name = "<no argv[0]>"; |  | ||||||
| static char *stdin_name = "<stdin>"; |  | ||||||
| static char *stdout_name = "<stdout>"; |  | ||||||
| static int read_flags = O_RDONLY; |  | ||||||
| static int write_flags = O_WRONLY | O_CREAT; |  | ||||||
| 
 |  | ||||||
| /* information that needs to be kept about each file in the "pipe" */ |  | ||||||
| struct Io{ |  | ||||||
| 	int bs;			/* buffer size */ |  | ||||||
| 	size_t bufuse;	/* buffer usage */ |  | ||||||
| 	char *buf;		/* buffer */ |  | ||||||
| 	int bytes;		/* bytes processed */ |  | ||||||
| 	int fd;			/* file descriptor */ |  | ||||||
| 	int fl;			/* file opening flags */ |  | ||||||
| 	char *fn;		/* file name (may be stdin_name or stdout_name) */ |  | ||||||
| 	int prec;		/* partial records processed */ |  | ||||||
| 	int rec;		/* records processed */ |  | ||||||
| 	long seek;		/* bytes to seek/skip (will be 0 after skippage) */ |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| /* Allocates *io's buffer. Returns NULL if successful. */ |  | ||||||
| static void * | static void * | ||||||
| Io_bufalloc(struct Io *io){ | Io_bufalloc(struct Io *io){ | ||||||
| 
 | 
 | ||||||
| @ -137,17 +175,6 @@ Io_fdopen(struct Io *io, char *fn){ | |||||||
| 	return fd; | 	return fd; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /* Reads io->bs bytes from *io's file descriptor into io->buf, storing the
 |  | ||||||
|  * number of read bytes in io->bufuse and updating io->bytes. If io->bufuse is |  | ||||||
|  * 0, errno will probably be set. Returns io. */ |  | ||||||
| static struct Io * |  | ||||||
| Io_read(struct Io *io){ |  | ||||||
| 
 |  | ||||||
| 	io->bytes += (io->bufuse = read(io->fd, io->buf, io->bs)); |  | ||||||
| 
 |  | ||||||
| 	return io; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /* Seeks io->seek bytes through *io's file descriptor, (counter-intuitively)
 | /* Seeks io->seek bytes through *io's file descriptor, (counter-intuitively)
 | ||||||
|  * returning -1 if successful and a sysexits.h exit code if an unrecoverable |  * returning -1 if successful and a sysexits.h exit code if an unrecoverable | ||||||
|  * error occurred. io->buf will be cleared of useful bytes and io->seek will |  * error occurred. io->buf will be cleared of useful bytes and io->seek will | ||||||
| @ -186,12 +213,23 @@ Io_fdseek(struct Io *io){ | |||||||
| 	return -1; | 	return -1; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | /* Reads io->bs bytes from *io's file descriptor into io->buf, storing the
 | ||||||
|  |  * number of read bytes in io->bufuse and updating io->bytes. If io->bufuse is | ||||||
|  |  * 0, errno will probably be set. Returns io. */ | ||||||
|  | static struct Io * | ||||||
|  | Io_read(struct Io *io){ | ||||||
|  | 
 | ||||||
|  | 	io->bytes += (io->bufuse = read(io->fd, io->buf, io->bs)); | ||||||
|  | 
 | ||||||
|  | 	return io; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| /* Sets the variables in a struct *io to the defaults. Identifies the read/
 | /* Sets the variables in a struct *io to the defaults. Identifies the read/
 | ||||||
|  * write ends of the "pipe" by checking io->fl. Returns io. */ |  * write ends of the "pipe" by checking io->fl. Returns io. */ | ||||||
| static struct Io * | static struct Io * | ||||||
| Io_setdefaults(struct Io *io){ | Io_setdefaults(struct Io *io){ | ||||||
| 
 | 
 | ||||||
| 	io->bs = 1024; | 	io->bs = bs_default; | ||||||
| 	io->buf = NULL; | 	io->buf = NULL; | ||||||
| 	io->bytes = 0; | 	io->bytes = 0; | ||||||
| 	io->fd = (io->fl == read_flags) ? STDIN_FILENO : STDOUT_FILENO; | 	io->fd = (io->fl == read_flags) ? STDIN_FILENO : STDOUT_FILENO; | ||||||
| @ -220,23 +258,24 @@ Io_write(struct Io *io){ | |||||||
| /* Prints an error message suitable for the event of an operating system error,
 | /* Prints an error message suitable for the event of an operating system error,
 | ||||||
|  * with the error itself to be described in the string s. */ |  * with the error itself to be described in the string s. */ | ||||||
| static int | static int | ||||||
| oserr(char *argv0, char *s){ | oserr(char *s){ | ||||||
| 
 | 
 | ||||||
| 	fprintf(stderr, "%s: %s: %s\n", argv0, s, strerror(errno)); | 	fprintf(stderr, "%s: %s: %s\n", program_name, s, strerror(errno)); | ||||||
| 
 | 
 | ||||||
| 	return EX_OSERR; | 	return EX_OSERR; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /* Prints statistics regarding the use of dj, particularly partially and
 | /* Prints statistics regarding the use of dj, particularly partially and
 | ||||||
|  * completely read and written records. */ |  * completely read and written records, accessing debug, ep, and fmt_output. */ | ||||||
| struct Io * | static void | ||||||
| output(struct Io io[2]){ | output(void){ | ||||||
| 
 | 
 | ||||||
| 	fprintf(stderr, fmt_output, | 	if(debug >= 1) | ||||||
| 		io[0].rec, io[0].prec, io[1].rec, io[1].prec, | 		fprintf(stderr, fmt_output, | ||||||
| 		io[0].bytes, io[1].bytes); | 			ep[0].rec, ep[0].prec, ep[1].rec, ep[1].prec, | ||||||
|  | 			ep[0].bytes, ep[1].bytes); | ||||||
| 
 | 
 | ||||||
| 	return io; | 	return; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /* Parses the string s to an integer, returning either the integer or in the
 | /* Parses the string s to an integer, returning either the integer or in the
 | ||||||
| @ -247,58 +286,43 @@ parse(char *s){ | |||||||
| 	long r; | 	long r; | ||||||
| 
 | 
 | ||||||
| 	errno = 0; | 	errno = 0; | ||||||
| 	r = (long)strtol(s, &s, 0); | 	r = strtol(s, &s, 0); | ||||||
| 	if(*s == '\0' /* no chars left unparsed */ && errno == 0) | 	return (*s == '\0' /* no chars left unparsed */ && errno == 0) | ||||||
| 		return r; | 		? r | ||||||
| 	else | 		: -1; | ||||||
| 		return -1; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int | static int | ||||||
| usage(char *argv0){ | usage(void){ | ||||||
| 
 | 
 | ||||||
| 	fprintf(stderr, "Usage: %s (-AdfHqQ) (-a [byte]) (-c [count])\n" | 	fprintf(stderr, "Usage: %s (-AdfHqQ) (-a [byte]) (-c [count])\n" | ||||||
| 		"\t(-i [input file]) (-b [input block size]) (-s [input offset])\n" | 		"\t(-i [input file]) (-b [input block size]) (-s [input offset])\n" | ||||||
| 		"\t(-o [output file]) (-B [output block size]) (-S [output offset])\n", | 		"\t(-o [output file]) (-B [output block size]) (-S [output offset])\n", | ||||||
| 		ARGV0(argv0)); | 		program_name); | ||||||
| 
 | 
 | ||||||
| 	return EX_USAGE; | 	return EX_USAGE; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int main(int argc, char *argv[]){ | int main(int argc, char *argv[]){ | ||||||
| 	int align; |  | ||||||
| 	char debug; |  | ||||||
| 	char noerror; |  | ||||||
| 	int c; | 	int c; | ||||||
| 	int count; | 	int i; | ||||||
| 	int p; /* pipe side */ |  | ||||||
| 	struct Io io[2]; /* { read, write } same as pipe(2) */ |  | ||||||
| 
 | 
 | ||||||
| 	/* defaults */ | 	setdefaults; | ||||||
| 	align = -1; |  | ||||||
| 	count = 0; |  | ||||||
| 	debug = 2; |  | ||||||
| 	fmt_output = fmt_asv; |  | ||||||
| 	noerror = 0; |  | ||||||
| 	io[0].fl = read_flags; |  | ||||||
| 	Io_setdefaults(&io[0]); |  | ||||||
| 	io[1].fl = write_flags; |  | ||||||
| 	Io_setdefaults(&io[1]); |  | ||||||
| 
 | 
 | ||||||
| 	if(argc > 0) | 	if(argc > 0){ | ||||||
| 		while((c = getopt(argc, argv, "a:Ab:B:c:di:fhHqQs:S:o:")) != -1) | 		program_name = argv[0]; | ||||||
|  | 		while((c = getopt(argc, argv, "a:Ab:B:c:di:fhHqs:S:o:")) != -1) | ||||||
| 			switch(c){ | 			switch(c){ | ||||||
| 			case 'i': case 'o': | 			case 'i': case 'o': | ||||||
| 				if(Io_fdopen(&io[c == 'o'], optarg) != -1) | 				if(Io_fdopen(&ep[c == 'o'], optarg) != -1) | ||||||
| 					break; | 					break; | ||||||
| 				terminate(io); | 				terminate(ep); | ||||||
| 				return oserr(argv[0], optarg); | 				return oserr(optarg); | ||||||
| 			case 'A': align = '\0'; break; | 			case 'A': align = '\0'; break; | ||||||
| 			case 'd': debug = 3; break; | 			case 'd': ++debug; break; | ||||||
| 			case 'f': noerror = 1; break; | 			case 'f': noerror = 1; break; | ||||||
| 			case 'H': fmt_output = fmt_human; break; | 			case 'H': fmt_output = fmt_human; break; | ||||||
| 			case 'q': /* be quiet / BE QUIET */ | 			case 'q': --debug; break; | ||||||
| 			case 'Q': debug -= 1 + (c == 'Q'); break; |  | ||||||
| 			case 'a': | 			case 'a': | ||||||
| 				if(optarg[0] != '\0' && optarg[1] == '\0'){ | 				if(optarg[0] != '\0' && optarg[1] == '\0'){ | ||||||
| 					align = optarg[0]; | 					align = optarg[0]; | ||||||
| @ -307,97 +331,97 @@ int main(int argc, char *argv[]){ | |||||||
| 			case 'c': case 'b': case 's': case 'B': case 'S': | 			case 'c': case 'b': case 's': case 'B': case 'S': | ||||||
| 				if(c == 'c' && (count = parse(optarg)) >= 0) | 				if(c == 'c' && (count = parse(optarg)) >= 0) | ||||||
| 					break; | 					break; | ||||||
| 				p = isupper(c); | 				i = isupper(c); | ||||||
| 				c = tolower(c); | 				c = tolower(c); | ||||||
| 				if((c == 'b' && (io[p].bs = parse(optarg)) > 0) | 				if((c == 'b' && (ep[i].bs = parse(optarg)) > 0) | ||||||
| 						|| (c == 's' && (io[p].seek = parse(optarg)) >= 0)) | 						|| (c == 's' && (ep[i].seek = parse(optarg)) >= 0)) | ||||||
| 					break; | 					break; | ||||||
| 			default: | 			default: | ||||||
| 				terminate(io); | 				terminate(ep); | ||||||
| 				return usage(argv[0]); | 				return usage(); | ||||||
| 			} | 			} | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 	if(debug >= 3) | 	if(debug >= 3) | ||||||
| 		fprintf(stderr, | 		fprintf(stderr, | ||||||
| 			"argv0=%s\n" | 			"argv0=%s\n" | ||||||
| 			"in=%s\tibs=%d\tskip=%ld\talign=%hhx\tcount=%d\n" | 			"in=%s\tibs=%d\tskip=%ld\talign=%hhx\tcount=%d\n" | ||||||
| 			"out=%s\tobs=%d\tseek=%ld\tdebug=%2d\tnoerror=%d\n", | 			"out=%s\tobs=%d\tseek=%ld\tdebug=%2d\tnoerror=%d\n", | ||||||
| 			ARGV0(argv[0]), | 			program_name, | ||||||
| 			io[0].fn, io[0].bs, io[0].seek, align, count, | 			ep[0].fn, ep[0].bs, ep[0].seek, align, count, | ||||||
| 			io[1].fn, io[1].bs, io[1].seek, debug, noerror); | 			ep[1].fn, ep[1].bs, ep[1].seek, debug, noerror); | ||||||
| 
 | 
 | ||||||
| 	if(argc > optind){ | 	if(argc > optind){ | ||||||
| 		terminate(io); | 		terminate(ep); | ||||||
| 		return usage(argv[0]); | 		return usage(); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	for(p = 0; p <= 1; ++p){ | 	for(i = 0; i <= 1; ++i){ | ||||||
| 		if(Io_bufalloc(&io[p]) == NULL){ | 		if(Io_bufalloc(&ep[i]) == NULL){ | ||||||
| 			fprintf(stderr, "%s: Failed to allocate %d bytes\n", | 			fprintf(stderr, "%s: Failed to allocate %d bytes\n", | ||||||
| 				ARGV0(argv[0]), io[p].bs); | 				program_name, ep[i].bs); | ||||||
| 			terminate(io); | 			terminate(ep); | ||||||
| 			return EX_OSERR; | 			return EX_OSERR; | ||||||
| 		}else if(io[p].seek > 0) | 		}else if(ep[i].seek > 0) | ||||||
| 			switch(Io_fdseek(&io[p])){ | 			switch(Io_fdseek(&ep[i])){ | ||||||
| 			case EX_OK: | 			case EX_OK: | ||||||
| 				if(debug >= 1) | 				output(); | ||||||
| 					output(io); | 				terminate(ep); | ||||||
| 				terminate(io); |  | ||||||
| 				return EX_OK; | 				return EX_OK; | ||||||
| 			} | 			} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	do{	/* read */ | 	do{	/* read */ | ||||||
| 		Io_read(&io[0]); | 		Io_read(&ep[0]); | ||||||
| 		if(!noerror && io[0].bufuse == 0) | 		if(!noerror && ep[0].bufuse == 0) | ||||||
| 			Io_read(&io[0]); /* second chance */ | 			Io_read(&ep[0]); /* second chance */ | ||||||
| 		if(io[0].bufuse == 0) /* that's all she wrote */ | 		if(ep[0].bufuse == 0) /* that's all she wrote */ | ||||||
| 			break; | 			break; | ||||||
| 		else if(io[0].bufuse < io[0].bs){ | 		else if(ep[0].bufuse < ep[0].bs){ | ||||||
| 			++io[0].prec; | 			++ep[0].prec; | ||||||
| 			if(debug >= 2){ | 			if(debug >= 2){ | ||||||
| 				fprintf(stderr, "%s: Partial read:\n\t", ARGV0(argv[0])); | 				fprintf(stderr, "%s: Partial read:\n\t", program_name); | ||||||
| 				output(io); | 				output(); | ||||||
| 			} | 			} | ||||||
| 			if(!noerror) | 			if(!noerror) | ||||||
| 				count = 1; | 				count = 1; | ||||||
| 			if(align >= 0) | 			if(align >= 0) | ||||||
| 				Io_bufrpad(&io[0], align); | 				Io_bufrpad(&ep[0], align); | ||||||
| 		}else | 		}else | ||||||
| 			++io[0].rec; | 			++ep[0].rec; | ||||||
| 
 | 
 | ||||||
| 		/* write */ | 		/* write */ | ||||||
| 		do{	if(io[1].bs > io[0].bs){ /* io[1].bs > io[0].bs */ | 		do{	if(ep[1].bs > ep[0].bs){ /* io[1].bs > io[0].bs */ | ||||||
| 				Io_bufxapp(&io[1], &io[0]); | 				Io_bufxapp(&ep[1], &ep[0]); | ||||||
| 				if(io[0].bs + io[1].bufuse <= io[1].bs && count != 1) | 				if(ep[0].bs + ep[1].bufuse <= ep[1].bs && count != 1) | ||||||
| 					continue; /* we could write more */ | 					continue; /* we could write more */ | ||||||
| 			}else | 			}else | ||||||
| 				Io_bufxfer(&io[1], &io[0], MIN(io[0].bufuse, io[1].bs)); | 				Io_bufxfer(&ep[1], &ep[0], MIN(ep[0].bufuse, ep[1].bs)); | ||||||
| 
 | 
 | ||||||
| 			c = io[1].bufuse; | 			c = ep[1].bufuse; | ||||||
| 			Io_write(&io[1]); | 			Io_write(&ep[1]); | ||||||
| 			if(!noerror && io[1].bufuse == c) | 			if(!noerror && ep[1].bufuse == c) | ||||||
| 				Io_write(&io[1]); /* second chance */ | 				Io_write(&ep[1]); /* second chance */ | ||||||
| 			if(c == io[1].bufuse) /* no more love */ | 			if(c == ep[1].bufuse){ /* no more love */ | ||||||
| 				count = 1; | 				count = 1; | ||||||
| 			else if(c > io[1].bufuse && io[1].bufuse > 0){ | 				break; | ||||||
| 				io[1].prec += 1; | 			}else if(c > ep[1].bufuse && ep[1].bufuse > 0){ | ||||||
|  | 				ep[1].prec += 1; | ||||||
| 				if(debug >= 2){ | 				if(debug >= 2){ | ||||||
| 					fprintf(stderr, "%s: Partial write:\n\t", ARGV0(argv[0])); | 					fprintf(stderr, "%s: Partial write:\n\t", program_name); | ||||||
| 					output(io); | 					output(); | ||||||
| 				} | 				} | ||||||
| 				if(!noerror) | 				if(!noerror) | ||||||
| 					count = 1; | 					count = 1; | ||||||
| 			}else if(io[1].bufuse == 0 && c < io[1].bs) | 			}else if(ep[1].bufuse == 0 && c < ep[1].bs) | ||||||
| 				++io[1].prec; | 				++ep[1].prec; | ||||||
| 			else | 			else | ||||||
| 				++io[1].rec; | 				++ep[1].rec; | ||||||
| 		}while(io[0].bufuse > 0); | 		}while(ep[0].bufuse > 0); | ||||||
| 	}while(count == 0 || --count > 0); | 	}while(count == 0 || --count > 0); | ||||||
| 
 | 
 | ||||||
| 	if(debug >= 1) | 	output(); | ||||||
| 		output(io); | 	terminate(ep); | ||||||
| 	terminate(io); |  | ||||||
| 
 | 
 | ||||||
| 	return EX_OK; | 	return EX_OK; | ||||||
| } | } | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user