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