Annotation of src/usr.bin/lam/lam.c, Revision 1.8
1.8 ! millert 1: /* $OpenBSD: lam.c,v 1.7 2003/04/21 00:42:49 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
34: static char copyright[] =
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
41: static char sccsid[] = "@(#)lam.c 8.1 (Berkeley) 6/6/93";
42: #endif
1.8 ! millert 43: static char rcsid[] = "$OpenBSD: lam.c,v 1.7 2003/04/21 00:42:49 millert Exp $";
1.1 deraadt 44: #endif /* not lint */
45:
46: /*
47: * lam - laminate files
48: * Author: John Kunze, UCB
49: */
50:
51: #include <stdio.h>
52: #include <stdlib.h>
53: #include <string.h>
54:
55: #define MAXOFILES 20
56: #define BIGBUFSIZ 5 * BUFSIZ
57:
58: struct openfile { /* open file structure */
59: FILE *fp; /* file pointer */
60: short eof; /* eof flag */
61: short pad; /* pad flag for missing columns */
62: char eol; /* end of line character */
63: char *sepstring; /* string to print before each line */
64: char *format; /* printf(3) style string spec. */
65: } input[MAXOFILES];
66:
67: int morefiles; /* set by getargs(), changed by gatherline() */
68: int nofinalnl; /* normally append \n to each output line */
69: char line[BIGBUFSIZ];
70: char *linep;
71:
1.4 millert 72: void error(char *, char *);
73: char *gatherline(struct openfile *);
74: void getargs(char *[]);
75: char *pad(struct openfile *);
1.1 deraadt 76:
77: int
78: main(argc, argv)
79: int argc;
80: char *argv[];
81: {
1.3 mpech 82: struct openfile *ip;
1.1 deraadt 83:
84: getargs(argv);
85: if (!morefiles)
86: error("lam - laminate files", "");
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
101: getargs(av)
102: char *av[];
103: {
1.3 mpech 104: struct openfile *ip = input;
105: char *p;
106: char *c;
1.1 deraadt 107: static char fmtbuf[BUFSIZ];
108: char *fmtp = fmtbuf;
109: int P, S, F, T;
110:
111: P = S = F = T = 0; /* capitalized options */
112: while ((p = *++av) != NULL) {
113: if (*p != '-' || !p[1]) {
114: morefiles++;
115: if (*p == '-')
116: ip->fp = stdin;
117: else if ((ip->fp = fopen(p, "r")) == NULL) {
118: perror(p);
119: exit(1);
120: }
121: ip->pad = P;
122: if (!ip->sepstring)
123: ip->sepstring = (S ? (ip-1)->sepstring : "");
124: if (!ip->format)
125: ip->format = ((P || F) ? (ip-1)->format : "%s");
126: if (!ip->eol)
127: ip->eol = (T ? (ip-1)->eol : '\n');
128: ip++;
129: continue;
130: }
131: switch (*(c = ++p) | 040) {
132: case 's':
133: if (*++p || (p = *++av))
134: ip->sepstring = p;
135: else
136: error("Need string after -%s", c);
137: S = (*c == 'S' ? 1 : 0);
138: break;
139: case 't':
140: if (*++p || (p = *++av))
141: ip->eol = *p;
142: else
143: error("Need character after -%s", c);
144: T = (*c == 'T' ? 1 : 0);
145: nofinalnl = 1;
146: break;
147: case 'p':
148: ip->pad = 1;
149: P = (*c == 'P' ? 1 : 0);
150: case 'f':
151: F = (*c == 'F' ? 1 : 0);
152: if (*++p || (p = *++av)) {
153: fmtp += strlen(fmtp) + 1;
1.6 krw 154: if (fmtp >= fmtbuf + BUFSIZ)
1.1 deraadt 155: error("No more format space", "");
1.5 deraadt 156: snprintf(fmtp, fmtbuf + BUFSIZ - fmtp,
157: "%%%ss", p);
1.1 deraadt 158: ip->format = fmtp;
159: }
160: else
161: error("Need string after -%s", c);
162: break;
163: default:
164: error("What do you mean by -%s?", c);
165: break;
166: }
167: }
168: ip->fp = NULL;
169: if (!ip->sepstring)
170: ip->sepstring = "";
171: }
172:
173: char *
174: pad(ip)
175: struct openfile *ip;
176: {
1.7 millert 177: size_t n;
1.3 mpech 178: char *lp = linep;
1.1 deraadt 179:
1.7 millert 180: n = strlcpy(lp, ip->sepstring, line + sizeof(line) - lp);
181: lp += (n < line + sizeof(line) - lp) ? n : strlen(lp);
1.1 deraadt 182: if (ip->pad) {
1.7 millert 183: n = snprintf(lp, line + sizeof(line) - lp, ip->format, "");
184: lp += (n < line + sizeof(line) - lp) ? n : strlen(lp);
1.1 deraadt 185: }
186: return (lp);
187: }
188:
189: char *
190: gatherline(ip)
191: struct openfile *ip;
192: {
1.7 millert 193: size_t n;
1.1 deraadt 194: char s[BUFSIZ];
1.3 mpech 195: char *p;
196: char *lp = linep;
1.1 deraadt 197: char *end = s + BUFSIZ;
1.7 millert 198: int c;
1.1 deraadt 199:
200: if (ip->eof)
201: return (pad(ip));
202: for (p = s; (c = fgetc(ip->fp)) != EOF && p < end; p++)
203: if ((*p = c) == ip->eol)
204: break;
205: *p = '\0';
206: if (c == EOF) {
207: ip->eof = 1;
208: if (ip->fp == stdin)
209: fclose(stdin);
210: morefiles--;
211: return (pad(ip));
212: }
1.7 millert 213: n = strlcpy(lp, ip->sepstring, line + sizeof(line) - lp);
214: lp += (n < line + sizeof(line) - lp) ? n : strlen(lp);
215: n = snprintf(lp, line + sizeof line - lp, ip->format, s);
216: lp += (n < line + sizeof(line) - lp) ? n : strlen(lp);
1.1 deraadt 217: return (lp);
218: }
219:
220: void
221: error(msg, s)
222: char *msg, *s;
223: {
224: fprintf(stderr, "lam: ");
225: fprintf(stderr, msg, s);
226: fprintf(stderr,
227: "\nUsage: lam [ -[fp] min.max ] [ -s sepstring ] [ -t c ] file ...\n");
228: if (strncmp("lam - ", msg, 6) == 0)
229: fprintf(stderr, "Options:\n\t%s\t%s\t%s\t%s\t%s",
230: "-f min.max field widths for file fragments\n",
231: "-p min.max like -f, but pad missing fragments\n",
232: "-s sepstring fragment separator\n",
233: "-t c input line terminator is c, no \\n after output lines\n",
234: "Capitalized options affect more than one file.\n");
235: exit(1);
236: }