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