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