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