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