1 /* $OpenBSD: lpf.c,v 1.4 1997/07/19 07:11:42 deraadt Exp $ */ 2 3 /* 4 * Copyright (c) 1983, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by the University of 18 * California, Berkeley and its contributors. 19 * 4. Neither the name of the University nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36 #ifndef lint 37 static char copyright[] = 38 "@(#) Copyright (c) 1983, 1993\n\ 39 The Regents of the University of California. All rights reserved.\n"; 40 #endif /* not lint */ 41 42 #ifndef lint 43 #if 0 44 static char sccsid[] = "@(#)lpf.c 8.1 (Berkeley) 6/6/93"; 45 #else 46 static char rcsid[] = "$OpenBSD: lpf.c,v 1.4 1997/07/19 07:11:42 deraadt Exp $"; 47 #endif 48 #endif /* not lint */ 49 50 /* 51 * filter which reads the output of nroff and converts lines 52 * with ^H's to overwritten lines. Thus this works like 'ul' 53 * but is much better: it can handle more than 2 overwrites 54 * and it is written with some style. 55 * modified by kls to use register references instead of arrays 56 * to try to gain a little speed. 57 */ 58 59 #include <signal.h> 60 #include <unistd.h> 61 #include <stdlib.h> 62 #include <stdio.h> 63 64 #define MAXWIDTH 132 65 #define MAXREP 10 66 67 char buf[MAXREP][MAXWIDTH]; 68 int maxcol[MAXREP] = {-1}; 69 int lineno; 70 int width = 132; /* default line length */ 71 int length = 66; /* page length */ 72 int indent; /* indentation length */ 73 int npages = 1; 74 int literal; /* print control characters */ 75 int onlcr; /* map nl->cr-nl */ 76 char *name; /* user's login name */ 77 char *host; /* user's machine name */ 78 char *acctfile; /* accounting information file */ 79 80 int 81 main(argc, argv) 82 int argc; 83 char *argv[]; 84 { 85 register FILE *p = stdin, *o = stdout; 86 register int i, col; 87 register char *cp; 88 int done, linedone, maxrep; 89 char ch, *limit; 90 91 while (--argc) { 92 if (*(cp = *++argv) == '-') { 93 switch (cp[1]) { 94 case 'n': 95 argc--; 96 name = *++argv; 97 break; 98 99 case 'h': 100 argc--; 101 host = *++argv; 102 break; 103 104 case 'w': 105 if ((i = atoi(&cp[2])) > 0 && i <= MAXWIDTH) 106 width = i; 107 break; 108 109 case 'l': 110 length = atoi(&cp[2]); 111 break; 112 113 case 'i': 114 indent = atoi(&cp[2]); 115 break; 116 117 case 'r': /* map nl->cr-nl */ 118 onlcr++; 119 break; 120 121 case 'c': /* Print control chars */ 122 literal++; 123 break; 124 } 125 } else 126 acctfile = cp; 127 } 128 129 for (cp = buf[0], limit = buf[MAXREP]; cp < limit; *cp++ = ' '); 130 done = 0; 131 132 while (!done) { 133 col = indent; 134 maxrep = -1; 135 linedone = 0; 136 while (!linedone) { 137 switch (ch = getc(p)) { 138 case EOF: 139 linedone = done = 1; 140 ch = '\n'; 141 break; 142 143 case '\f': 144 lineno = length; 145 case '\n': 146 if (maxrep < 0) 147 maxrep = 0; 148 linedone = 1; 149 break; 150 151 case '\b': 152 if (--col < indent) 153 col = indent; 154 break; 155 156 case '\r': 157 col = indent; 158 break; 159 160 case '\t': 161 col = ((col - indent) | 07) + indent + 1; 162 break; 163 164 case '\031': 165 /* 166 * lpd needs to use a different filter to 167 * print data so stop what we are doing and 168 * wait for lpd to restart us. 169 */ 170 if ((ch = getchar()) == '\1') { 171 fflush(stdout); 172 kill(getpid(), SIGSTOP); 173 break; 174 } else { 175 ungetc(ch, stdin); 176 ch = '\031'; 177 } 178 179 default: 180 if ((col >= width) || (!literal && ch < ' ')) { 181 col++; 182 break; 183 } 184 cp = &buf[0][col]; 185 for (i = 0; i < MAXREP; i++) { 186 if (i > maxrep) 187 maxrep = i; 188 if (*cp == ' ') { 189 *cp = ch; 190 if (col > maxcol[i]) 191 maxcol[i] = col; 192 break; 193 } 194 cp += MAXWIDTH; 195 } 196 col++; 197 break; 198 } 199 } 200 201 /* print out lines */ 202 for (i = 0; i <= maxrep; i++) { 203 for (cp = buf[i], limit = cp+maxcol[i]; cp <= limit;) { 204 putc(*cp, o); 205 *cp++ = ' '; 206 } 207 if (i < maxrep) 208 putc('\r', o); 209 else { 210 if (onlcr) 211 putc('\r', o); 212 putc(ch, o); 213 } 214 if (++lineno >= length) { 215 fflush(o); 216 npages++; 217 lineno = 0; 218 } 219 maxcol[i] = -1; 220 } 221 } 222 if (lineno) { /* be sure to end on a page boundary */ 223 putchar('\f'); 224 npages++; 225 } 226 if (name && acctfile && access(acctfile, 02) >= 0 && 227 freopen(acctfile, "a", stdout) != NULL) { 228 printf("%7.2f\t%s:%s\n", (float)npages, host, name); 229 } 230 exit(0); 231 } 232