Annotation of src/usr.bin/paste/paste.c, Revision 1.1.1.1
1.1 deraadt 1: /*
2: * Copyright (c) 1989 The Regents of the University of California.
3: * All rights reserved.
4: *
5: * This code is derived from software contributed to Berkeley by
6: * Adam S. Moskowitz of Menlo Consulting.
7: *
8: * Redistribution and use in source and binary forms, with or without
9: * modification, are permitted provided that the following conditions
10: * are met:
11: * 1. Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: * 2. Redistributions in binary form must reproduce the above copyright
14: * notice, this list of conditions and the following disclaimer in the
15: * documentation and/or other materials provided with the distribution.
16: * 3. All advertising materials mentioning features or use of this software
17: * must display the following acknowledgement:
18: * This product includes software developed by the University of
19: * California, Berkeley and its contributors.
20: * 4. Neither the name of the University nor the names of its contributors
21: * may be used to endorse or promote products derived from this software
22: * without specific prior written permission.
23: *
24: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34: * SUCH DAMAGE.
35: */
36:
37: #ifndef lint
38: char copyright[] =
39: "@(#) Copyright (c) 1989 The Regents of the University of California.\n\
40: All rights reserved.\n";
41: #endif /* not lint */
42:
43: #ifndef lint
44: /*static char sccsid[] = "from: @(#)paste.c 5.7 (Berkeley) 10/30/90";*/
45: static char rcsid[] = "$Id: paste.c,v 1.2 1993/08/01 18:10:14 mycroft Exp $";
46: #endif /* not lint */
47:
48: #include <sys/types.h>
49: #include <errno.h>
50: #include <limits.h>
51: #include <stdio.h>
52: #include <string.h>
53:
54: char *delim;
55: int delimcnt;
56:
57: main(argc, argv)
58: int argc;
59: char **argv;
60: {
61: extern char *optarg;
62: extern int optind;
63: int ch, seq;
64:
65: seq = 0;
66: while ((ch = getopt(argc, argv, "d:s")) != EOF)
67: switch(ch) {
68: case 'd':
69: delimcnt = tr(delim = optarg);
70: break;
71: case 's':
72: seq = 1;
73: break;
74: case '?':
75: default:
76: usage();
77: }
78: argc -= optind;
79: argv += optind;
80:
81: if (!delim) {
82: delimcnt = 1;
83: delim = "\t";
84: }
85:
86: if (seq)
87: sequential(argv);
88: else
89: parallel(argv);
90: exit(0);
91: }
92:
93: typedef struct _list {
94: struct _list *next;
95: FILE *fp;
96: int cnt;
97: char *name;
98: } LIST;
99:
100: parallel(argv)
101: char **argv;
102: {
103: register LIST *lp;
104: register int cnt;
105: register char ch, *p;
106: LIST *head, *tmp;
107: int opencnt, output;
108: char buf[_POSIX2_LINE_MAX + 1], *malloc();
109:
110: for (cnt = 0, head = NULL; p = *argv; ++argv, ++cnt) {
111: if (!(lp = (LIST *)malloc((u_int)sizeof(LIST)))) {
112: (void)fprintf(stderr, "paste: %s.\n", strerror(ENOMEM));
113: exit(1);
114: }
115: if (p[0] == '-' && !p[1])
116: lp->fp = stdin;
117: else if (!(lp->fp = fopen(p, "r"))) {
118: (void)fprintf(stderr, "paste: %s: %s.\n", p,
119: strerror(errno));
120: exit(1);
121: }
122: lp->next = NULL;
123: lp->cnt = cnt;
124: lp->name = p;
125: if (!head)
126: head = tmp = lp;
127: else {
128: tmp->next = lp;
129: tmp = lp;
130: }
131: }
132:
133: for (opencnt = cnt; opencnt;) {
134: for (output = 0, lp = head; lp; lp = lp->next) {
135: if (!lp->fp) {
136: if (output && lp->cnt &&
137: (ch = delim[(lp->cnt - 1) % delimcnt]))
138: putchar(ch);
139: continue;
140: }
141: if (!fgets(buf, sizeof(buf), lp->fp)) {
142: if (!--opencnt)
143: break;
144: lp->fp = NULL;
145: if (output && lp->cnt &&
146: (ch = delim[(lp->cnt - 1) % delimcnt]))
147: putchar(ch);
148: continue;
149: }
150: if (!(p = index(buf, '\n'))) {
151: (void)fprintf(stderr,
152: "paste: %s: input line too long.\n",
153: lp->name);
154: exit(1);
155: }
156: *p = '\0';
157: /*
158: * make sure that we don't print any delimiters
159: * unless there's a non-empty file.
160: */
161: if (!output) {
162: output = 1;
163: for (cnt = 0; cnt < lp->cnt; ++cnt)
164: if (ch = delim[cnt % delimcnt])
165: putchar(ch);
166: } else if (ch = delim[(lp->cnt - 1) % delimcnt])
167: putchar(ch);
168: (void)printf("%s", buf);
169: }
170: if (output)
171: putchar('\n');
172: }
173: }
174:
175: sequential(argv)
176: char **argv;
177: {
178: register FILE *fp;
179: register int cnt;
180: register char ch, *p, *dp;
181: char buf[_POSIX2_LINE_MAX + 1];
182:
183: for (; p = *argv; ++argv) {
184: if (p[0] == '-' && !p[1])
185: fp = stdin;
186: else if (!(fp = fopen(p, "r"))) {
187: (void)fprintf(stderr, "paste: %s: %s.\n", p,
188: strerror(errno));
189: continue;
190: }
191: if (fgets(buf, sizeof(buf), fp)) {
192: for (cnt = 0, dp = delim;;) {
193: if (!(p = index(buf, '\n'))) {
194: (void)fprintf(stderr,
195: "paste: %s: input line too long.\n",
196: *argv);
197: exit(1);
198: }
199: *p = '\0';
200: (void)printf("%s", buf);
201: if (!fgets(buf, sizeof(buf), fp))
202: break;
203: if (ch = *dp++)
204: putchar(ch);
205: if (++cnt == delimcnt) {
206: dp = delim;
207: cnt = 0;
208: }
209: }
210: putchar('\n');
211: }
212: if (fp != stdin)
213: (void)fclose(fp);
214: }
215: }
216:
217: tr(arg)
218: char *arg;
219: {
220: register int cnt;
221: register char ch, *p;
222:
223: for (p = arg, cnt = 0; (ch = *p++); ++arg, ++cnt)
224: if (ch == '\\')
225: switch(ch = *p++) {
226: case 'n':
227: *arg = '\n';
228: break;
229: case 't':
230: *arg = '\t';
231: break;
232: case '0':
233: *arg = '\0';
234: break;
235: default:
236: *arg = ch;
237: break;
238: } else
239: *arg = ch;
240:
241: if (!cnt) {
242: (void)fprintf(stderr, "paste: no delimiters specified.\n");
243: exit(1);
244: }
245: return(cnt);
246: }
247:
248: usage()
249: {
250: (void)fprintf(stderr, "paste: [-s] [-d delimiters] file ...\n");
251: exit(1);
252: }