139826Sbostic /*
2*62161Sbostic * Copyright (c) 1989, 1993
3*62161Sbostic * The Regents of the University of California. All rights reserved.
439826Sbostic *
539826Sbostic * This code is derived from software contributed to Berkeley by
639826Sbostic * Adam S. Moskowitz of Menlo Consulting.
739826Sbostic *
842757Sbostic * %sccs.include.redist.c%
939826Sbostic */
1039826Sbostic
1139826Sbostic #ifndef lint
12*62161Sbostic static char copyright[] =
13*62161Sbostic "@(#) Copyright (c) 1989, 1993\n\
14*62161Sbostic The Regents of the University of California. All rights reserved.\n";
1539826Sbostic #endif /* not lint */
1639826Sbostic
1739826Sbostic #ifndef lint
18*62161Sbostic static char sccsid[] = "@(#)paste.c 8.1 (Berkeley) 06/06/93";
1939826Sbostic #endif /* not lint */
2039826Sbostic
2139826Sbostic #include <sys/types.h>
2239826Sbostic #include <errno.h>
2339826Sbostic #include <limits.h>
2439826Sbostic #include <stdio.h>
2542756Sbostic #include <string.h>
2639826Sbostic
2739826Sbostic char *delim;
2839826Sbostic int delimcnt;
2939826Sbostic
main(argc,argv)3042756Sbostic main(argc, argv)
3139826Sbostic int argc;
3239826Sbostic char **argv;
3339826Sbostic {
3439826Sbostic extern char *optarg;
3539826Sbostic extern int optind;
3639826Sbostic int ch, seq;
3739826Sbostic
3839826Sbostic seq = 0;
3939826Sbostic while ((ch = getopt(argc, argv, "d:s")) != EOF)
4039826Sbostic switch(ch) {
4139826Sbostic case 'd':
4239826Sbostic delimcnt = tr(delim = optarg);
4339826Sbostic break;
4439826Sbostic case 's':
4539826Sbostic seq = 1;
4639826Sbostic break;
4739826Sbostic case '?':
4839826Sbostic default:
4939826Sbostic usage();
5039826Sbostic }
5139826Sbostic argc -= optind;
5239826Sbostic argv += optind;
5339826Sbostic
5439826Sbostic if (!delim) {
5539826Sbostic delimcnt = 1;
5639826Sbostic delim = "\t";
5739826Sbostic }
5839826Sbostic
5939826Sbostic if (seq)
6039826Sbostic sequential(argv);
6139826Sbostic else
6239826Sbostic parallel(argv);
6339826Sbostic exit(0);
6439826Sbostic }
6539826Sbostic
6639826Sbostic typedef struct _list {
6739826Sbostic struct _list *next;
6839826Sbostic FILE *fp;
6939826Sbostic int cnt;
7039826Sbostic char *name;
7139826Sbostic } LIST;
7239826Sbostic
parallel(argv)7339826Sbostic parallel(argv)
7439826Sbostic char **argv;
7539826Sbostic {
7639826Sbostic register LIST *lp;
7739826Sbostic register int cnt;
7839826Sbostic register char ch, *p;
7939826Sbostic LIST *head, *tmp;
8039826Sbostic int opencnt, output;
8145442Sbostic char buf[_POSIX2_LINE_MAX + 1], *malloc();
8239826Sbostic
8339826Sbostic for (cnt = 0, head = NULL; p = *argv; ++argv, ++cnt) {
8439826Sbostic if (!(lp = (LIST *)malloc((u_int)sizeof(LIST)))) {
8539826Sbostic (void)fprintf(stderr, "paste: %s.\n", strerror(ENOMEM));
8639826Sbostic exit(1);
8739826Sbostic }
8839826Sbostic if (p[0] == '-' && !p[1])
8939826Sbostic lp->fp = stdin;
9039826Sbostic else if (!(lp->fp = fopen(p, "r"))) {
9139826Sbostic (void)fprintf(stderr, "paste: %s: %s.\n", p,
9239826Sbostic strerror(errno));
9339826Sbostic exit(1);
9439826Sbostic }
9539826Sbostic lp->next = NULL;
9639826Sbostic lp->cnt = cnt;
9739826Sbostic lp->name = p;
9839826Sbostic if (!head)
9939826Sbostic head = tmp = lp;
10039826Sbostic else {
10139826Sbostic tmp->next = lp;
10239826Sbostic tmp = lp;
10339826Sbostic }
10439826Sbostic }
10539826Sbostic
10639826Sbostic for (opencnt = cnt; opencnt;) {
10740308Sbostic for (output = 0, lp = head; lp; lp = lp->next) {
10839826Sbostic if (!lp->fp) {
10940308Sbostic if (output && lp->cnt &&
11040308Sbostic (ch = delim[(lp->cnt - 1) % delimcnt]))
11140308Sbostic putchar(ch);
11239826Sbostic continue;
11339826Sbostic }
11439826Sbostic if (!fgets(buf, sizeof(buf), lp->fp)) {
11539826Sbostic if (!--opencnt)
11639826Sbostic break;
11739826Sbostic lp->fp = NULL;
11840308Sbostic if (output && lp->cnt &&
11940308Sbostic (ch = delim[(lp->cnt - 1) % delimcnt]))
12040308Sbostic putchar(ch);
12139826Sbostic continue;
12239826Sbostic }
12339826Sbostic if (!(p = index(buf, '\n'))) {
12439826Sbostic (void)fprintf(stderr,
12539826Sbostic "paste: %s: input line too long.\n",
12639826Sbostic lp->name);
12739826Sbostic exit(1);
12839826Sbostic }
12939826Sbostic *p = '\0';
13040308Sbostic /*
13140308Sbostic * make sure that we don't print any delimiters
13240308Sbostic * unless there's a non-empty file.
13340308Sbostic */
13440308Sbostic if (!output) {
13540308Sbostic output = 1;
13640308Sbostic for (cnt = 0; cnt < lp->cnt; ++cnt)
13740308Sbostic if (ch = delim[cnt % delimcnt])
13840308Sbostic putchar(ch);
13940308Sbostic } else if (ch = delim[(lp->cnt - 1) % delimcnt])
14040308Sbostic putchar(ch);
14139826Sbostic (void)printf("%s", buf);
14239826Sbostic }
14339826Sbostic if (output)
14439826Sbostic putchar('\n');
14539826Sbostic }
14639826Sbostic }
14739826Sbostic
sequential(argv)14839826Sbostic sequential(argv)
14939826Sbostic char **argv;
15039826Sbostic {
15139826Sbostic register FILE *fp;
15239826Sbostic register int cnt;
15339826Sbostic register char ch, *p, *dp;
15445442Sbostic char buf[_POSIX2_LINE_MAX + 1];
15539826Sbostic
15639826Sbostic for (; p = *argv; ++argv) {
15739826Sbostic if (p[0] == '-' && !p[1])
15839826Sbostic fp = stdin;
15940306Sbostic else if (!(fp = fopen(p, "r"))) {
16039826Sbostic (void)fprintf(stderr, "paste: %s: %s.\n", p,
16139826Sbostic strerror(errno));
16239826Sbostic continue;
16339826Sbostic }
16439826Sbostic if (fgets(buf, sizeof(buf), fp)) {
16539826Sbostic for (cnt = 0, dp = delim;;) {
16639826Sbostic if (!(p = index(buf, '\n'))) {
16739826Sbostic (void)fprintf(stderr,
16839826Sbostic "paste: %s: input line too long.\n",
16939826Sbostic *argv);
17039826Sbostic exit(1);
17139826Sbostic }
17239826Sbostic *p = '\0';
17339826Sbostic (void)printf("%s", buf);
17439826Sbostic if (!fgets(buf, sizeof(buf), fp))
17539826Sbostic break;
17639826Sbostic if (ch = *dp++)
17739826Sbostic putchar(ch);
17839826Sbostic if (++cnt == delimcnt) {
17939826Sbostic dp = delim;
18039826Sbostic cnt = 0;
18139826Sbostic }
18239826Sbostic }
18339826Sbostic putchar('\n');
18439826Sbostic }
18539826Sbostic if (fp != stdin)
18639826Sbostic (void)fclose(fp);
18739826Sbostic }
18839826Sbostic }
18939826Sbostic
tr(arg)19039826Sbostic tr(arg)
19139826Sbostic char *arg;
19239826Sbostic {
19339826Sbostic register int cnt;
19439826Sbostic register char ch, *p;
19539826Sbostic
19639826Sbostic for (p = arg, cnt = 0; (ch = *p++); ++arg, ++cnt)
19739826Sbostic if (ch == '\\')
19839826Sbostic switch(ch = *p++) {
19939826Sbostic case 'n':
20039826Sbostic *arg = '\n';
20139826Sbostic break;
20239826Sbostic case 't':
20339826Sbostic *arg = '\t';
20439826Sbostic break;
20539826Sbostic case '0':
20639826Sbostic *arg = '\0';
20739826Sbostic break;
20839826Sbostic default:
20939826Sbostic *arg = ch;
21039826Sbostic break;
21139826Sbostic } else
21239826Sbostic *arg = ch;
21339826Sbostic
21439826Sbostic if (!cnt) {
21539826Sbostic (void)fprintf(stderr, "paste: no delimiters specified.\n");
21639826Sbostic exit(1);
21739826Sbostic }
21839826Sbostic return(cnt);
21939826Sbostic }
22039826Sbostic
usage()22139826Sbostic usage()
22239826Sbostic {
22339826Sbostic (void)fprintf(stderr, "paste: [-s] [-d delimiters] file ...\n");
22439826Sbostic exit(1);
22539826Sbostic }
226