|
|
1.1 root 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: * Redistribution and use in source and binary forms are permitted provided
9: * that: (1) source distributions retain this entire copyright notice and
10: * comment, and (2) distributions including binaries display the following
11: * acknowledgement: ``This product includes software developed by the
12: * University of California, Berkeley and its contributors'' in the
13: * documentation or other materials provided with the distribution and in
14: * all advertising materials mentioning features or use of this software.
15: * Neither the name of the University nor the names of its contributors may
16: * be used to endorse or promote products derived from this software without
17: * specific prior written permission.
18: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
19: * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
20: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
21: */
22:
23: #ifndef lint
24: char copyright[] =
25: "@(#) Copyright (c) 1990 The Regents of the University of California.\n\
26: All rights reserved.\n";
27: #endif /* not lint */
28:
29: #ifndef lint
30: static char sccsid[] = "@(#)xargs.c 5.4 (Berkeley) 6/24/90";
31: #endif /* not lint */
32:
33: #include <sys/types.h>
34: #include <sys/wait.h>
35: #include <errno.h>
36: #include <stdio.h>
37: #include <string.h>
38: #include <limits.h>
39: #include "pathnames.h"
40:
41: #define DEF_ARGC 255
42:
43: int tflag;
44:
45: main(argc, argv)
46: int argc;
47: char **argv;
48: {
49: extern int errno, optind;
50: extern char *optarg;
51: register int ch;
52: register char *p, *bp, *endbp, **bxp, **endxp, **xp;
53: int cnt, indouble, insingle, nargs, nline;
54: char *mark, *prog, **xargs, *malloc();
55:
56: nargs = DEF_ARGC;
57: nline = _BSD_LINE_MAX;
58:
59: while ((ch = getopt(argc, argv, "n:s:t")) != EOF)
60: switch(ch) {
61: case 'n':
62: if ((nargs = atoi(optarg)) <= 0) {
63: (void)fprintf(stderr,
64: "xargs: bad argument count.\n");
65: exit(1);
66: }
67: break;
68: case 's':
69: if ((nline = atoi(optarg)) <= 0) {
70: (void)fprintf(stderr,
71: "xargs: bad command length.\n");
72: exit(1);
73: }
74: break;
75: case 't':
76: tflag = 1;
77: break;
78: case '?':
79: default:
80: usage();
81: }
82: argc -= optind;
83: argv += optind;
84:
85: /* room for the command, leftover arguments and trailing NULL */
86: if (!(xargs =
87: (char **)malloc((u_int)(nargs + argc + 2) * sizeof(char **))))
88: enomem();
89:
90: if (!(bp = malloc((u_int)nline + 1)))
91: enomem();
92:
93: xp = xargs + 1;
94: if (!*argv)
95: prog = _PATH_ECHO;
96: else {
97: prog = *argv;
98: while (*++argv)
99: *xp++ = *argv;
100: }
101:
102: if (xargs[0] = rindex(prog, '/'))
103: ++xargs[0];
104: else
105: xargs[0] = prog;
106:
107: /* set up the pointers into the buffer and the arguments */
108: *(endxp = (bxp = xp) + nargs) = NULL;
109: endbp = (mark = p = bp) + nline;
110:
111: insingle = indouble = 0;
112: for (;;)
113: switch(ch = getchar()) {
114: case EOF:
115: if (p == bp) /* nothing to display */
116: exit(0);
117: if (mark == p) { /* nothing since last arg end */
118: run(prog, xargs);
119: exit(0);
120: }
121: goto addarg;
122: case ' ':
123: case '\t':
124: if (insingle || indouble)
125: goto addch;
126: goto addarg;
127: case '\n':
128: if (mark == p) /* empty line */
129: continue;
130: addarg: *xp++ = mark;
131: *p++ = '\0';
132: if (xp == endxp || p >= endbp || ch == EOF) {
133: if (insingle || indouble) {
134: (void)fprintf(stderr,
135: "xargs: unterminated quote.\n");
136: exit(1);
137: }
138: run(prog, xargs);
139: if (ch == EOF)
140: exit(0);
141: p = bp;
142: xp = bxp;
143: }
144: mark = p;
145: break;
146: case '\'':
147: if (indouble)
148: goto addch;
149: insingle = !insingle;
150: break;
151: case '"':
152: if (insingle)
153: goto addch;
154: indouble = !indouble;
155: break;
156: case '\\':
157: if ((ch = getchar()) == EOF)
158: ch = '\\';
159: if (ch == '\n') {
160: (void)fprintf(stderr,
161: "xargs: newline may not be escaped.\n");
162: exit(1);
163: }
164: /* FALLTHROUGH */
165: default:
166: addch: if (p != endbp) {
167: *p++ = ch;
168: continue;
169: }
170: if (xp == bxp) {
171: (void)fprintf(stderr,
172: "xargs: argument too large.\n");
173: exit(1);
174: }
175: *xp = NULL;
176: run(prog, xargs);
177: cnt = endbp - mark;
178: bcopy(mark, bp, cnt);
179: p = (mark = bp) + cnt;
180: *p++ = ch;
181: xp = bxp;
182: break;
183: }
184: /* NOTREACHED */
185: }
186:
187: run(prog, argv)
188: char *prog, **argv;
189: {
190: union wait pstat;
191: pid_t pid, waitpid();
192: char **p;
193:
194: if (tflag) {
195: (void)fprintf(stderr, "%s", *argv);
196: for (p = argv + 1; *p; ++p)
197: (void)fprintf(stderr, " %s", *p);
198: (void)fprintf(stderr, "\n");
199: (void)fflush(stderr);
200: }
201: switch(pid = vfork()) {
202: case -1:
203: (void)fprintf(stderr,
204: "xargs: vfork: %s.\n", strerror(errno));
205: exit(1);
206: case 0:
207: execvp(prog, argv);
208: (void)fprintf(stderr,
209: "xargs: %s: %s.\n", prog, strerror(errno));
210: _exit(1);
211: }
212: pid = waitpid(pid, &pstat, 0);
213: if (pid == -1) {
214: (void)fprintf(stderr,
215: "xargs: waitpid: %s.\n", strerror(errno));
216: exit(1);
217: }
218: if (pstat.w_status)
219: exit(1);
220: }
221:
222: enomem()
223: {
224: (void)fprintf(stderr, "xargs: %s.\n", strerror(ENOMEM));
225: exit(1);
226: }
227:
228: usage()
229: {
230: (void)fprintf(stderr,
231: "xargs: [-t] [-n number] [-s size] [utility [argument ...]]\n");
232: exit(1);
233: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.