Serious quoteing problem in conditionals:
[unix-history] / usr / src / usr.bin / paste / paste.c
CommitLineData
666af5c2 1/*
38dbba7c
KB
2 * Copyright (c) 1989, 1993
3 * The Regents of the University of California. All rights reserved.
666af5c2
KB
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Adam S. Moskowitz of Menlo Consulting.
7 *
6d936b27 8 * %sccs.include.redist.c%
666af5c2
KB
9 */
10
11#ifndef lint
38dbba7c
KB
12static char copyright[] =
13"@(#) Copyright (c) 1989, 1993\n\
14 The Regents of the University of California. All rights reserved.\n";
666af5c2
KB
15#endif /* not lint */
16
17#ifndef lint
38dbba7c 18static char sccsid[] = "@(#)paste.c 8.1 (Berkeley) %G%";
666af5c2
KB
19#endif /* not lint */
20
21#include <sys/types.h>
22#include <errno.h>
23#include <limits.h>
24#include <stdio.h>
8783897a 25#include <string.h>
666af5c2 26
666af5c2
KB
27char *delim;
28int delimcnt;
29
8783897a 30main(argc, argv)
666af5c2
KB
31 int argc;
32 char **argv;
33{
34 extern char *optarg;
35 extern int optind;
36 int ch, seq;
37
38 seq = 0;
39 while ((ch = getopt(argc, argv, "d:s")) != EOF)
40 switch(ch) {
41 case 'd':
42 delimcnt = tr(delim = optarg);
43 break;
44 case 's':
45 seq = 1;
46 break;
47 case '?':
48 default:
49 usage();
50 }
51 argc -= optind;
52 argv += optind;
53
54 if (!delim) {
55 delimcnt = 1;
56 delim = "\t";
57 }
58
59 if (seq)
60 sequential(argv);
61 else
62 parallel(argv);
63 exit(0);
64}
65
66typedef struct _list {
67 struct _list *next;
68 FILE *fp;
69 int cnt;
70 char *name;
71} LIST;
72
73parallel(argv)
74 char **argv;
75{
76 register LIST *lp;
77 register int cnt;
78 register char ch, *p;
79 LIST *head, *tmp;
80 int opencnt, output;
3b49ff20 81 char buf[_POSIX2_LINE_MAX + 1], *malloc();
666af5c2
KB
82
83 for (cnt = 0, head = NULL; p = *argv; ++argv, ++cnt) {
84 if (!(lp = (LIST *)malloc((u_int)sizeof(LIST)))) {
85 (void)fprintf(stderr, "paste: %s.\n", strerror(ENOMEM));
86 exit(1);
87 }
88 if (p[0] == '-' && !p[1])
89 lp->fp = stdin;
90 else if (!(lp->fp = fopen(p, "r"))) {
91 (void)fprintf(stderr, "paste: %s: %s.\n", p,
92 strerror(errno));
93 exit(1);
94 }
95 lp->next = NULL;
96 lp->cnt = cnt;
97 lp->name = p;
98 if (!head)
99 head = tmp = lp;
100 else {
101 tmp->next = lp;
102 tmp = lp;
103 }
104 }
105
106 for (opencnt = cnt; opencnt;) {
8e217866 107 for (output = 0, lp = head; lp; lp = lp->next) {
666af5c2 108 if (!lp->fp) {
8e217866
KB
109 if (output && lp->cnt &&
110 (ch = delim[(lp->cnt - 1) % delimcnt]))
111 putchar(ch);
666af5c2
KB
112 continue;
113 }
114 if (!fgets(buf, sizeof(buf), lp->fp)) {
115 if (!--opencnt)
116 break;
117 lp->fp = NULL;
8e217866
KB
118 if (output && lp->cnt &&
119 (ch = delim[(lp->cnt - 1) % delimcnt]))
120 putchar(ch);
666af5c2
KB
121 continue;
122 }
123 if (!(p = index(buf, '\n'))) {
124 (void)fprintf(stderr,
125 "paste: %s: input line too long.\n",
126 lp->name);
127 exit(1);
128 }
129 *p = '\0';
8e217866
KB
130 /*
131 * make sure that we don't print any delimiters
132 * unless there's a non-empty file.
133 */
134 if (!output) {
135 output = 1;
136 for (cnt = 0; cnt < lp->cnt; ++cnt)
137 if (ch = delim[cnt % delimcnt])
138 putchar(ch);
139 } else if (ch = delim[(lp->cnt - 1) % delimcnt])
140 putchar(ch);
666af5c2
KB
141 (void)printf("%s", buf);
142 }
143 if (output)
144 putchar('\n');
145 }
146}
147
148sequential(argv)
149 char **argv;
150{
151 register FILE *fp;
152 register int cnt;
153 register char ch, *p, *dp;
3b49ff20 154 char buf[_POSIX2_LINE_MAX + 1];
666af5c2
KB
155
156 for (; p = *argv; ++argv) {
157 if (p[0] == '-' && !p[1])
158 fp = stdin;
7dfe98e3 159 else if (!(fp = fopen(p, "r"))) {
666af5c2
KB
160 (void)fprintf(stderr, "paste: %s: %s.\n", p,
161 strerror(errno));
162 continue;
163 }
164 if (fgets(buf, sizeof(buf), fp)) {
165 for (cnt = 0, dp = delim;;) {
166 if (!(p = index(buf, '\n'))) {
167 (void)fprintf(stderr,
168 "paste: %s: input line too long.\n",
169 *argv);
170 exit(1);
171 }
172 *p = '\0';
173 (void)printf("%s", buf);
174 if (!fgets(buf, sizeof(buf), fp))
175 break;
176 if (ch = *dp++)
177 putchar(ch);
178 if (++cnt == delimcnt) {
179 dp = delim;
180 cnt = 0;
181 }
182 }
183 putchar('\n');
184 }
185 if (fp != stdin)
186 (void)fclose(fp);
187 }
188}
189
190tr(arg)
191 char *arg;
192{
193 register int cnt;
194 register char ch, *p;
195
196 for (p = arg, cnt = 0; (ch = *p++); ++arg, ++cnt)
197 if (ch == '\\')
198 switch(ch = *p++) {
199 case 'n':
200 *arg = '\n';
201 break;
202 case 't':
203 *arg = '\t';
204 break;
205 case '0':
206 *arg = '\0';
207 break;
208 default:
209 *arg = ch;
210 break;
211 } else
212 *arg = ch;
213
214 if (!cnt) {
215 (void)fprintf(stderr, "paste: no delimiters specified.\n");
216 exit(1);
217 }
218 return(cnt);
219}
220
221usage()
222{
223 (void)fprintf(stderr, "paste: [-s] [-d delimiters] file ...\n");
224 exit(1);
225}