Annotation of src/usr.bin/paste/paste.c, Revision 1.7
1.7 ! aaron 1: /* $OpenBSD: paste.c,v 1.6 1999/08/23 23:58:23 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.7 ! aaron 47: static char rcsid[] = "$OpenBSD: paste.c,v 1.6 1999/08/23 23:58:23 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;) {
1.7 ! aaron 146: lbuf = NULL;
1.1 deraadt 147: for (output = 0, lp = head; lp; lp = lp->next) {
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.7 ! aaron 166: lbuf = (char *)malloc(len + 1);
! 167: memcpy(lbuf, buf, len);
! 168: lbuf[len] = '\0';
! 169: buf = lbuf;
1.1 deraadt 170: }
171: /*
172: * make sure that we don't print any delimiters
173: * unless there's a non-empty file.
174: */
175: if (!output) {
176: output = 1;
177: for (cnt = 0; cnt < lp->cnt; ++cnt)
1.5 deraadt 178: if ((ch = delim[cnt % delimcnt]))
1.1 deraadt 179: putchar(ch);
1.5 deraadt 180: } else if ((ch = delim[(lp->cnt - 1) % delimcnt]))
1.1 deraadt 181: putchar(ch);
1.7 ! aaron 182: (void)printf("%s", buf);
! 183: if (lbuf != NULL) {
! 184: free(lbuf);
! 185: lbuf = NULL;
! 186: }
1.1 deraadt 187: }
188: if (output)
189: putchar('\n');
190: }
191: }
192:
1.5 deraadt 193: void
1.1 deraadt 194: sequential(argv)
195: char **argv;
196: {
197: register FILE *fp;
198: register int cnt;
199: register char ch, *p, *dp;
1.7 ! aaron 200: char *buf, *lbuf;
! 201: size_t len;
1.1 deraadt 202:
1.7 ! aaron 203: lbuf = NULL;
1.5 deraadt 204: for (; (p = *argv); ++argv) {
1.1 deraadt 205: if (p[0] == '-' && !p[1])
206: fp = stdin;
207: else if (!(fp = fopen(p, "r"))) {
208: (void)fprintf(stderr, "paste: %s: %s.\n", p,
209: strerror(errno));
210: continue;
211: }
1.7 ! aaron 212: if ((buf = fgetln(fp, &len))) {
1.1 deraadt 213: for (cnt = 0, dp = delim;;) {
1.7 ! aaron 214: if (*(buf + len - 1) == '\n')
! 215: *(buf + len - 1) = '\0';
! 216: else {
! 217: lbuf = (char *)malloc(len + 1);
! 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.7 ! aaron 236: if (lbuf != NULL) {
! 237: free(lbuf);
! 238: lbuf = NULL;
! 239: }
1.1 deraadt 240: }
241: }
242:
1.5 deraadt 243: int
1.1 deraadt 244: tr(arg)
245: char *arg;
246: {
247: register int cnt;
248: register char ch, *p;
249:
250: for (p = arg, cnt = 0; (ch = *p++); ++arg, ++cnt)
251: if (ch == '\\')
252: switch(ch = *p++) {
253: case 'n':
254: *arg = '\n';
255: break;
256: case 't':
257: *arg = '\t';
258: break;
259: case '0':
260: *arg = '\0';
261: break;
262: default:
263: *arg = ch;
264: break;
265: } else
266: *arg = ch;
267:
268: if (!cnt) {
269: (void)fprintf(stderr, "paste: no delimiters specified.\n");
270: exit(1);
271: }
272: return(cnt);
273: }
274:
1.5 deraadt 275: void
1.1 deraadt 276: usage()
277: {
278: (void)fprintf(stderr, "paste: [-s] [-d delimiters] file ...\n");
279: exit(1);
280: }