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