1: /*\
   2:  *
   3:  * ulf -- Universal Lineprinter Filter
   4:  *	  Written by Cliff Matthews, on April 7th, 1983 at the
   5:  *	  University of New Mexico
   6:  *
   7:  * Supports:  diablo and dumb (LA180, LA120) "lineprinters"
   8:  *
   9:  * This program uses a "line_structure" that is a linked list of arrays to
  10:  * hold enough characters for one physical line on the lineprinter.  The
  11:  * first array contains the characters of the line, and all subsequent arrays
  12:  * hold overprinting characters.  Blanks are left as zero's, so that they
  13:  * don't have to be printed, just move the printhead whatever way is easiest.
  14:  *
  15: \*/
  16: 
  17: #include    <stdio.h>
  18: #include    <ctype.h>
  19: #include    <errno.h>
  20: #include    <sgtty.h>
  21: #include    "lp.local.h"
  22: 
  23: #define CONTROL     20  /* How many tolerable control characters */
  24: #define RPRINT      "\0336" /* Make diablo print backword esc 6 */
  25: #define FPRINT      "\0335" /* Make diablo print forward  esc 5 */
  26: #define FORWARD     1   /* directions for diablo */
  27: #define BACKWARD    0   /* directions for diablo */
  28: 
  29: struct  line_s {
  30:     char    *line;
  31:     struct  line_s *next;
  32: };
  33: 
  34: char    *malloc();
  35: char    *rindex();
  36: char    *pgetstr();
  37: struct  line_s *makeline();
  38: 
  39: short   BR;     /* baud rate if lp is a tty */
  40: int FC;     /* flags to clear if lp is a tty */
  41: int FS;     /* flags to set if lp is a tty */
  42: int XC;     /* flags to clear for local mode */
  43: int XS;     /* flags to set for local mode */
  44: 
  45: char    *lpac;      /* where the lineprinter accounting is kept */
  46: char    *invoke;    /* name this filter was invoked as */
  47: char    *user;      /* name the user that this should be billed to */
  48: char    *ff;        /* what to use for a form feed */
  49: int linelen;    /* length of a line for current line_printer */
  50: int pagesize;   /* number of lines on a page */
  51: int manual;     /* paper must be fed by hand */
  52: int printhead;  /* location of the printhead */
  53: int diablo;     /* are we a diablo or not */
  54: int linenum;    /* number of lines printed so far on this page */
  55: unsigned pages;     /* number of pages printed */
  56: int direction;  /* 1 means we are printing forward */
  57: static  int eatme = 0;  /* set when disposing of bad output */
  58: 
  59: main(argc,argv)
  60: int argc;
  61: char *argv[];
  62: {
  63: 
  64:     char c;             /* last character read */
  65:     struct line_s *linepointer; /* chars to print later */
  66:     int loc;            /* current printing location */
  67: 
  68:     init(argv);
  69:     linepointer = makeline();
  70: 
  71:     while ( (c = getchar()) != EOF ) {
  72:     if (!eatme)
  73:         switch (c) {
  74:         case ' ':           /* Space */
  75:             loc++;
  76:             break;
  77: 
  78:         case '\b':          /* Backspace */
  79:             loc--;
  80:             break;
  81: 
  82:         case '\t':          /* Tab */
  83:             loc += 8 - (loc % 8);
  84:             break;
  85: 
  86:         case '\n':          /* New Line */
  87:             dumplines( linepointer );
  88:             loc = 0;
  89:             break;
  90: 
  91:         case '\r':          /* Carriage Return */
  92:             loc = 0;
  93:             break;
  94: 
  95:         case '\f':          /* Form Feed */
  96:             dumplines( linepointer );
  97:             loc = 0;
  98:             throwpage();
  99:             break;
 100: 
 101:         default:
 102:             c &= 0177;          /* Turn off parity */
 103:             if ( !isprint( c ) )
 104:             tossout();      /* Not Printable */
 105:             else
 106:                 if (( loc >= 0) && ( loc <= linelen - 1))
 107:                     place( c, loc++, linepointer );
 108:                 else
 109:                     loc++;          /* off page */
 110:         }
 111:     }
 112:     bill(user);
 113: }
 114: 
 115: static struct bauds {
 116:     int baud;
 117:     int speed;
 118: } bauds[] = {
 119:     50, B50,
 120:     75, B75,
 121:     110,    B110,
 122:     134,    B134,
 123:     150,    B150,
 124:     200,    B200,
 125:     300,    B300,
 126:     600,    B600,
 127:     1200,   B1200,
 128:     1800,   B1800,
 129:     2400,   B2400,
 130:     4800,   B4800,
 131:     9600,   B9600,
 132:     19200,  EXTA,
 133:     38400,  EXTB,
 134:     0,      0
 135: };
 136: 
 137: init(argv)          /* initialize global variables */
 138: char *argv[];
 139: {
 140:     static char buf[BUFSIZ/2];  /* Stolen from lpr.c */
 141:     char b[BUFSIZ];         /* Stolen from lpr.c */
 142:     int stat;           /* Stolen from lpr.c */
 143:     char *bp = buf;         /* Stolen from lpr.c */
 144:     char *cp;           /* scratch character pointer */
 145:     int i;              /* scratch index */
 146:     register struct bauds *baudp;
 147:     static struct sgttyb sbuf;
 148: 
 149:     printhead = 0;
 150:     linenum = 0;
 151:     pages = 1;
 152:     invoke = ((cp = rindex(*argv,'/')) ? cp + 1 : *argv);
 153:     user = argv[1];
 154: 
 155:     if (strncmp("diablo",invoke,sizeof("diablo")-sizeof(char)) == 0)
 156:         diablo = 1;
 157:     else
 158:         diablo = 0;
 159: 
 160:     if ((stat = pgetent(b, invoke)) <= 0) {
 161:         printf("%s: can't find printer description\n",invoke);
 162:         exit(3);
 163:     } else {
 164:         if ((linelen = pgetnum("pw", &bp)) == NULL)
 165:             linelen = DEFLINELEN;
 166:         if ((pagesize = pgetnum("pl", &bp)) == NULL)
 167:             pagesize = DEFPAGESIZE;
 168:         BR = pgetnum("br", &bp);
 169:         if ((lpac = pgetstr("af", &bp)) == NULL)
 170:             lpac = DEFACCOUNTFILE;
 171:         if ((ff = pgetstr("ff", &bp)) == NULL)
 172:             ff = "\f";
 173:         if ((FC = pgetnum("fc")) < 0)
 174:             FC = 0;
 175:         if ((FS = pgetnum("fs")) < 0)
 176:             FS = 0;
 177:         if ((XC = pgetnum("xc")) < 0)
 178:             XC = 0;
 179:         if ((XS = pgetnum("xs")) < 0)
 180:             XS = 0;
 181:         if ((LF = pgetstr("lf", &bp)) == NULL)
 182:             LF = DEFLOGF;
 183:     }
 184: 
 185:     if (ioctl(fileno(stdout), TIOCEXCL, (char *)0) < 0) {
 186:         log("cannot set exclusive-use");
 187:         exit(1);
 188:     }
 189:     if (ioctl(fileno(stdout), TIOCGETP, (char *) &sbuf) < 0) {
 190:         log("cannot get tty parameters");
 191:         exit(1);
 192:     }
 193: 
 194:     if (BR) {
 195:         for (baudp = bauds; baudp->baud; baudp++)
 196:             if (BR == baudp->baud)
 197:                 break;
 198:             if (!baudp->baud) {
 199:                 log("illegal baud rate %d", BR);
 200:                 exit(1);
 201:             }
 202:             sbuf.sg_ispeed = sbuf.sg_ospeed = baudp->speed;
 203:     }
 204:     sbuf.sg_flags &= ~FC;
 205:     sbuf.sg_flags |= FS;
 206:     if (ioctl(fileno(stdout), TIOCSETP, (char *)&sbuf) < 0) {
 207:         log("cannot set tty parameters");
 208:         exit(1);
 209:     }
 210:     if (XC) {
 211:         if (ioctl(fileno(stdout), TIOCLBIC, (char *) &XC) < 0) {
 212:             log("cannot set local tty parameters");
 213:             exit(1);
 214:         }
 215:     }
 216:     if (XS) {
 217:         if (ioctl(fileno(stdout), TIOCLBIS, (char *) &XS) < 0) {
 218:             log("cannot set local tty parameters");
 219:             exit(1);
 220:         }
 221:     }
 222: 
 223:     putchar ('\r');
 224:     direction = FORWARD;
 225: }
 226: 
 227: struct line_s *
 228: makeline()  /* malloc up some memory for a line_structure */
 229: {
 230:     struct line_s *s;   /* memory allocated for the new line */
 231:     char *cp;       /* scratch char pointer */
 232:     char *end;      /* last legal array position for while loop */
 233: 
 234:     s = (struct line_s *) malloc(sizeof(struct line_s));
 235:     if ( s == 0 )
 236:         outofmemory();
 237:     else {
 238:         s->next = NULL;
 239:         cp = s->line = malloc(linelen + 1);
 240:         if ( s->line == 0)
 241:             outofmemory();
 242:         else {
 243:             end = s->line + linelen;
 244:             while ( cp < end )
 245:                 *cp++ = ' ';
 246:             *cp = 0;
 247:         }
 248:     }
 249:     return (s);
 250: }
 251: 
 252: tossout()   /* toss out invalid characters, and keep count, maybe puke */
 253: {
 254: 
 255:     static int tossed = 0;  /* how many characters have been discarded */
 256: 
 257:     if (++tossed > CONTROL) {
 258:         if (diablo)
 259:             spaceto(0,FORWARD);
 260:         printf("\r\n\n\n\n\n\n");
 261:         printf("%s: *************************************\r\n",invoke);
 262:         printf("%s: *************************************\r\n",invoke);
 263:         printf("%s: *************************************\r\n",invoke);
 264:         printf("%s: Too many control characters in output\r\n",invoke);
 265:         printf("%s: *************************************\r\n",invoke);
 266:         printf("%s: *************************************\r\n",invoke);
 267:         printf("%s: *************************************\r\n",invoke);
 268:         eatme = 1;
 269:     }
 270: }
 271: 
 272: place(c, location, p)   /* add a new character to a line_structure */
 273: char c;         /* character to place */
 274: struct line_s *p;   /* structure to put character in */
 275: int location;       /* where in the line the character should go */
 276: {
 277:     char *cp;
 278: 
 279:     if (*(cp = (p->line + location)) != ' ') {
 280:         if (p->next == NULL)
 281:             p->next = makeline();
 282:         place(c, location, p->next);
 283:     } else
 284:         *cp = c;
 285: }
 286: 
 287: dumplines(p)        /* dump the top-level line_structure */
 288: struct line_s *p;
 289: {
 290:     char *cp, *end; /* scratch, and last legit array element */
 291: 
 292:     if (p->next != NULL)
 293:         rdumpl(p->next);
 294:     qprint(p->line);
 295:     printf("\n");
 296: 
 297:     linenum++;
 298:     if (linenum == pagesize) {
 299:         pages++;
 300:         linenum = 0;
 301:     }
 302: 
 303:     cp = p->line;
 304:     end = cp + linelen;
 305:     while ( cp < end )
 306:         *cp++ = ' ';
 307: 
 308:     p->next = NULL;
 309: }
 310: 
 311: 
 312: rdumpl(p)       /* recursively dump the overprints */
 313: struct line_s *p;
 314: {
 315:     if (p->next != NULL)
 316:         rdumpl(p->next);
 317:     qprint(p->line);
 318:     free(p->line);
 319:     free(p);
 320: }
 321: 
 322: outofmemory()
 323: {
 324:     printf("%s: Out of Memory\n",invoke);
 325:     exit(ENOMEM);
 326: }
 327: 
 328: qprint(line)        /* print a line efficiently */
 329: char *line;
 330: {
 331:     char *cp;       /* scratch character pointer */
 332:     char *end;      /* last legitimate array position */
 333:     int r,l;        /* right most character, leftmost */
 334:     int i,j;        /* temporary values */
 335: 
 336:     cp = line + linelen - 1;
 337:     while ( cp >= line && *cp == ' ')
 338:         --cp;
 339: 
 340:     if ( cp < line )
 341:         return;
 342: 
 343:     if (diablo) {
 344:         r = cp - line;
 345:         end = line + linelen;
 346:         cp = line;
 347:         while ( *cp++ == ' ' );
 348:         l = cp - line - 1;
 349:         i = abs(printhead - l) + (2 * ((direction == FORWARD) ? 1 : -1));
 350:         j = abs(printhead - r);
 351:         if ( (printhead < l) || (i < j) ) {
 352:             spaceto(l,FORWARD);
 353:             pr(line,l,r);
 354:         } else {
 355:             spaceto(r,BACKWARD);
 356:             pr(line,r,l);
 357:         }
 358: 
 359:     } else {
 360:         *++cp = '\0';
 361:         printf("%s\r", line);
 362:     }
 363: }
 364: 
 365: spaceto( where, dir)
 366: int where;          /* which column */
 367: int dir;            /* which way to go afterward */
 368: {
 369:     if (where == 0) {
 370:         putchar('\r');
 371:         direction = FORWARD;    /* where else should we go */
 372:     } else {
 373:         if ( direction != dir ) {
 374:             printf("%s", ( dir == FORWARD ) ? FPRINT : RPRINT );
 375:             direction = dir;
 376:         }
 377:         if (printhead != where) {
 378:             putchar('\033');    /* <esc><tab># gets you to # */
 379:             putchar('\t');
 380:             putchar((char)where+1);
 381:         }
 382:     }
 383:     printhead = where;
 384: }
 385: 
 386: pr(line,start,stop) /* prints the characters from start to stop */
 387: int start;      /* array index of first character */
 388: int stop;       /* array index of last character */
 389: char *line;     /* line to play with */
 390: {
 391:     char *end;      /* last character location to access */
 392:     char *cp;       /* scratch character position */
 393: 
 394:     end = line + stop;
 395:     cp = line + start;
 396:     if (start < stop) {
 397:         while ( cp <= end )
 398:             putchar( *cp++ );
 399:         printhead = stop+1;
 400:     } else {
 401:         while ( cp >= end )
 402:             putchar( *cp-- );
 403:         if ( printhead < 0 )
 404:             printhead = 0;
 405:         printhead = stop-1;
 406:     }
 407: }
 408: 
 409: throwpage()     /* toss a page */
 410: {
 411:     register int x;
 412: 
 413:     printf("%s",ff);
 414:     pages++;
 415: 
 416:     linenum = 0;
 417: }
 418: 
 419: bill(account)
 420: char *account;
 421: {
 422:     FILE *fopen(), *ac;
 423: 
 424:     if ((ac = fopen(lpac,"a")) != NULL) {
 425:         fprintf(ac,"%s\t%u\n",account,pages);
 426:         fclose(ac);
 427:     }
 428: }
 429: 
 430: /*VARARGS1*/
 431: log(message, a1, a2, a3)
 432: char *message;
 433: {
 434:     short console;
 435:     FILE *lfd;
 436:     lfd = fopen(lf,"a");
 437:     console = isatty(fileno(lfd));
 438: 
 439:     fprintf(lfd, console ? "\r\n%s: " : "%s: ", invoke);
 440:     fprintf(lfd, message, a1, a2, a3);
 441:     if (console)
 442:         putc('\r', lfd);
 443:     putc('\n', lfd);
 444:     fclose(lfd);
 445: }

