1 /* 2 * Copyright (c) 1983, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 */ 7 8 #ifndef lint 9 static char copyright[] = 10 "@(#) Copyright (c) 1983, 1993\n\ 11 The Regents of the University of California. All rights reserved.\n"; 12 #endif /* not lint */ 13 14 #ifndef lint 15 static char sccsid[] = "@(#)lpf.c 8.1 (Berkeley) 06/06/93"; 16 #endif /* not lint */ 17 18 /* 19 * filter which reads the output of nroff and converts lines 20 * with ^H's to overwritten lines. Thus this works like 'ul' 21 * but is much better: it can handle more than 2 overwrites 22 * and it is written with some style. 23 * modified by kls to use register references instead of arrays 24 * to try to gain a little speed. 25 */ 26 27 #include <signal.h> 28 #include <unistd.h> 29 #include <stdlib.h> 30 #include <stdio.h> 31 32 #define MAXWIDTH 132 33 #define MAXREP 10 34 35 char buf[MAXREP][MAXWIDTH]; 36 int maxcol[MAXREP] = {-1}; 37 int lineno; 38 int width = 132; /* default line length */ 39 int length = 66; /* page length */ 40 int indent; /* indentation length */ 41 int npages = 1; 42 int literal; /* print control characters */ 43 char *name; /* user's login name */ 44 char *host; /* user's machine name */ 45 char *acctfile; /* accounting information file */ 46 47 int 48 main(argc, argv) 49 int argc; 50 char *argv[]; 51 { 52 register FILE *p = stdin, *o = stdout; 53 register int i, col; 54 register char *cp; 55 int done, linedone, maxrep; 56 char ch, *limit; 57 58 while (--argc) { 59 if (*(cp = *++argv) == '-') { 60 switch (cp[1]) { 61 case 'n': 62 argc--; 63 name = *++argv; 64 break; 65 66 case 'h': 67 argc--; 68 host = *++argv; 69 break; 70 71 case 'w': 72 if ((i = atoi(&cp[2])) > 0 && i <= MAXWIDTH) 73 width = i; 74 break; 75 76 case 'l': 77 length = atoi(&cp[2]); 78 break; 79 80 case 'i': 81 indent = atoi(&cp[2]); 82 break; 83 84 case 'c': /* Print control chars */ 85 literal++; 86 break; 87 } 88 } else 89 acctfile = cp; 90 } 91 92 for (cp = buf[0], limit = buf[MAXREP]; cp < limit; *cp++ = ' '); 93 done = 0; 94 95 while (!done) { 96 col = indent; 97 maxrep = -1; 98 linedone = 0; 99 while (!linedone) { 100 switch (ch = getc(p)) { 101 case EOF: 102 linedone = done = 1; 103 ch = '\n'; 104 break; 105 106 case '\f': 107 lineno = length; 108 case '\n': 109 if (maxrep < 0) 110 maxrep = 0; 111 linedone = 1; 112 break; 113 114 case '\b': 115 if (--col < indent) 116 col = indent; 117 break; 118 119 case '\r': 120 col = indent; 121 break; 122 123 case '\t': 124 col = ((col - indent) | 07) + indent + 1; 125 break; 126 127 case '\031': 128 /* 129 * lpd needs to use a different filter to 130 * print data so stop what we are doing and 131 * wait for lpd to restart us. 132 */ 133 if ((ch = getchar()) == '\1') { 134 fflush(stdout); 135 kill(getpid(), SIGSTOP); 136 break; 137 } else { 138 ungetc(ch, stdin); 139 ch = '\031'; 140 } 141 142 default: 143 if (col >= width || !literal && ch < ' ') { 144 col++; 145 break; 146 } 147 cp = &buf[0][col]; 148 for (i = 0; i < MAXREP; i++) { 149 if (i > maxrep) 150 maxrep = i; 151 if (*cp == ' ') { 152 *cp = ch; 153 if (col > maxcol[i]) 154 maxcol[i] = col; 155 break; 156 } 157 cp += MAXWIDTH; 158 } 159 col++; 160 break; 161 } 162 } 163 164 /* print out lines */ 165 for (i = 0; i <= maxrep; i++) { 166 for (cp = buf[i], limit = cp+maxcol[i]; cp <= limit;) { 167 putc(*cp, o); 168 *cp++ = ' '; 169 } 170 if (i < maxrep) 171 putc('\r', o); 172 else 173 putc(ch, o); 174 if (++lineno >= length) { 175 fflush(o); 176 npages++; 177 lineno = 0; 178 } 179 maxcol[i] = -1; 180 } 181 } 182 if (lineno) { /* be sure to end on a page boundary */ 183 putchar('\f'); 184 npages++; 185 } 186 if (name && acctfile && access(acctfile, 02) >= 0 && 187 freopen(acctfile, "a", stdout) != NULL) { 188 printf("%7.2f\t%s:%s\n", (float)npages, host, name); 189 } 190 exit(0); 191 } 192