1 /* $NetBSD: lpf.c,v 1.9 2000/04/30 15:47:55 thorpej 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.9 2000/04/30 15:47:55 thorpej 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 <string.h> 57 #include <unistd.h> 58 #include <stdlib.h> 59 #include <stdio.h> 60 61 #define MAXWIDTH 132 62 #define MAXREP 10 63 64 char buf[MAXREP][MAXWIDTH]; 65 int maxcol[MAXREP] = {-1}; 66 int lineno; 67 int width = 132; /* default line length */ 68 int length = 66; /* page length */ 69 int indent; /* indentation length */ 70 int npages = 1; 71 int literal; /* print control characters */ 72 char *name; /* user's login name */ 73 char *host; /* user's machine name */ 74 char *acctfile; /* accounting information file */ 75 int crnl; /* \n -> \r\n */ 76 int need_cr; 77 78 int main __P((int, char *[])); 79 void usage __P((void)); 80 81 int 82 main(argc, argv) 83 int argc; 84 char *argv[]; 85 { 86 FILE *p = stdin, *o = stdout; 87 int i, col; 88 char *cp; 89 int done, linedone, maxrep, ch, prch; 90 char *limit; 91 92 while ((ch = getopt(argc, argv, "cfh:i:l:n:w:")) != -1) 93 switch (ch) { 94 case 'n': 95 name = optarg; 96 break; 97 case 'h': 98 host = optarg; 99 break; 100 case 'w': 101 if ((i = atoi(optarg)) > 0 && i <= MAXWIDTH) 102 width = i; 103 break; 104 case 'l': 105 length = atoi(optarg); 106 break; 107 case 'i': 108 indent = atoi(optarg); 109 break; 110 case 'c': /* Print control chars */ 111 literal++; 112 break; 113 case 'f': /* Fix missing carriage returns */ 114 crnl++; 115 break; 116 default: 117 usage(); 118 } 119 argc -= optind; 120 argv += optind; 121 if (argc) 122 acctfile = *argv; 123 124 memset(buf, ' ', sizeof(buf)); 125 done = 0; 126 127 while (!done) { 128 col = indent; 129 maxrep = -1; 130 linedone = 0; 131 prch = ch = 0; 132 need_cr = 0; 133 while (!linedone) { 134 prch = ch; 135 switch (ch = getc(p)) { 136 case EOF: 137 linedone = done = 1; 138 ch = '\n'; 139 break; 140 141 case '\f': 142 lineno = length; 143 case '\n': 144 if (crnl && prch != '\r') 145 need_cr = 1; 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 (need_cr) 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 233 void 234 usage() 235 { 236 fprintf(stderr, 237 "usage: lpf [-c] [-f] [-h host] [-i indent] [-l length] [-n name] [-w width] [acctfile]\n"); 238 exit(1); 239 240 } 241 242