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