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