Home | History | Annotate | Line # | Download | only in paste
paste.c revision 1.5
      1 /*	$NetBSD: paste.c,v 1.5 1998/02/03 03:56:44 perry 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.5 1998/02/03 03:56:44 perry 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 <string.h>
     57 #include <unistd.h>
     58 
     59 int	main __P((int, char **));
     60 void	parallel __P((char **));
     61 void	sequential __P((char **));
     62 int	tr __P((char *));
     63 void	usage __P((void));
     64 
     65 char *delim;
     66 int delimcnt;
     67 
     68 int
     69 main(argc, argv)
     70 	int argc;
     71 	char **argv;
     72 {
     73 	int ch, seq;
     74 
     75 	seq = 0;
     76 	while ((ch = getopt(argc, argv, "d:s")) != -1)
     77 		switch(ch) {
     78 		case 'd':
     79 			delimcnt = tr(delim = optarg);
     80 			break;
     81 		case 's':
     82 			seq = 1;
     83 			break;
     84 		case '?':
     85 		default:
     86 			usage();
     87 		}
     88 	argc -= optind;
     89 	argv += optind;
     90 
     91 	if (!delim) {
     92 		delimcnt = 1;
     93 		delim = "\t";
     94 	}
     95 
     96 	if (seq)
     97 		sequential(argv);
     98 	else
     99 		parallel(argv);
    100 	exit(0);
    101 }
    102 
    103 typedef struct _list {
    104 	struct _list *next;
    105 	FILE *fp;
    106 	int cnt;
    107 	char *name;
    108 } LIST;
    109 
    110 void
    111 parallel(argv)
    112 	char **argv;
    113 {
    114 	LIST *lp;
    115 	int cnt;
    116 	char ch, *p;
    117 	LIST *head, *tmp;
    118 	int opencnt, output;
    119 	char buf[_POSIX2_LINE_MAX + 1];
    120 
    121 	tmp = NULL;
    122 	for (cnt = 0, head = NULL; (p = *argv) != NULL; ++argv, ++cnt) {
    123 		if (!(lp = (LIST *)malloc((u_int)sizeof(LIST))))
    124 			err(1, "malloc");
    125 		if (p[0] == '-' && !p[1])
    126 			lp->fp = stdin;
    127 		else if (!(lp->fp = fopen(p, "r")))
    128 			err(1, "%s", p);
    129 		lp->next = NULL;
    130 		lp->cnt = cnt;
    131 		lp->name = p;
    132 		if (!head)
    133 			head = tmp = lp;
    134 		else {
    135 			tmp->next = lp;
    136 			tmp = lp;
    137 		}
    138 	}
    139 
    140 	for (opencnt = cnt; opencnt;) {
    141 		for (output = 0, lp = head; lp; lp = lp->next) {
    142 			if (!lp->fp) {
    143 				if (output && lp->cnt &&
    144 				    (ch = delim[(lp->cnt - 1) % delimcnt]))
    145 					putchar(ch);
    146 				continue;
    147 			}
    148 			if (!fgets(buf, sizeof(buf), lp->fp)) {
    149 				if (!--opencnt)
    150 					break;
    151 				lp->fp = NULL;
    152 				if (output && lp->cnt &&
    153 				    (ch = delim[(lp->cnt - 1) % delimcnt]))
    154 					putchar(ch);
    155 				continue;
    156 			}
    157 			if (!(p = strchr(buf, '\n')))
    158 				err(1, "%s: input line too long.", lp->name);
    159 			*p = '\0';
    160 			/*
    161 			 * make sure that we don't print any delimiters
    162 			 * unless there's a non-empty file.
    163 			 */
    164 			if (!output) {
    165 				output = 1;
    166 				for (cnt = 0; cnt < lp->cnt; ++cnt)
    167 					if ((ch = delim[cnt % delimcnt]) != 0)
    168 						putchar(ch);
    169 			} else if ((ch = delim[(lp->cnt - 1) % delimcnt]) != 0)
    170 				putchar(ch);
    171 			(void)printf("%s", buf);
    172 		}
    173 		if (output)
    174 			putchar('\n');
    175 	}
    176 }
    177 
    178 void
    179 sequential(argv)
    180 	char **argv;
    181 {
    182 	FILE *fp;
    183 	int cnt;
    184 	char ch, *p, *dp;
    185 	char buf[_POSIX2_LINE_MAX + 1];
    186 
    187 	for (; (p = *argv) != NULL; ++argv) {
    188 		if (p[0] == '-' && !p[1])
    189 			fp = stdin;
    190 		else if (!(fp = fopen(p, "r"))) {
    191 			warn("%s", p);
    192 			continue;
    193 		}
    194 		if (fgets(buf, sizeof(buf), fp)) {
    195 			for (cnt = 0, dp = delim;;) {
    196 				if (!(p = strchr(buf, '\n')))
    197 					err(1, "%s: input line too long.",
    198 					    *argv);
    199 				*p = '\0';
    200 				(void)printf("%s", buf);
    201 				if (!fgets(buf, sizeof(buf), fp))
    202 					break;
    203 				if ((ch = *dp++) != 0)
    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 int
    218 tr(arg)
    219 	char *arg;
    220 {
    221 	int cnt;
    222 	char ch, *p;
    223 
    224 	for (p = arg, cnt = 0; (ch = *p++); ++arg, ++cnt)
    225 		if (ch == '\\')
    226 			switch(ch = *p++) {
    227 			case 'n':
    228 				*arg = '\n';
    229 				break;
    230 			case 't':
    231 				*arg = '\t';
    232 				break;
    233 			case '0':
    234 				*arg = '\0';
    235 				break;
    236 			default:
    237 				*arg = ch;
    238 				break;
    239 		} else
    240 			*arg = ch;
    241 
    242 	if (!cnt)
    243 		errx(1, "no delimiters specified.");
    244 	return(cnt);
    245 }
    246 
    247 void
    248 usage()
    249 {
    250 	(void)fprintf(stderr, "paste: [-s] [-d delimiters] file ...\n");
    251 	exit(1);
    252 }
    253