19b50d902SRodney W. Grimes /*- 29b50d902SRodney W. Grimes * Copyright (c) 1993 39b50d902SRodney W. Grimes * The Regents of the University of California. All rights reserved. 49b50d902SRodney W. Grimes * 59b50d902SRodney W. Grimes * Redistribution and use in source and binary forms, with or without 69b50d902SRodney W. Grimes * modification, are permitted provided that the following conditions 79b50d902SRodney W. Grimes * are met: 89b50d902SRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 99b50d902SRodney W. Grimes * notice, this list of conditions and the following disclaimer. 109b50d902SRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 119b50d902SRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 129b50d902SRodney W. Grimes * documentation and/or other materials provided with the distribution. 13*fbbd9655SWarner Losh * 3. Neither the name of the University nor the names of its contributors 149b50d902SRodney W. Grimes * may be used to endorse or promote products derived from this software 159b50d902SRodney W. Grimes * without specific prior written permission. 169b50d902SRodney W. Grimes * 179b50d902SRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 189b50d902SRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 199b50d902SRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 209b50d902SRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 219b50d902SRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 229b50d902SRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 239b50d902SRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 249b50d902SRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 259b50d902SRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 269b50d902SRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 279b50d902SRodney W. Grimes * SUCH DAMAGE. 289b50d902SRodney W. Grimes */ 299b50d902SRodney W. Grimes 309b50d902SRodney W. Grimes #ifndef lint 31df899658SPhilippe Charnier static const char copyright[] = 329b50d902SRodney W. Grimes "@(#) Copyright (c) 1993\n\ 339b50d902SRodney W. Grimes The Regents of the University of California. All rights reserved.\n"; 349b50d902SRodney W. Grimes #endif /* not lint */ 359b50d902SRodney W. Grimes 369b50d902SRodney W. Grimes #ifndef lint 37df899658SPhilippe Charnier #if 0 389b50d902SRodney W. Grimes static char sccsid[] = "@(#)lam.c 8.1 (Berkeley) 6/6/93"; 39df899658SPhilippe Charnier #endif 409b50d902SRodney W. Grimes #endif /* not lint */ 41e026a48cSDavid E. O'Brien #include <sys/cdefs.h> 42e026a48cSDavid E. O'Brien __FBSDID("$FreeBSD$"); 439b50d902SRodney W. Grimes 449b50d902SRodney W. Grimes /* 459b50d902SRodney W. Grimes * lam - laminate files 469b50d902SRodney W. Grimes * Author: John Kunze, UCB 479b50d902SRodney W. Grimes */ 489b50d902SRodney W. Grimes 49ba032055SAllan Jude #include <sys/capsicum.h> 50ba032055SAllan Jude 51ba032055SAllan Jude #include <capsicum_helpers.h> 52aeacf525SMike Heffner #include <ctype.h> 53df899658SPhilippe Charnier #include <err.h> 54ba032055SAllan Jude #include <errno.h> 559b50d902SRodney W. Grimes #include <stdio.h> 569b50d902SRodney W. Grimes #include <stdlib.h> 579b50d902SRodney W. Grimes #include <string.h> 58ba032055SAllan Jude #include <unistd.h> 599b50d902SRodney W. Grimes 609b50d902SRodney W. Grimes #define MAXOFILES 20 619b50d902SRodney W. Grimes #define BIGBUFSIZ 5 * BUFSIZ 629b50d902SRodney W. Grimes 6386350df6SEd Schouten static struct openfile { /* open file structure */ 649b50d902SRodney W. Grimes FILE *fp; /* file pointer */ 659b50d902SRodney W. Grimes short eof; /* eof flag */ 669b50d902SRodney W. Grimes short pad; /* pad flag for missing columns */ 679b50d902SRodney W. Grimes char eol; /* end of line character */ 68b5b9b430SMike Barcroft const char *sepstring; /* string to print before each line */ 69b5b9b430SMike Barcroft const char *format; /* printf(3) style string spec. */ 709b50d902SRodney W. Grimes } input[MAXOFILES]; 719b50d902SRodney W. Grimes 7286350df6SEd Schouten static int morefiles; /* set by getargs(), changed by gatherline() */ 7386350df6SEd Schouten static int nofinalnl; /* normally append \n to each output line */ 7486350df6SEd Schouten static char line[BIGBUFSIZ]; 7586350df6SEd Schouten static char *linep; 769b50d902SRodney W. Grimes 77b5b9b430SMike Barcroft static char *gatherline(struct openfile *); 78b5b9b430SMike Barcroft static void getargs(char *[]); 79b5b9b430SMike Barcroft static char *pad(struct openfile *); 807a536c3bSMike Heffner static void usage(void); 819b50d902SRodney W. Grimes 829b50d902SRodney W. Grimes int 83f63eec78SJuli Mallett main(int argc, char *argv[]) 849b50d902SRodney W. Grimes { 85aeacf525SMike Heffner struct openfile *ip; 869b50d902SRodney W. Grimes 87f201bc9cSJuli Mallett if (argc == 1) 88df899658SPhilippe Charnier usage(); 890064a5b3SBaptiste Daroussin if (caph_limit_stdio() == -1) 900064a5b3SBaptiste Daroussin err(1, "unable to limit stdio"); 91f63eec78SJuli Mallett getargs(argv); 92f201bc9cSJuli Mallett if (!morefiles) 93f201bc9cSJuli Mallett usage(); 94ba032055SAllan Jude 95ba032055SAllan Jude /* 96ba032055SAllan Jude * Cache NLS data, for strerror, for err(3), before entering capability 97ba032055SAllan Jude * mode. 98ba032055SAllan Jude */ 99ba032055SAllan Jude caph_cache_catpages(); 100ba032055SAllan Jude if (cap_enter() < 0 && errno != ENOSYS) 101ba032055SAllan Jude err(1, "unable to enter capability mode"); 102ba032055SAllan Jude 1039b50d902SRodney W. Grimes for (;;) { 1049b50d902SRodney W. Grimes linep = line; 1059b50d902SRodney W. Grimes for (ip = input; ip->fp != NULL; ip++) 1069b50d902SRodney W. Grimes linep = gatherline(ip); 1079b50d902SRodney W. Grimes if (!morefiles) 1089b50d902SRodney W. Grimes exit(0); 1099b50d902SRodney W. Grimes fputs(line, stdout); 1109b50d902SRodney W. Grimes fputs(ip->sepstring, stdout); 1119b50d902SRodney W. Grimes if (!nofinalnl) 1129b50d902SRodney W. Grimes putchar('\n'); 1139b50d902SRodney W. Grimes } 1149b50d902SRodney W. Grimes } 1159b50d902SRodney W. Grimes 116b5b9b430SMike Barcroft static void 1178ecfa014SMike Heffner getargs(char *av[]) 1189b50d902SRodney W. Grimes { 119aeacf525SMike Heffner struct openfile *ip = input; 120aeacf525SMike Heffner char *p, *c; 1219b50d902SRodney W. Grimes static char fmtbuf[BUFSIZ]; 1229b50d902SRodney W. Grimes char *fmtp = fmtbuf; 1239b50d902SRodney W. Grimes int P, S, F, T; 124ba032055SAllan Jude cap_rights_t rights_ro; 1259b50d902SRodney W. Grimes 126ba032055SAllan Jude cap_rights_init(&rights_ro, CAP_READ, CAP_FSTAT); 1279b50d902SRodney W. Grimes P = S = F = T = 0; /* capitalized options */ 1289b50d902SRodney W. Grimes while ((p = *++av) != NULL) { 1299b50d902SRodney W. Grimes if (*p != '-' || !p[1]) { 130f201bc9cSJuli Mallett if (++morefiles >= MAXOFILES) 131f201bc9cSJuli Mallett errx(1, "too many input files"); 132f201bc9cSJuli Mallett if (*p == '-') 1339b50d902SRodney W. Grimes ip->fp = stdin; 134f201bc9cSJuli Mallett else if ((ip->fp = fopen(p, "r")) == NULL) { 1350c4d24a7SKris Kennaway err(1, "%s", p); 1369b50d902SRodney W. Grimes } 137ba032055SAllan Jude if (cap_rights_limit(fileno(ip->fp), &rights_ro) < 0) 138ba032055SAllan Jude err(1, "unable to limit rights on: %s", p); 1399b50d902SRodney W. Grimes ip->pad = P; 1409b50d902SRodney W. Grimes if (!ip->sepstring) 1419b50d902SRodney W. Grimes ip->sepstring = (S ? (ip-1)->sepstring : ""); 1429b50d902SRodney W. Grimes if (!ip->format) 1439b50d902SRodney W. Grimes ip->format = ((P || F) ? (ip-1)->format : "%s"); 1449b50d902SRodney W. Grimes if (!ip->eol) 1459b50d902SRodney W. Grimes ip->eol = (T ? (ip-1)->eol : '\n'); 1469b50d902SRodney W. Grimes ip++; 1479b50d902SRodney W. Grimes continue; 1489b50d902SRodney W. Grimes } 149aeacf525SMike Heffner c = ++p; 150be1e385eSTim J. Robbins switch (tolower((unsigned char)*c)) { 1519b50d902SRodney W. Grimes case 's': 1529b50d902SRodney W. Grimes if (*++p || (p = *++av)) 1539b50d902SRodney W. Grimes ip->sepstring = p; 1549b50d902SRodney W. Grimes else 155dfaacec6SJuli Mallett usage(); 1569b50d902SRodney W. Grimes S = (*c == 'S' ? 1 : 0); 1579b50d902SRodney W. Grimes break; 1589b50d902SRodney W. Grimes case 't': 1599b50d902SRodney W. Grimes if (*++p || (p = *++av)) 1609b50d902SRodney W. Grimes ip->eol = *p; 1619b50d902SRodney W. Grimes else 162dfaacec6SJuli Mallett usage(); 1639b50d902SRodney W. Grimes T = (*c == 'T' ? 1 : 0); 1649b50d902SRodney W. Grimes nofinalnl = 1; 1659b50d902SRodney W. Grimes break; 1669b50d902SRodney W. Grimes case 'p': 1679b50d902SRodney W. Grimes ip->pad = 1; 1689b50d902SRodney W. Grimes P = (*c == 'P' ? 1 : 0); 169aeacf525SMike Heffner /* FALLTHROUGH */ 1709b50d902SRodney W. Grimes case 'f': 1719b50d902SRodney W. Grimes F = (*c == 'F' ? 1 : 0); 1729b50d902SRodney W. Grimes if (*++p || (p = *++av)) { 1739b50d902SRodney W. Grimes fmtp += strlen(fmtp) + 1; 174aeacf525SMike Heffner if (fmtp >= fmtbuf + sizeof(fmtbuf)) 175df899658SPhilippe Charnier errx(1, "no more format space"); 176aeacf525SMike Heffner /* restrict format string to only valid width formatters */ 177aeacf525SMike Heffner if (strspn(p, "-.0123456789") != strlen(p)) 178aeacf525SMike Heffner errx(1, "invalid format string `%s'", p); 179aeacf525SMike Heffner if (snprintf(fmtp, fmtbuf + sizeof(fmtbuf) - fmtp, "%%%ss", p) 180aeacf525SMike Heffner >= fmtbuf + sizeof(fmtbuf) - fmtp) 181aeacf525SMike Heffner errx(1, "no more format space"); 1829b50d902SRodney W. Grimes ip->format = fmtp; 1839b50d902SRodney W. Grimes } 1849b50d902SRodney W. Grimes else 185dfaacec6SJuli Mallett usage(); 1869b50d902SRodney W. Grimes break; 1879b50d902SRodney W. Grimes default: 188dfaacec6SJuli Mallett usage(); 1899b50d902SRodney W. Grimes } 1909b50d902SRodney W. Grimes } 1919b50d902SRodney W. Grimes ip->fp = NULL; 1929b50d902SRodney W. Grimes if (!ip->sepstring) 1939b50d902SRodney W. Grimes ip->sepstring = ""; 1949b50d902SRodney W. Grimes } 1959b50d902SRodney W. Grimes 196b5b9b430SMike Barcroft static char * 1977a536c3bSMike Heffner pad(struct openfile *ip) 1989b50d902SRodney W. Grimes { 199aeacf525SMike Heffner char *lp = linep; 2009b50d902SRodney W. Grimes 201aeacf525SMike Heffner strlcpy(lp, ip->sepstring, line + sizeof(line) - lp); 202aeacf525SMike Heffner lp += strlen(lp); 2039b50d902SRodney W. Grimes if (ip->pad) { 204aeacf525SMike Heffner snprintf(lp, line + sizeof(line) - lp, ip->format, ""); 2059b50d902SRodney W. Grimes lp += strlen(lp); 2069b50d902SRodney W. Grimes } 2079b50d902SRodney W. Grimes return (lp); 2089b50d902SRodney W. Grimes } 2099b50d902SRodney W. Grimes 210b5b9b430SMike Barcroft static char * 2117a536c3bSMike Heffner gatherline(struct openfile *ip) 2129b50d902SRodney W. Grimes { 2139b50d902SRodney W. Grimes char s[BUFSIZ]; 214aeacf525SMike Heffner int c; 215aeacf525SMike Heffner char *p; 216aeacf525SMike Heffner char *lp = linep; 217aeacf525SMike Heffner char *end = s + sizeof(s) - 1; 2189b50d902SRodney W. Grimes 2199b50d902SRodney W. Grimes if (ip->eof) 2209b50d902SRodney W. Grimes return (pad(ip)); 2219b50d902SRodney W. Grimes for (p = s; (c = fgetc(ip->fp)) != EOF && p < end; p++) 2229b50d902SRodney W. Grimes if ((*p = c) == ip->eol) 2239b50d902SRodney W. Grimes break; 2249b50d902SRodney W. Grimes *p = '\0'; 2259b50d902SRodney W. Grimes if (c == EOF) { 2269b50d902SRodney W. Grimes ip->eof = 1; 2279b50d902SRodney W. Grimes if (ip->fp == stdin) 2289b50d902SRodney W. Grimes fclose(stdin); 2299b50d902SRodney W. Grimes morefiles--; 2309b50d902SRodney W. Grimes return (pad(ip)); 2319b50d902SRodney W. Grimes } 232aeacf525SMike Heffner strlcpy(lp, ip->sepstring, line + sizeof(line) - lp); 233aeacf525SMike Heffner lp += strlen(lp); 234aeacf525SMike Heffner snprintf(lp, line + sizeof(line) - lp, ip->format, s); 2359b50d902SRodney W. Grimes lp += strlen(lp); 2369b50d902SRodney W. Grimes return (lp); 2379b50d902SRodney W. Grimes } 2389b50d902SRodney W. Grimes 239df899658SPhilippe Charnier static void 240ef636796SEd Schouten usage(void) 2419b50d902SRodney W. Grimes { 242df899658SPhilippe Charnier fprintf(stderr, "%s\n%s\n", 243df899658SPhilippe Charnier "usage: lam [ -f min.max ] [ -s sepstring ] [ -t c ] file ...", 244df899658SPhilippe Charnier " lam [ -p min.max ] [ -s sepstring ] [ -t c ] file ..."); 2459b50d902SRodney W. Grimes exit(1); 2469b50d902SRodney W. Grimes } 247