Annotation of src/usr.bin/lam/lam.c, Revision 1.12
1.12 ! deraadt 1: /* $OpenBSD: lam.c,v 1.11 2004/07/03 21:00:37 millert Exp $ */
1.1 deraadt 2: /* $NetBSD: lam.c,v 1.2 1994/11/14 20:27:42 jtc Exp $ */
3:
4: /*-
5: * Copyright (c) 1993
6: * The Regents of the University of California. All rights reserved.
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.
1.8 millert 16: * 3. Neither the name of the University nor the names of its contributors
1.1 deraadt 17: * may be used to endorse or promote products derived from this software
18: * without specific prior written permission.
19: *
20: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30: * SUCH DAMAGE.
31: */
32:
33: #ifndef lint
1.11 millert 34: static const char copyright[] =
1.1 deraadt 35: "@(#) Copyright (c) 1993\n\
36: The Regents of the University of California. All rights reserved.\n";
37: #endif /* not lint */
38:
39: #ifndef lint
40: #if 0
1.11 millert 41: static const char sccsid[] = "@(#)lam.c 8.1 (Berkeley) 6/6/93";
1.1 deraadt 42: #endif
1.12 ! deraadt 43: static const char rcsid[] = "$OpenBSD: lam.c,v 1.11 2004/07/03 21:00:37 millert Exp $";
1.1 deraadt 44: #endif /* not lint */
45:
46: /*
47: * lam - laminate files
48: * Author: John Kunze, UCB
49: */
50:
1.11 millert 51: #include <ctype.h>
52: #include <err.h>
53: #include <limits.h>
1.1 deraadt 54: #include <stdio.h>
55: #include <stdlib.h>
56: #include <string.h>
57:
58: #define BIGBUFSIZ 5 * BUFSIZ
59:
60: struct openfile { /* open file structure */
61: FILE *fp; /* file pointer */
62: short eof; /* eof flag */
63: short pad; /* pad flag for missing columns */
64: char eol; /* end of line character */
65: char *sepstring; /* string to print before each line */
66: char *format; /* printf(3) style string spec. */
1.11 millert 67: } input[OPEN_MAX];
1.1 deraadt 68:
69: int morefiles; /* set by getargs(), changed by gatherline() */
70: int nofinalnl; /* normally append \n to each output line */
71: char line[BIGBUFSIZ];
72: char *linep;
73:
1.11 millert 74: void usage(void);
1.4 millert 75: char *gatherline(struct openfile *);
1.11 millert 76: void getargs(int, char *[]);
1.4 millert 77: char *pad(struct openfile *);
1.1 deraadt 78:
79: int
1.9 deraadt 80: main(int argc, char *argv[])
1.1 deraadt 81: {
1.3 mpech 82: struct openfile *ip;
1.1 deraadt 83:
1.11 millert 84: getargs(argc, argv);
1.1 deraadt 85: if (!morefiles)
1.11 millert 86: usage();
1.1 deraadt 87: for (;;) {
88: linep = line;
89: for (ip = input; ip->fp != NULL; ip++)
90: linep = gatherline(ip);
91: if (!morefiles)
92: exit(0);
93: fputs(line, stdout);
94: fputs(ip->sepstring, stdout);
95: if (!nofinalnl)
96: putchar('\n');
97: }
98: }
99:
100: void
1.11 millert 101: getargs(int argc, char *argv[])
1.1 deraadt 102: {
1.11 millert 103: struct openfile *ip = input;
1.3 mpech 104: char *p;
1.11 millert 105: int ch, P, S, F, T;
106: size_t siz;
1.1 deraadt 107:
108: P = S = F = T = 0; /* capitalized options */
1.11 millert 109: while (optind < argc) {
110: switch (ch = getopt(argc, argv, "F:f:P:p:S:s:T:t:")) {
111: case 'F': case 'f':
112: F = (ch == 'F');
113: /* Validate format string argument. */
114: for (p = optarg; *p != '\0'; p++)
115: if (!isdigit(*p) && *p != '.' && *p != '-')
116: errx(1, "%s: invalid width specified",
117: optarg);
118: /* '%' + width + 's' + '\0' */
119: siz = p - optarg + 3;
120: if ((p = realloc(ip->format, siz)) == NULL)
121: err(1, NULL);
122: snprintf(p, siz, "%%%ss", optarg);
123: ip->format = p;
124: break;
125: case 'P': case 'p':
126: P = (ch == 'P');
127: ip->pad = 1;
128: break;
129: case 'S': case 's':
130: S = (ch == 'S');
131: ip->sepstring = optarg;
132: break;
133: case 'T': case 't':
134: T = (ch == 'T');
135: if (strlen(optarg) != 1)
136: usage();
137: ip->eol = optarg[0];
138: nofinalnl = 1;
139: break;
140: case -1:
141: if (optind >= argc)
142: break; /* to support "--" */
1.1 deraadt 143: morefiles++;
1.11 millert 144: if (strcmp(argv[optind], "-") == 0)
1.1 deraadt 145: ip->fp = stdin;
1.11 millert 146: else if ((ip->fp = fopen(argv[optind], "r")) == NULL)
147: err(1, "%s", argv[optind]);
1.1 deraadt 148: ip->pad = P;
1.11 millert 149: if (ip->sepstring == NULL)
150: ip->sepstring = S ? (ip-1)->sepstring : "";
151: if (ip->format == NULL)
152: ip->format = (P || F) ? (ip-1)->format : "%s";
153: if (ip->eol == '\0')
154: ip->eol = T ? (ip-1)->eol : '\n';
1.1 deraadt 155: ip++;
1.11 millert 156: optind++;
1.1 deraadt 157: break;
158: default:
1.11 millert 159: usage();
160: /* NOTREACHED */
1.1 deraadt 161: }
162: }
163: ip->fp = NULL;
1.11 millert 164: if (ip->sepstring == NULL)
1.1 deraadt 165: ip->sepstring = "";
166: }
167:
168: char *
1.9 deraadt 169: pad(struct openfile *ip)
1.1 deraadt 170: {
1.7 millert 171: size_t n;
1.3 mpech 172: char *lp = linep;
1.1 deraadt 173:
1.7 millert 174: n = strlcpy(lp, ip->sepstring, line + sizeof(line) - lp);
175: lp += (n < line + sizeof(line) - lp) ? n : strlen(lp);
1.1 deraadt 176: if (ip->pad) {
1.7 millert 177: n = snprintf(lp, line + sizeof(line) - lp, ip->format, "");
1.12 ! deraadt 178: if (n > 0)
! 179: lp += (n < line + sizeof(line) - lp) ? n : strlen(lp);
1.1 deraadt 180: }
181: return (lp);
182: }
183:
184: char *
1.9 deraadt 185: gatherline(struct openfile *ip)
1.1 deraadt 186: {
1.7 millert 187: size_t n;
1.1 deraadt 188: char s[BUFSIZ];
1.3 mpech 189: char *p;
190: char *lp = linep;
1.11 millert 191: char *end = s + BUFSIZ - 1;
1.7 millert 192: int c;
1.1 deraadt 193:
194: if (ip->eof)
195: return (pad(ip));
196: for (p = s; (c = fgetc(ip->fp)) != EOF && p < end; p++)
197: if ((*p = c) == ip->eol)
198: break;
199: *p = '\0';
200: if (c == EOF) {
201: ip->eof = 1;
202: if (ip->fp == stdin)
203: fclose(stdin);
204: morefiles--;
205: return (pad(ip));
206: }
1.7 millert 207: n = strlcpy(lp, ip->sepstring, line + sizeof(line) - lp);
208: lp += (n < line + sizeof(line) - lp) ? n : strlen(lp);
1.11 millert 209: n = snprintf(lp, line + sizeof(line) - lp, ip->format, s);
1.12 ! deraadt 210: if (n > 0)
! 211: lp += (n < line + sizeof(line) - lp) ? n : strlen(lp);
1.1 deraadt 212: return (lp);
213: }
214:
215: void
1.11 millert 216: usage(void)
1.1 deraadt 217: {
1.10 mickey 218: extern char *__progname;
1.11 millert 219:
1.1 deraadt 220: fprintf(stderr,
1.11 millert 221: "usage: %s [-f min.max] [-p min.max] [-s sepstring] [-t c] file ...\n",
1.10 mickey 222: __progname);
1.1 deraadt 223: exit(1);
224: }