tools/tcp_stream: Set message size on both send and receive sides
[dragonfly.git] / usr.bin / paste / paste.c
blob7e67dc09dcc7f048b8b3ffeded05836394879174
1 /*
2 * Copyright (c) 1989, 1993
3 * The Regents of the University of California. All rights reserved.
5 * This code is derived from software contributed to Berkeley by
6 * Adam S. Moskowitz of Menlo Consulting.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
32 * @(#) Copyright (c) 1989, 1993 The Regents of the University of California. All rights reserved.
33 * @(#)paste.c 8.1 (Berkeley) 6/6/93
34 * $FreeBSD: head/usr.bin/paste/paste.c 227242 2011-11-06 18:49:53Z ed $
37 #include <sys/types.h>
39 #include <err.h>
40 #include <errno.h>
41 #include <limits.h>
42 #include <locale.h>
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <string.h>
46 #include <unistd.h>
47 #include <wchar.h>
49 static wchar_t *delim;
50 static int delimcnt;
52 static int parallel(char **);
53 static int sequential(char **);
54 static int tr(wchar_t *);
55 static void usage(void);
57 static wchar_t tab[] = L"\t";
59 int
60 main(int argc, char *argv[])
62 int ch, rval, seq;
63 wchar_t *warg;
64 const char *arg;
65 size_t len;
67 setlocale(LC_CTYPE, "");
69 seq = 0;
70 while ((ch = getopt(argc, argv, "d:s")) != -1)
71 switch(ch) {
72 case 'd':
73 arg = optarg;
74 len = mbsrtowcs(NULL, &arg, 0, NULL);
75 if (len == (size_t)-1)
76 err(1, "delimiters");
77 warg = malloc((len + 1) * sizeof(*warg));
78 if (warg == NULL)
79 err(1, NULL);
80 arg = optarg;
81 len = mbsrtowcs(warg, &arg, len + 1, NULL);
82 if (len == (size_t)-1)
83 err(1, "delimiters");
84 delimcnt = tr(delim = warg);
85 break;
86 case 's':
87 seq = 1;
88 break;
89 case '?':
90 default:
91 usage();
93 argc -= optind;
94 argv += optind;
96 if (*argv == NULL)
97 usage();
98 if (!delim) {
99 delimcnt = 1;
100 delim = tab;
103 if (seq)
104 rval = sequential(argv);
105 else
106 rval = parallel(argv);
107 exit(rval);
110 typedef struct _list {
111 struct _list *next;
112 FILE *fp;
113 int cnt;
114 char *name;
115 } LIST;
117 static int
118 parallel(char **argv)
120 LIST *lp;
121 int cnt;
122 wint_t ich;
123 wchar_t ch;
124 char *p;
125 LIST *head, *tmp;
126 int opencnt, output;
128 for (cnt = 0, head = tmp = NULL; (p = *argv); ++argv, ++cnt) {
129 if ((lp = malloc(sizeof(LIST))) == NULL)
130 err(1, NULL);
131 if (p[0] == '-' && !p[1])
132 lp->fp = stdin;
133 else if (!(lp->fp = fopen(p, "r")))
134 err(1, "%s", p);
135 lp->next = NULL;
136 lp->cnt = cnt;
137 lp->name = p;
138 if (!head)
139 head = tmp = lp;
140 else {
141 tmp->next = lp;
142 tmp = lp;
146 for (opencnt = cnt; opencnt;) {
147 for (output = 0, lp = head; lp; lp = lp->next) {
148 if (!lp->fp) {
149 if (output && lp->cnt &&
150 (ch = delim[(lp->cnt - 1) % delimcnt]))
151 putwchar(ch);
152 continue;
154 if ((ich = getwc(lp->fp)) == WEOF) {
155 if (!--opencnt)
156 break;
157 lp->fp = NULL;
158 if (output && lp->cnt &&
159 (ch = delim[(lp->cnt - 1) % delimcnt]))
160 putwchar(ch);
161 continue;
164 * make sure that we don't print any delimiters
165 * unless there's a non-empty file.
167 if (!output) {
168 output = 1;
169 for (cnt = 0; cnt < lp->cnt; ++cnt)
170 if ((ch = delim[cnt % delimcnt]))
171 putwchar(ch);
172 } else if ((ch = delim[(lp->cnt - 1) % delimcnt]))
173 putwchar(ch);
174 if (ich == '\n')
175 continue;
176 do {
177 putwchar(ich);
178 } while ((ich = getwc(lp->fp)) != WEOF && ich != '\n');
180 if (output)
181 putwchar('\n');
184 return (0);
187 static int
188 sequential(char **argv)
190 FILE *fp;
191 int cnt, failed, needdelim;
192 wint_t ch;
193 char *p;
195 failed = 0;
196 for (; (p = *argv); ++argv) {
197 if (p[0] == '-' && !p[1])
198 fp = stdin;
199 else if (!(fp = fopen(p, "r"))) {
200 warn("%s", p);
201 failed = 1;
202 continue;
204 cnt = needdelim = 0;
205 while ((ch = getwc(fp)) != WEOF) {
206 if (needdelim) {
207 needdelim = 0;
208 if (delim[cnt] != '\0')
209 putwchar(delim[cnt]);
210 if (++cnt == delimcnt)
211 cnt = 0;
213 if (ch != '\n')
214 putwchar(ch);
215 else
216 needdelim = 1;
218 if (needdelim)
219 putwchar('\n');
220 if (fp != stdin)
221 (void)fclose(fp);
224 return (failed != 0);
227 static int
228 tr(wchar_t *arg)
230 int cnt;
231 wchar_t ch, *p;
233 for (p = arg, cnt = 0; (ch = *p++); ++arg, ++cnt)
234 if (ch == '\\')
235 switch(ch = *p++) {
236 case 'n':
237 *arg = '\n';
238 break;
239 case 't':
240 *arg = '\t';
241 break;
242 case '0':
243 *arg = '\0';
244 break;
245 default:
246 *arg = ch;
247 break;
248 } else
249 *arg = ch;
251 if (!cnt)
252 errx(1, "no delimiters specified");
253 return(cnt);
256 static void
257 usage(void)
259 (void)fprintf(stderr, "usage: paste [-s] [-d delimiters] file ...\n");
260 exit(1);