ANSI, make exit codes consistent
[unix-history] / usr / src / usr.bin / xargs / xargs.c
CommitLineData
c599959c
KB
1/*-
2 * Copyright (c) 1990 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * John B. Roll Jr.
7 *
8 * %sccs.include.redist.c%
9 */
10
11#ifndef lint
12char copyright[] =
13"@(#) Copyright (c) 1990 The Regents of the University of California.\n\
14 All rights reserved.\n";
15#endif /* not lint */
16
17#ifndef lint
d777ab9d 18static char sccsid[] = "@(#)xargs.c 5.5 (Berkeley) %G%";
c599959c
KB
19#endif /* not lint */
20
21#include <sys/types.h>
22#include <sys/wait.h>
23#include <errno.h>
24#include <stdio.h>
38dde0cd 25#include <string.h>
c599959c
KB
26#include <limits.h>
27#include "pathnames.h"
28
29#define DEF_ARGC 255
30
31int tflag;
32
33main(argc, argv)
34 int argc;
35 char **argv;
36{
37 extern int errno, optind;
38 extern char *optarg;
39 register int ch;
40 register char *p, *bp, *endbp, **bxp, **endxp, **xp;
41 int cnt, indouble, insingle, nargs, nline;
42 char *mark, *prog, **xargs, *malloc();
43
44 nargs = DEF_ARGC;
d777ab9d 45 nline = _POSIX2_LINE_MAX;
c599959c
KB
46
47 while ((ch = getopt(argc, argv, "n:s:t")) != EOF)
48 switch(ch) {
49 case 'n':
50 if ((nargs = atoi(optarg)) <= 0) {
51 (void)fprintf(stderr,
52 "xargs: bad argument count.\n");
53 exit(1);
54 }
55 break;
56 case 's':
57 if ((nline = atoi(optarg)) <= 0) {
58 (void)fprintf(stderr,
59 "xargs: bad command length.\n");
60 exit(1);
61 }
62 break;
63 case 't':
64 tflag = 1;
65 break;
66 case '?':
67 default:
68 usage();
69 }
70 argc -= optind;
71 argv += optind;
72
73 /* room for the command, leftover arguments and trailing NULL */
74 if (!(xargs =
75 (char **)malloc((u_int)(nargs + argc + 2) * sizeof(char **))))
76 enomem();
77
78 if (!(bp = malloc((u_int)nline + 1)))
79 enomem();
80
81 xp = xargs + 1;
82 if (!*argv)
83 prog = _PATH_ECHO;
84 else {
85 prog = *argv;
86 while (*++argv)
87 *xp++ = *argv;
88 }
89
90 if (xargs[0] = rindex(prog, '/'))
91 ++xargs[0];
92 else
93 xargs[0] = prog;
94
95 /* set up the pointers into the buffer and the arguments */
96 *(endxp = (bxp = xp) + nargs) = NULL;
97 endbp = (mark = p = bp) + nline;
98
99 insingle = indouble = 0;
100 for (;;)
101 switch(ch = getchar()) {
102 case EOF:
8add0d2b 103 if (p == bp) /* nothing to display */
c599959c 104 exit(0);
8add0d2b
KB
105 if (mark == p) { /* nothing since last arg end */
106 run(prog, xargs);
107 exit(0);
108 }
c599959c
KB
109 goto addarg;
110 case ' ':
111 case '\t':
112 if (insingle || indouble)
113 goto addch;
114 goto addarg;
115 case '\n':
116 if (mark == p) /* empty line */
117 continue;
118addarg: *xp++ = mark;
119 *p++ = '\0';
120 if (xp == endxp || p >= endbp || ch == EOF) {
121 if (insingle || indouble) {
122 (void)fprintf(stderr,
123 "xargs: unterminated quote.\n");
124 exit(1);
125 }
126 run(prog, xargs);
127 if (ch == EOF)
128 exit(0);
129 p = bp;
130 xp = bxp;
131 }
132 mark = p;
133 break;
134 case '\'':
135 if (indouble)
136 goto addch;
137 insingle = !insingle;
138 break;
139 case '"':
140 if (insingle)
141 goto addch;
142 indouble = !indouble;
143 break;
144 case '\\':
145 if ((ch = getchar()) == EOF)
146 ch = '\\';
147 if (ch == '\n') {
148 (void)fprintf(stderr,
149 "xargs: newline may not be escaped.\n");
150 exit(1);
151 }
152 /* FALLTHROUGH */
153 default:
154addch: if (p != endbp) {
155 *p++ = ch;
156 continue;
157 }
158 if (xp == bxp) {
159 (void)fprintf(stderr,
160 "xargs: argument too large.\n");
161 exit(1);
162 }
163 *xp = NULL;
164 run(prog, xargs);
165 cnt = endbp - mark;
166 bcopy(mark, bp, cnt);
167 p = (mark = bp) + cnt;
168 *p++ = ch;
169 xp = bxp;
170 break;
171 }
172 /* NOTREACHED */
173}
174
175run(prog, argv)
176 char *prog, **argv;
177{
178 union wait pstat;
179 pid_t pid, waitpid();
180 char **p;
181
182 if (tflag) {
183 (void)fprintf(stderr, "%s", *argv);
184 for (p = argv + 1; *p; ++p)
185 (void)fprintf(stderr, " %s", *p);
186 (void)fprintf(stderr, "\n");
187 (void)fflush(stderr);
188 }
189 switch(pid = vfork()) {
190 case -1:
191 (void)fprintf(stderr,
192 "xargs: vfork: %s.\n", strerror(errno));
193 exit(1);
194 case 0:
195 execvp(prog, argv);
196 (void)fprintf(stderr,
197 "xargs: %s: %s.\n", prog, strerror(errno));
198 _exit(1);
199 }
200 pid = waitpid(pid, &pstat, 0);
201 if (pid == -1) {
202 (void)fprintf(stderr,
203 "xargs: waitpid: %s.\n", strerror(errno));
204 exit(1);
205 }
206 if (pstat.w_status)
207 exit(1);
208}
209
210enomem()
211{
212 (void)fprintf(stderr, "xargs: %s.\n", strerror(ENOMEM));
213 exit(1);
214}
215
216usage()
217{
218 (void)fprintf(stderr,
219 "xargs: [-t] [-n number] [-s size] [utility [argument ...]]\n");
220 exit(1);
221}