1 /*- 2 * Copyright (c) 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * @(#) Copyright (c) 1993 The Regents of the University of California. All rights reserved. 34 * @(#)lam.c 8.1 (Berkeley) 6/6/93 35 * $FreeBSD: src/usr.bin/lam/lam.c,v 1.3.2.3 2001/08/11 03:03:19 mike Exp $ 36 * $DragonFly: src/usr.bin/lam/lam.c,v 1.3 2003/10/04 20:36:47 hmp Exp $ 37 */ 38 39 /* 40 * lam - laminate files 41 * Author: John Kunze, UCB 42 */ 43 44 #include <ctype.h> 45 #include <err.h> 46 #include <stdio.h> 47 #include <stdlib.h> 48 #include <string.h> 49 50 #define MAXOFILES 20 51 #define BIGBUFSIZ 5 * BUFSIZ 52 53 struct openfile { /* open file structure */ 54 FILE *fp; /* file pointer */ 55 short eof; /* eof flag */ 56 short pad; /* pad flag for missing columns */ 57 char eol; /* end of line character */ 58 const char *sepstring; /* string to print before each line */ 59 const char *format; /* printf(3) style string spec. */ 60 } input[MAXOFILES]; 61 62 int morefiles; /* set by getargs(), changed by gatherline() */ 63 int nofinalnl; /* normally append \n to each output line */ 64 char line[BIGBUFSIZ]; 65 char *linep; 66 67 static char *gatherline(struct openfile *); 68 static void getargs(char *[]); 69 static char *pad(struct openfile *); 70 static void usage(void); 71 72 int 73 main(int argc __unused, char *argv[]) 74 { 75 struct openfile *ip; 76 77 getargs(argv); 78 if (!morefiles) 79 usage(); 80 for (;;) { 81 linep = line; 82 for (ip = input; ip->fp != NULL; ip++) 83 linep = gatherline(ip); 84 if (!morefiles) 85 exit(0); 86 fputs(line, stdout); 87 fputs(ip->sepstring, stdout); 88 if (!nofinalnl) 89 putchar('\n'); 90 } 91 } 92 93 static void 94 getargs(char *av[]) 95 { 96 struct openfile *ip = input; 97 char *p, *c; 98 static char fmtbuf[BUFSIZ]; 99 char *fmtp = fmtbuf; 100 int P, S, F, T; 101 102 P = S = F = T = 0; /* capitalized options */ 103 while ((p = *++av) != NULL) { 104 if (*p != '-' || !p[1]) { 105 if (++morefiles >= MAXOFILES) 106 errx(1, "too many input files"); 107 if (*p == '-') 108 ip->fp = stdin; 109 else if ((ip->fp = fopen(p, "r")) == NULL) { 110 err(1, "%s", p); 111 } 112 ip->pad = P; 113 if (!ip->sepstring) 114 ip->sepstring = (S ? (ip-1)->sepstring : ""); 115 if (!ip->format) 116 ip->format = ((P || F) ? (ip-1)->format : "%s"); 117 if (!ip->eol) 118 ip->eol = (T ? (ip-1)->eol : '\n'); 119 ip++; 120 continue; 121 } 122 c = ++p; 123 switch (tolower(*c)) { 124 case 's': 125 if (*++p || (p = *++av)) 126 ip->sepstring = p; 127 else 128 errx(1, "need string after -%s", c); 129 S = (*c == 'S' ? 1 : 0); 130 break; 131 case 't': 132 if (*++p || (p = *++av)) 133 ip->eol = *p; 134 else 135 errx(1, "need character after -%s", c); 136 T = (*c == 'T' ? 1 : 0); 137 nofinalnl = 1; 138 break; 139 case 'p': 140 ip->pad = 1; 141 P = (*c == 'P' ? 1 : 0); 142 /* FALLTHROUGH */ 143 case 'f': 144 F = (*c == 'F' ? 1 : 0); 145 if (*++p || (p = *++av)) { 146 fmtp += strlen(fmtp) + 1; 147 if (fmtp >= fmtbuf + sizeof(fmtbuf)) 148 errx(1, "no more format space"); 149 /* restrict format string to only valid width formatters */ 150 if (strspn(p, "-.0123456789") != strlen(p)) 151 errx(1, "invalid format string `%s'", p); 152 if (snprintf(fmtp, fmtbuf + sizeof(fmtbuf) - fmtp, "%%%ss", p) 153 >= fmtbuf + sizeof(fmtbuf) - fmtp) 154 errx(1, "no more format space"); 155 ip->format = fmtp; 156 } 157 else 158 errx(1, "need string after -%s", c); 159 break; 160 default: 161 errx(1, "what do you mean by -%s?", c); 162 break; 163 } 164 } 165 ip->fp = NULL; 166 if (!ip->sepstring) 167 ip->sepstring = ""; 168 } 169 170 static char * 171 pad(struct openfile *ip) 172 { 173 char *lp = linep; 174 175 strlcpy(lp, ip->sepstring, line + sizeof(line) - lp); 176 lp += strlen(lp); 177 if (ip->pad) { 178 snprintf(lp, line + sizeof(line) - lp, ip->format, ""); 179 lp += strlen(lp); 180 } 181 return (lp); 182 } 183 184 static char * 185 gatherline(struct openfile *ip) 186 { 187 char s[BUFSIZ]; 188 int c; 189 char *p; 190 char *lp = linep; 191 char *end = s + sizeof(s) - 1; 192 193 if (ip->eof) 194 return (pad(ip)); 195 for (p = s; (c = fgetc(ip->fp)) != EOF && p < end; p++) 196 if ((*p = c) == ip->eol) 197 break; 198 *p = '\0'; 199 if (c == EOF) { 200 ip->eof = 1; 201 if (ip->fp == stdin) 202 fclose(stdin); 203 morefiles--; 204 return (pad(ip)); 205 } 206 strlcpy(lp, ip->sepstring, line + sizeof(line) - lp); 207 lp += strlen(lp); 208 snprintf(lp, line + sizeof(line) - lp, ip->format, s); 209 lp += strlen(lp); 210 return (lp); 211 } 212 213 static void 214 usage(void) 215 { 216 fprintf(stderr, "%s\n%s\n", 217 "usage: lam [ -f min.max ] [ -s sepstring ] [ -t c ] file ...", 218 " lam [ -p min.max ] [ -s sepstring ] [ -t c ] file ..."); 219 exit(1); 220 } 221