Annotation of src/usr.bin/paste/paste.c, Revision 1.8
1.8 ! aaron 1: /* $OpenBSD: paste.c,v 1.7 1999/08/24 18:49:45 aaron 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.8 ! aaron 47: static char rcsid[] = "$OpenBSD: paste.c,v 1.7 1999/08/24 18:49:45 aaron 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>
1.6 aaron 54: #include <stdlib.h>
1.1 deraadt 55: #include <string.h>
1.6 aaron 56: #include <unistd.h>
1.1 deraadt 57:
58: char *delim;
59: int delimcnt;
60:
1.5 deraadt 61: int tr __P((char *));
62: void usage __P((void));
63: void parallel __P((char **));
64: void sequential __P((char **));
65:
66: int
1.1 deraadt 67: main(argc, argv)
68: int argc;
69: char **argv;
70: {
71: extern char *optarg;
72: extern int optind;
73: int ch, seq;
74:
75: seq = 0;
1.3 millert 76: while ((ch = getopt(argc, argv, "d:s")) != -1)
1.1 deraadt 77: switch(ch) {
78: case 'd':
79: delimcnt = tr(delim = optarg);
80: break;
81: case 's':
82: seq = 1;
83: break;
84: case '?':
85: default:
86: usage();
87: }
88: argc -= optind;
89: argv += optind;
90:
91: if (!delim) {
92: delimcnt = 1;
93: delim = "\t";
94: }
95:
96: if (seq)
97: sequential(argv);
98: else
99: parallel(argv);
100: exit(0);
101: }
102:
103: typedef struct _list {
104: struct _list *next;
105: FILE *fp;
106: int cnt;
107: char *name;
108: } LIST;
109:
1.5 deraadt 110: void
1.1 deraadt 111: parallel(argv)
112: char **argv;
113: {
114: register LIST *lp;
115: register int cnt;
116: register char ch, *p;
117: LIST *head, *tmp;
118: int opencnt, output;
1.7 aaron 119: char *buf, *lbuf;
1.6 aaron 120: size_t len;
1.1 deraadt 121:
1.5 deraadt 122: for (cnt = 0, head = NULL; (p = *argv); ++argv, ++cnt) {
1.1 deraadt 123: if (!(lp = (LIST *)malloc((u_int)sizeof(LIST)))) {
124: (void)fprintf(stderr, "paste: %s.\n", strerror(ENOMEM));
125: exit(1);
126: }
127: if (p[0] == '-' && !p[1])
128: lp->fp = stdin;
129: else if (!(lp->fp = fopen(p, "r"))) {
130: (void)fprintf(stderr, "paste: %s: %s.\n", p,
131: strerror(errno));
132: exit(1);
133: }
134: lp->next = NULL;
135: lp->cnt = cnt;
136: lp->name = p;
137: if (!head)
138: head = tmp = lp;
139: else {
140: tmp->next = lp;
141: tmp = lp;
142: }
143: }
144:
145: for (opencnt = cnt; opencnt;) {
146: for (output = 0, lp = head; lp; lp = lp->next) {
1.8 ! aaron 147: lbuf = NULL;
1.1 deraadt 148: if (!lp->fp) {
149: if (output && lp->cnt &&
150: (ch = delim[(lp->cnt - 1) % delimcnt]))
151: putchar(ch);
152: continue;
153: }
1.7 aaron 154: if (!(buf = fgetln(lp->fp, &len))) {
1.1 deraadt 155: if (!--opencnt)
156: break;
157: lp->fp = NULL;
158: if (output && lp->cnt &&
159: (ch = delim[(lp->cnt - 1) % delimcnt]))
160: putchar(ch);
161: continue;
162: }
1.7 aaron 163: if (*(buf + len - 1) == '\n')
164: *(buf + len - 1) = '\0';
1.6 aaron 165: else {
1.8 ! aaron 166: if ((lbuf = malloc(len + 1)) == NULL)
! 167: err(1, NULL);
1.7 aaron 168: memcpy(lbuf, buf, len);
169: lbuf[len] = '\0';
170: buf = lbuf;
1.1 deraadt 171: }
172: /*
173: * make sure that we don't print any delimiters
174: * unless there's a non-empty file.
175: */
176: if (!output) {
177: output = 1;
178: for (cnt = 0; cnt < lp->cnt; ++cnt)
1.5 deraadt 179: if ((ch = delim[cnt % delimcnt]))
1.1 deraadt 180: putchar(ch);
1.5 deraadt 181: } else if ((ch = delim[(lp->cnt - 1) % delimcnt]))
1.1 deraadt 182: putchar(ch);
1.7 aaron 183: (void)printf("%s", buf);
1.8 ! aaron 184: if (lbuf)
1.7 aaron 185: free(lbuf);
1.1 deraadt 186: }
187: if (output)
188: putchar('\n');
189: }
190: }
191:
1.5 deraadt 192: void
1.1 deraadt 193: sequential(argv)
194: char **argv;
195: {
196: register FILE *fp;
197: register int cnt;
198: register char ch, *p, *dp;
1.7 aaron 199: char *buf, *lbuf;
200: size_t len;
1.1 deraadt 201:
1.5 deraadt 202: for (; (p = *argv); ++argv) {
1.8 ! aaron 203: lbuf = NULL;
1.1 deraadt 204: if (p[0] == '-' && !p[1])
205: fp = stdin;
206: else if (!(fp = fopen(p, "r"))) {
207: (void)fprintf(stderr, "paste: %s: %s.\n", p,
208: strerror(errno));
209: continue;
210: }
1.7 aaron 211: if ((buf = fgetln(fp, &len))) {
1.1 deraadt 212: for (cnt = 0, dp = delim;;) {
1.7 aaron 213: if (*(buf + len - 1) == '\n')
214: *(buf + len - 1) = '\0';
215: else {
1.8 ! aaron 216: if ((lbuf = malloc(len + 1)) == NULL)
! 217: err(1, NULL);
1.7 aaron 218: memcpy(lbuf, buf, len);
219: lbuf[len] = '\0';
220: buf = lbuf;
1.1 deraadt 221: }
222: (void)printf("%s", buf);
1.7 aaron 223: if (!(buf = fgetln(fp, &len)))
1.1 deraadt 224: break;
1.5 deraadt 225: if ((ch = *dp++))
1.1 deraadt 226: putchar(ch);
227: if (++cnt == delimcnt) {
228: dp = delim;
229: cnt = 0;
230: }
231: }
232: putchar('\n');
233: }
234: if (fp != stdin)
235: (void)fclose(fp);
1.8 ! aaron 236: if (lbuf)
1.7 aaron 237: free(lbuf);
1.1 deraadt 238: }
239: }
240:
1.5 deraadt 241: int
1.1 deraadt 242: tr(arg)
243: char *arg;
244: {
245: register int cnt;
246: register char ch, *p;
247:
248: for (p = arg, cnt = 0; (ch = *p++); ++arg, ++cnt)
249: if (ch == '\\')
250: switch(ch = *p++) {
251: case 'n':
252: *arg = '\n';
253: break;
254: case 't':
255: *arg = '\t';
256: break;
257: case '0':
258: *arg = '\0';
259: break;
260: default:
261: *arg = ch;
262: break;
263: } else
264: *arg = ch;
265:
266: if (!cnt) {
267: (void)fprintf(stderr, "paste: no delimiters specified.\n");
268: exit(1);
269: }
270: return(cnt);
271: }
272:
1.5 deraadt 273: void
1.1 deraadt 274: usage()
275: {
276: (void)fprintf(stderr, "paste: [-s] [-d delimiters] file ...\n");
277: exit(1);
278: }