Defined functions

bill defined in line 419; used 1 times
dumplines defined in line 287; used 2 times
init defined in line 137; used 1 times
  • in line 68
log defined in line 431; used 6 times
main defined in line 59; never used
makeline defined in line 227; used 3 times
outofmemory defined in line 322; used 2 times
place defined in line 272; used 2 times
pr defined in line 386; used 2 times
qprint defined in line 328; used 2 times
rdumpl defined in line 312; used 2 times
spaceto defined in line 365; used 3 times
throwpage defined in line 409; used 1 times
  • in line 98
tossout defined in line 252; used 1 times

Defined variables

BR defined in line 39; used 4 times
FC defined in line 40; used 3 times
FS defined in line 41; used 3 times
XC defined in line 42; used 4 times
XS defined in line 43; used 4 times
bauds defined in line 118; used 1 times
diablo defined in line 53; used 4 times
direction defined in line 56; used 5 times
eatme defined in line 57; used 2 times
ff defined in line 48; used 3 times
invoke defined in line 46; used 13 times
linelen defined in line 49; used 8 times
linenum defined in line 54; used 5 times
lpac defined in line 45; used 3 times
manual defined in line 51; never used
pages defined in line 55; used 4 times
pagesize defined in line 50; used 3 times
printhead defined in line 52; used 10 times
user defined in line 47; used 2 times

Defined struct's

bauds defined in line 115; used 2 times
  • in line 146(2)
line_s defined in line 29; used 20 times

Defined macros

BACKWARD defined in line 27; used 1 times
CONTROL defined in line 23; used 1 times
FORWARD defined in line 26; used 6 times
FPRINT defined in line 25; used 1 times
RPRINT defined in line 24; used 1 times
Last modified: 1983-12-10
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1345
Valid CSS Valid XHTML 1.0 Strict