1 /* $OpenBSD: lam.c,v 1.9 2003/06/10 22:20:47 deraadt Exp $ */ 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. 16 * 3. Neither the name of the University nor the names of its contributors 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 43 static char rcsid[] = "$OpenBSD: lam.c,v 1.9 2003/06/10 22:20:47 deraadt Exp $"; 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 72 void error(char *, char *); 73 char *gatherline(struct openfile *); 74 void getargs(char *[]); 75 char *pad(struct openfile *); 76 77 int 78 main(int argc, char *argv[]) 79 { 80 struct openfile *ip; 81 82 getargs(argv); 83 if (!morefiles) 84 error("lam - laminate files", ""); 85 for (;;) { 86 linep = line; 87 for (ip = input; ip->fp != NULL; ip++) 88 linep = gatherline(ip); 89 if (!morefiles) 90 exit(0); 91 fputs(line, stdout); 92 fputs(ip->sepstring, stdout); 93 if (!nofinalnl) 94 putchar('\n'); 95 } 96 } 97 98 void 99 getargs(char *av[]) 100 { 101 struct openfile *ip = input; 102 char *p; 103 char *c; 104 static char fmtbuf[BUFSIZ]; 105 char *fmtp = fmtbuf; 106 int P, S, F, T; 107 108 P = S = F = T = 0; /* capitalized options */ 109 while ((p = *++av) != NULL) { 110 if (*p != '-' || !p[1]) { 111 morefiles++; 112 if (*p == '-') 113 ip->fp = stdin; 114 else if ((ip->fp = fopen(p, "r")) == NULL) { 115 perror(p); 116 exit(1); 117 } 118 ip->pad = P; 119 if (!ip->sepstring) 120 ip->sepstring = (S ? (ip-1)->sepstring : ""); 121 if (!ip->format) 122 ip->format = ((P || F) ? (ip-1)->format : "%s"); 123 if (!ip->eol) 124 ip->eol = (T ? (ip-1)->eol : '\n'); 125 ip++; 126 continue; 127 } 128 switch (*(c = ++p) | 040) { 129 case 's': 130 if (*++p || (p = *++av)) 131 ip->sepstring = p; 132 else 133 error("Need string after -%s", c); 134 S = (*c == 'S' ? 1 : 0); 135 break; 136 case 't': 137 if (*++p || (p = *++av)) 138 ip->eol = *p; 139 else 140 error("Need character after -%s", c); 141 T = (*c == 'T' ? 1 : 0); 142 nofinalnl = 1; 143 break; 144 case 'p': 145 ip->pad = 1; 146 P = (*c == 'P' ? 1 : 0); 147 case 'f': 148 F = (*c == 'F' ? 1 : 0); 149 if (*++p || (p = *++av)) { 150 fmtp += strlen(fmtp) + 1; 151 if (fmtp >= fmtbuf + BUFSIZ) 152 error("No more format space", ""); 153 snprintf(fmtp, fmtbuf + BUFSIZ - fmtp, 154 "%%%ss", p); 155 ip->format = fmtp; 156 } 157 else 158 error("Need string after -%s", c); 159 break; 160 default: 161 error("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 char * 171 pad(struct openfile *ip) 172 { 173 size_t n; 174 char *lp = linep; 175 176 n = strlcpy(lp, ip->sepstring, line + sizeof(line) - lp); 177 lp += (n < line + sizeof(line) - lp) ? n : strlen(lp); 178 if (ip->pad) { 179 n = snprintf(lp, line + sizeof(line) - lp, ip->format, ""); 180 lp += (n < line + sizeof(line) - lp) ? n : strlen(lp); 181 } 182 return (lp); 183 } 184 185 char * 186 gatherline(struct openfile *ip) 187 { 188 size_t n; 189 char s[BUFSIZ]; 190 char *p; 191 char *lp = linep; 192 char *end = s + BUFSIZ; 193 int c; 194 195 if (ip->eof) 196 return (pad(ip)); 197 for (p = s; (c = fgetc(ip->fp)) != EOF && p < end; p++) 198 if ((*p = c) == ip->eol) 199 break; 200 *p = '\0'; 201 if (c == EOF) { 202 ip->eof = 1; 203 if (ip->fp == stdin) 204 fclose(stdin); 205 morefiles--; 206 return (pad(ip)); 207 } 208 n = strlcpy(lp, ip->sepstring, line + sizeof(line) - lp); 209 lp += (n < line + sizeof(line) - lp) ? n : strlen(lp); 210 n = snprintf(lp, line + sizeof line - lp, ip->format, s); 211 lp += (n < line + sizeof(line) - lp) ? n : strlen(lp); 212 return (lp); 213 } 214 215 void 216 error(char *msg, char *s) 217 { 218 fprintf(stderr, "lam: "); 219 fprintf(stderr, msg, s); 220 fprintf(stderr, 221 "\nUsage: lam [ -[fp] min.max ] [ -s sepstring ] [ -t c ] file ...\n"); 222 if (strncmp("lam - ", msg, 6) == 0) 223 fprintf(stderr, "Options:\n\t%s\t%s\t%s\t%s\t%s", 224 "-f min.max field widths for file fragments\n", 225 "-p min.max like -f, but pad missing fragments\n", 226 "-s sepstring fragment separator\n", 227 "-t c input line terminator is c, no \\n after output lines\n", 228 "Capitalized options affect more than one file.\n"); 229 exit(1); 230 } 231