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