Annotation of src/usr.bin/paste/paste.c, Revision 1.1
1.1 ! deraadt 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: }