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