1 /* $NetBSD: paste.c,v 1.6 1998/10/13 17:02:16 wsanchez Exp $ */ 2 3 /* 4 * Copyright (c) 1989, 1993 5 * The Regents of the University of California. 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. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the University of 21 * California, Berkeley and its contributors. 22 * 4. Neither the name of the University nor the names of its contributors 23 * may be used to endorse or promote products derived from this software 24 * without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 */ 38 39 #include <sys/cdefs.h> 40 #ifndef lint 41 __COPYRIGHT("@(#) Copyright (c) 1989, 1993\n\ 42 The Regents of the University of California. All rights reserved.\n"); 43 #endif /* not lint */ 44 45 #ifndef lint 46 /*static char sccsid[] = "from: @(#)paste.c 8.1 (Berkeley) 6/6/93";*/ 47 __RCSID("$NetBSD: paste.c,v 1.6 1998/10/13 17:02:16 wsanchez Exp $"); 48 #endif /* not lint */ 49 50 #include <sys/types.h> 51 #include <err.h> 52 #include <errno.h> 53 #include <limits.h> 54 #include <stdio.h> 55 #include <stdlib.h> 56 #include <unistd.h> 57 #include <string.h> 58 #include <unistd.h> 59 60 int main __P((int, char **)); 61 void parallel __P((char **)); 62 void sequential __P((char **)); 63 int tr __P((char *)); 64 void usage __P((void)); 65 66 char *delim; 67 int delimcnt; 68 69 int 70 main(argc, argv) 71 int argc; 72 char **argv; 73 { 74 int ch, seq; 75 76 seq = 0; 77 while ((ch = getopt(argc, argv, "d:s")) != -1) 78 switch(ch) { 79 case 'd': 80 delimcnt = tr(delim = optarg); 81 break; 82 case 's': 83 seq = 1; 84 break; 85 case '?': 86 default: 87 usage(); 88 } 89 argc -= optind; 90 argv += optind; 91 92 if (!delim) { 93 delimcnt = 1; 94 delim = "\t"; 95 } 96 97 if (seq) 98 sequential(argv); 99 else 100 parallel(argv); 101 exit(0); 102 } 103 104 typedef struct _list { 105 struct _list *next; 106 FILE *fp; 107 int cnt; 108 char *name; 109 } LIST; 110 111 void 112 parallel(argv) 113 char **argv; 114 { 115 LIST *lp; 116 int cnt; 117 char ch, *p; 118 LIST *head, *tmp; 119 int opencnt, output; 120 char buf[_POSIX2_LINE_MAX + 1]; 121 122 tmp = NULL; 123 for (cnt = 0, head = NULL; (p = *argv) != NULL; ++argv, ++cnt) { 124 if (!(lp = (LIST *)malloc((u_int)sizeof(LIST)))) 125 err(1, "malloc"); 126 if (p[0] == '-' && !p[1]) 127 lp->fp = stdin; 128 else if (!(lp->fp = fopen(p, "r"))) 129 err(1, "%s", p); 130 lp->next = NULL; 131 lp->cnt = cnt; 132 lp->name = p; 133 if (!head) 134 head = tmp = lp; 135 else { 136 tmp->next = lp; 137 tmp = lp; 138 } 139 } 140 141 for (opencnt = cnt; opencnt;) { 142 for (output = 0, lp = head; lp; lp = lp->next) { 143 if (!lp->fp) { 144 if (output && lp->cnt && 145 (ch = delim[(lp->cnt - 1) % delimcnt])) 146 putchar(ch); 147 continue; 148 } 149 if (!fgets(buf, sizeof(buf), lp->fp)) { 150 if (!--opencnt) 151 break; 152 lp->fp = NULL; 153 if (output && lp->cnt && 154 (ch = delim[(lp->cnt - 1) % delimcnt])) 155 putchar(ch); 156 continue; 157 } 158 if (!(p = strchr(buf, '\n'))) 159 err(1, "%s: input line too long.", lp->name); 160 *p = '\0'; 161 /* 162 * make sure that we don't print any delimiters 163 * unless there's a non-empty file. 164 */ 165 if (!output) { 166 output = 1; 167 for (cnt = 0; cnt < lp->cnt; ++cnt) 168 if ((ch = delim[cnt % delimcnt]) != 0) 169 putchar(ch); 170 } else if ((ch = delim[(lp->cnt - 1) % delimcnt]) != 0) 171 putchar(ch); 172 (void)printf("%s", buf); 173 } 174 if (output) 175 putchar('\n'); 176 } 177 } 178 179 void 180 sequential(argv) 181 char **argv; 182 { 183 FILE *fp; 184 int cnt; 185 char ch, *p, *dp; 186 char buf[_POSIX2_LINE_MAX + 1]; 187 188 for (; (p = *argv) != NULL; ++argv) { 189 if (p[0] == '-' && !p[1]) 190 fp = stdin; 191 else if (!(fp = fopen(p, "r"))) { 192 warn("%s", p); 193 continue; 194 } 195 if (fgets(buf, sizeof(buf), fp)) { 196 for (cnt = 0, dp = delim;;) { 197 if (!(p = strchr(buf, '\n'))) 198 err(1, "%s: input line too long.", 199 *argv); 200 *p = '\0'; 201 (void)printf("%s", buf); 202 if (!fgets(buf, sizeof(buf), fp)) 203 break; 204 if ((ch = *dp++) != 0) 205 putchar(ch); 206 if (++cnt == delimcnt) { 207 dp = delim; 208 cnt = 0; 209 } 210 } 211 putchar('\n'); 212 } 213 if (fp != stdin) 214 (void)fclose(fp); 215 } 216 } 217 218 int 219 tr(arg) 220 char *arg; 221 { 222 int cnt; 223 char ch, *p; 224 225 for (p = arg, cnt = 0; (ch = *p++); ++arg, ++cnt) 226 if (ch == '\\') 227 switch(ch = *p++) { 228 case 'n': 229 *arg = '\n'; 230 break; 231 case 't': 232 *arg = '\t'; 233 break; 234 case '0': 235 *arg = '\0'; 236 break; 237 default: 238 *arg = ch; 239 break; 240 } else 241 *arg = ch; 242 243 if (!cnt) 244 errx(1, "no delimiters specified."); 245 return(cnt); 246 } 247 248 void 249 usage() 250 { 251 (void)fprintf(stderr, "paste: [-s] [-d delimiters] file ...\n"); 252 exit(1); 253 } 254