home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume16 / plp / part08 < prev    next >
Text File  |  1988-09-14  |  50KB  |  1,622 lines

  1. Subject:  v16i021:  Public lineprinter spooler package, Part08/16
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rsalz@uunet.UU.NET
  5.  
  6. Submitted-by: papowell@julius.cs.umn.edu
  7. Posting-number: Volume 16, Issue 21
  8. Archive-name: plp/part08
  9.  
  10. #! /bin/sh
  11. # This is a shell archive.  Remove anything before this line, then unpack
  12. # it by saving it into a file and typing "sh file".  To overwrite existing
  13. # files, type "sh file -c".  You can also feed this as standard input via
  14. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  15. # will see the following message at the end:
  16. #        "End of archive 8 (of 16)."
  17. # Contents:  filters/main.c src/link_support.c src/lpr.c
  18. #   src/lpr_filters.c
  19. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  20. if test -f 'filters/main.c' -a "${1}" != "-c" ; then 
  21.   echo shar: Will not clobber existing file \"'filters/main.c'\"
  22. else
  23. echo shar: Extracting \"'filters/main.c'\" \(11034 characters\)
  24. sed "s/^X//" >'filters/main.c' <<'END_OF_FILE'
  25. X/***************************************************************************
  26. X * U. Minnesota LPD Software * Copyright 1987, 1988, Patrick Powell
  27. X ***************************************************************************
  28. X * MODULE: main.c for filters
  29. X ***************************************************************************
  30. X * Revision History: Created Fri Mar  4 19:45:03 CST 1988
  31. X * $Log:    main.c,v $
  32. X * Revision 2.2  88/05/19  07:36:17  papowell
  33. X * Added a -D (debug) flag
  34. X * 
  35. X * Revision 2.1  88/05/09  10:12:10  papowell
  36. X * *** empty log message ***
  37. X * 
  38. X ***************************************************************************/
  39. X#ifndef lint
  40. static char id_str1[] =
  41. X    "$Header: main.c,v 2.2 88/05/19 07:36:17 papowell Locked $ PLP Copyright 1988 Patrick Powell";
  42. X#endif lint
  43. X/***************************************************************************
  44. X *  UMN-LPR filter template and frontend.
  45. X *
  46. X *    A filter is invoked with the following parameters,
  47. X *  which can be in any order, and perhaps some missing.
  48. X *
  49. X *  filtername arguments \   <- from PRINTCAP entry
  50. X *      -PPrinter -wwidth -llength -xwidth -ylength [-c] [-iindent] \
  51. X *        [-Zoptions] [-Cclass] [-Jjob] [-Raccntname] -nlogin -hHost  \
  52. X *      -Fformat -Ddebug [affile]
  53. X * 
  54. X *  1. Parameters can be in different order than the above.
  55. X *  2. Optional parameters can be missing
  56. X *  3. Values specified for the width, length, etc., are from PRINTCAP
  57. X *     or from the overridding user specified options.
  58. X *
  59. X *  This program provides a common front end for most of the necessary
  60. X *  grunt work.  This falls into the following classes:
  61. X * 1. Parameter extraction.
  62. X * 2. Suspension when used as the "of" filter.
  63. X * 3. Termination and accounting
  64. X *  The front end will extract parameters,  then call the filter()
  65. X *  routine,  which is responsible for carrying out the required filter
  66. X *  actions. filter() is invoked with the printer device on fd 1,
  67. X *    and error log on fd 2.  The npages variable is used to record the
  68. X *  number of pages that were used.
  69. X *  The "halt string", which is a sequence of characters that
  70. X *  should cause the filter to suspend itself, is passed to filter.
  71. X *  When these characters are detected,  the "suspend()" routine should be
  72. X *  called.
  73. X *
  74. X *  On successful termination,  the accounting file will be updated.
  75. X *
  76. X *  The filter() routine should return 0 (success), 1 (retry) or 2 (abort).
  77. X *
  78. X * Parameter Extraction
  79. X *    The main() routine will extract parameters
  80. X *  whose values are placed in the appropriate variables.  This is done
  81. X *  by using the ParmTable[], which has entries for each valid letter
  82. X *  parmeter, such as the letter flag, the type of variable,
  83. X *  and the address of the variable.
  84. X *  The following variables are provided as a default set.
  85. X *      -PPrinter -wwidth -llength -xwidth -ylength [-c] [-iindent] \
  86. X *        [-Zoptions] [-Cclass] [-Jjob] [-Raccntname] -nlogin -hHost  \
  87. X *      -Fformat [affile]
  88. X * VARIABLE  FLAG          TYPE    PURPOSE / PRINTCAP ENTRTY
  89. X * name     name of filter char*    argv[0], program identification
  90. X * width    -wwidth           int      PW, width in chars
  91. X * length   -llength       int      PL, length in lines
  92. X * xwidth   -xwidth        int      PX, width in pixels
  93. X * xlength  -xlength       int      PY, length in pixels
  94. X * literal  -c               int      if set, ignore control chars
  95. X * indent   -iindent       int      indent amount (depends on device)
  96. X * zopts    -Zoptions      char*    extra options for printer
  97. X * class    -Cclass        char*    classname
  98. X * job      -Jjob          char*    jobname
  99. X * accntname -Raccntname   char*    account for billing purposes
  100. X * login    -nlogin        char*    login name
  101. X * host     -hhost         char*    host name
  102. X * format   -Fformat       char*    format
  103. X * accntfile file          char*    AF, accounting file
  104. X *
  105. X * npages    - number of pages for accounting
  106. X * debug     - sets debug level
  107. X *
  108. X *    The functions fatal(), logerr(), and logerr_die() can be used to report
  109. X *    status. The variable errorcode can be set by the user before calling
  110. X *    these functions, and will be the exit value of the program. Its default
  111. X *    value will be 2 (abort status).
  112. X *    fatal() reports a fatal message, and terminates.
  113. X *    logerr() reports a message, appends information indicated by errno
  114. X *    (see perror(2) for details), and then returns.
  115. X *    logerr_die() will call logerr(), and then will exit with errorcode
  116. X *    status.
  117. X *    Both fatal() and logerr_die() call the cleanup() function before exit.
  118. X *
  119. X * DEBUGGING:  a simple minded debugging version can be enabled by
  120. X * compiling with the -DDEBUG option.
  121. X */
  122. X
  123. X#include <stdio.h>
  124. X#include <sys/types.h>
  125. X#include <sys/file.h>
  126. X#include <signal.h>
  127. X
  128. X/*
  129. X * default exit status, causes abort
  130. X */
  131. int errorcode = 2;
  132. X
  133. char *name;        /* name of filter */
  134. X/* set from flags */
  135. int debug, width, length, xwidth, ylength, literal, indent;
  136. char *zopts, *class, *job, *login, *accntname, *host, *accntfile, *format;
  137. char *printer;
  138. int npages;    /* number of pages */
  139. char filter_stop[] = "\031\001";    /* sent to cause filter to suspend */
  140. X
  141. main( argc, argv )
  142. X    int argc;
  143. X    char **argv;
  144. X{
  145. X    int i;
  146. X
  147. X    getargs( argc, argv );
  148. X    /*
  149. X     * Turn off SIGPIPE
  150. X     */
  151. X    (void)signal( SIGPIPE, SIG_IGN );
  152. X    if( format && *format == 'o' ){
  153. X        filter( filter_stop );
  154. X    } else {
  155. X        filter( (char *)0 );
  156. X    }
  157. X    doaccnt();
  158. X    return(0);
  159. X}
  160. X
  161. X/*VARARGS1*/
  162. log(msg, a1, a2, a3)
  163. X    char *msg;
  164. X{
  165. X    (void)fprintf(stderr, "%s: ", name);
  166. X    (void)fprintf(stderr, msg, a1, a2, a3);
  167. X    (void)putc('\n', stderr);
  168. X    (void)fflush(stderr);
  169. X}
  170. X
  171. X
  172. X/*VARARGS1*/
  173. fatal(msg, a1, a2, a3)
  174. X    char *msg;
  175. X{
  176. X    log(msg, a1, a2, a3);
  177. X    cleanup();
  178. X    exit(errorcode);
  179. X}
  180. X
  181. X
  182. X/*VARARGS1*/
  183. logerr(msg, a1, a2, a3)
  184. X    char *msg;
  185. X{
  186. X    extern int errno, sys_nerr;
  187. X    extern char *sys_errlist[];
  188. X    int err = errno;
  189. X
  190. X    (void)fprintf(stderr, "%s: ", name);
  191. X    if (msg){
  192. X        (void)fprintf(stderr, msg, a1, a2, a3);
  193. X        (void)fputs( "- ", stderr);
  194. X    }
  195. X    if( err < sys_nerr ){
  196. X        (void)fputs(sys_errlist[err]);
  197. X    } else {
  198. X        (void)fprintf(stderr, "Unknown error %d", err);
  199. X    }
  200. X    (void)putc('\n', stderr);
  201. X    (void)fflush(stderr);
  202. X}
  203. X
  204. X/*VARARGS1*/
  205. logerr_die(msg, a1, a2, a3)
  206. X    char *msg;
  207. X{
  208. X    logerr(msg, a1, a2, a3);
  209. X    cleanup();
  210. X    exit(errorcode);
  211. X}
  212. X
  213. X/*
  214. X *    doaccnt()
  215. X *    writes the accounting information to the accounting file
  216. X *  This has the format: user host printer pages format date
  217. X */
  218. doaccnt()
  219. X{
  220. X    time_t t, time();
  221. X    char *ctime();
  222. X    FILE *f;
  223. X
  224. X    t = time((time_t *)0);
  225. X    if(accntfile && access(accntfile, W_OK) >= 0 &&
  226. X        (f = fopen(accntfile, "a" )) != NULL) {
  227. X        fprintf(f,"%s\t%s\t%s\t%7d\t%s\t%s",
  228. X            login? login: "NULL", 
  229. X            host? host: "NULL", 
  230. X            printer? printer: "NULL", 
  231. X            npages,
  232. X            format? format: "NULL", 
  233. X            ctime(&t));
  234. X        (void)fclose(f);
  235. X    }
  236. X}
  237. X
  238. getargs(argc, argv)
  239. X    int argc;
  240. X    char **argv;
  241. X{
  242. X    int i;        /* argument index */
  243. X    char *arg;    /* argument */
  244. X    int flag;    /* flag */
  245. X
  246. X    name = argv[0];
  247. X    for( i = 1; i < argc; ++i ){
  248. X        arg = argv[i];
  249. X        if( *arg == '-' ){ /* arg will be string */
  250. X                setvar( arg[1], &arg[2] );
  251. X        } else {
  252. X            /* must be accounting file */
  253. X            accntfile = arg;
  254. X        }
  255. X    }
  256. X    if( debug ){
  257. X        for( i = 0; i < argc; ++i ){
  258. X            fprintf(stderr, "%s ", argv[i] );
  259. X        }
  260. X        fprintf( stderr, "\n" );
  261. X        fprintf(stderr,"login '%s'\n", login? login : "null" );
  262. X        fprintf(stderr,"host '%s'\n", host? host : "null" );
  263. X        fprintf(stderr,"class '%s'\n", class? class : "null" );
  264. X        fprintf(stderr,"format '%s'\n", format? format : "null" );
  265. X        fprintf(stderr,"job '%s'\n", job? job : "null" );
  266. X        fprintf(stderr,"printer '%s'\n", printer? printer : "null" );
  267. X        fprintf(stderr,"accntname '%s'\n", accntname? accntname : "null" );
  268. X        fprintf(stderr,"zopts '%s'\n", zopts? zopts : "null" );
  269. X        fprintf(stderr,"literal, %d\n", literal);
  270. X        fprintf(stderr,"indent, %d\n", indent);
  271. X        fprintf(stderr,"length, %d\n", length);
  272. X        fprintf(stderr,"width, %d\n", width);
  273. X        fprintf(stderr,"xwidth, %d\n", xwidth);
  274. X        fprintf(stderr,"ylength, %d\n", ylength);
  275. X        fprintf(stderr,"accntfile '%s'\n", accntfile? accntfile : "null" );
  276. X        for( i = 0; i < argc; ++i ){
  277. X            fprintf(stderr, "%s ", argv[i] );
  278. X        }
  279. X        fprintf( stderr, "\n" );
  280. X        fflush(stderr);
  281. X        fflush(stderr);
  282. X    }
  283. X}
  284. X            
  285. X#define INTV 0
  286. X#define STRV 1
  287. X#define FLGV 2
  288. struct parm {
  289. X    int flag;
  290. X    char **var;
  291. X    int kind;
  292. X} Parmlist[] = {
  293. X{'C', &class, STRV },
  294. X{'D', (char **)&debug, INTV },
  295. X{'F', &format, STRV },
  296. X{'J', &job, STRV },
  297. X{'P', &printer, STRV },
  298. X{'R', &accntname, STRV },
  299. X{'Z', &zopts, STRV },
  300. X{'c', (char **)&literal, FLGV },
  301. X{'h', &host, STRV },
  302. X{'i', (char **)&indent, INTV },
  303. X{'l', (char **)&length, INTV },
  304. X{'n', &login, STRV },
  305. X{'w', (char **)&width, INTV },
  306. X{'x', (char **)&xwidth, INTV },
  307. X{'y', (char **)&ylength, INTV } };
  308. X
  309. int Parmlen = sizeof(Parmlist)/sizeof(struct parm);
  310. X
  311. X/*
  312. X * setvar( int flag, char *arg )
  313. X * 1. look in table and find entry
  314. X * 2. if STRV, then set 
  315. X * 3. if INTV, then convert and set
  316. X * 4. if FLGV, then set to 1
  317. X */
  318. setvar( flag, arg )
  319. X    int flag;
  320. X    char *arg;
  321. X{
  322. X    int u, l, i, c;    /* upper, lower, i */
  323. X
  324. X    l = 0; u = Parmlen;
  325. X    while( l <= u ){
  326. X        i = (u+l)/2;
  327. X        c = flag - Parmlist[i].flag;
  328. X        if( 0 == c ){
  329. X            /* printf( "found parm %c, %d\n", flag, i ); */
  330. X            switch( Parmlist[i].kind ){
  331. X            case STRV: *Parmlist[i].var = arg; break;
  332. X            case INTV: *(int *)Parmlist[i].var = atoi(arg); break;
  333. X            case FLGV: *(int *)Parmlist[i].var = 1; break;
  334. X            }
  335. X            return;
  336. X        } else if( c < 0 ){
  337. X            /* fprintf(stderr, "down parm %c, %d\n", flag, i ); */
  338. X            u = i - 1 ;
  339. X        } else {
  340. X            /* fprintf(stderr, "up parm %c, %d\n", flag, i ); */
  341. X            l = i + 1 ;
  342. X        }
  343. X    }
  344. X    /* fprintf(stderr, "did not find parm %c, %d\n", flag, i ); */
  345. X    return;
  346. X}
  347. X
  348. X/*
  349. X * suspend():  suspends the output filter, waits for a signal
  350. X */
  351. suspend()
  352. X{
  353. X    if(debug)fprintf(stderr,"suspending\n");
  354. X    fflush(stderr);
  355. X    kill(getpid(), SIGSTOP);
  356. X    if(debug)fprintf(stderr,"awake\n");
  357. X    fflush(stderr);
  358. X}
  359. X#ifdef DEBUG
  360. X/******************************************
  361. X * prototype filter() and cleanup() functions;
  362. X * filter will scan the input looking for the suspend string
  363. X * if any.
  364. X ******************************************/
  365. cleanup() {}
  366. X
  367. filter(stop)
  368. X    char *stop;
  369. X{
  370. X    int c;
  371. X    int state, i;
  372. X    int lines = 0;
  373. X
  374. X    /*
  375. X     * do whatever initializations are needed
  376. X     */
  377. X    /* fprintf(stderr, "filter ('%s')\n", stop ? stop : "NULL" ); */
  378. X    /*
  379. X     * now scan the input string, looking for the stop string
  380. X     */
  381. X    state = 0;
  382. X    npages = 1;
  383. X
  384. X    while( (c = getchar()) != EOF ){
  385. X        if( c == '\n' ){
  386. X            ++lines;
  387. X            if( lines > length ){
  388. X                lines -= length;
  389. X                ++npages;
  390. X            }
  391. X        }
  392. X        if( stop || state ){
  393. X            if( c == stop[state] ){
  394. X                ++state;
  395. X                if( stop[state] == 0 ){
  396. X                    state = 0;
  397. X                    if( fflush(stdout) ){
  398. X                        logerr_die( "fflush returned error" );
  399. X                    }
  400. X                    suspend();
  401. X                }
  402. X            } else if( state ){
  403. X                for( i = 0; i < state; ++i ){
  404. X                    dochar( stop[i] );
  405. X                }
  406. X                state = 0;
  407. X                dochar( c );
  408. X            } else {
  409. X                dochar( c );
  410. X            }
  411. X        } else {
  412. X            dochar( c );
  413. X        }
  414. X    }
  415. X    if( ferror( stdin ) ){
  416. X        logerr_die( "read error on stdin");
  417. X    }
  418. X    for( i = 0; i < state; ++i ){
  419. X        dochar( stop[i] );
  420. X    }
  421. X    if( lines > 0 ){
  422. X        ++npages;
  423. X    }
  424. X    if( fflush(stdout) ){
  425. X        logerr_die( "fflush returned error" );
  426. X    }
  427. X}
  428. X
  429. dochar(c)
  430. X    int c;
  431. X{
  432. X    putchar( c );
  433. X}
  434. X#endif DEBUG
  435. END_OF_FILE
  436. if test 11034 -ne `wc -c <'filters/main.c'`; then
  437.     echo shar: \"'filters/main.c'\" unpacked with wrong size!
  438. fi
  439. # end of 'filters/main.c'
  440. fi
  441. if test -f 'src/link_support.c' -a "${1}" != "-c" ; then 
  442.   echo shar: Will not clobber existing file \"'src/link_support.c'\"
  443. else
  444. echo shar: Extracting \"'src/link_support.c'\" \(12422 characters\)
  445. sed "s/^X//" >'src/link_support.c' <<'END_OF_FILE'
  446. X/***************************************************************************
  447. X * U. Minnesota LPD Software * Copyright 1987, 1988, Patrick Powell
  448. X ***************************************************************************
  449. X * MODULE: Link_support.c
  450. X ***************************************************************************
  451. X * Revision History:  Created Fri Jan 15 20:13:48 CST 1988
  452. X * $Log:    link_support.c,v $
  453. X * Revision 3.1  88/06/18  09:34:21  papowell
  454. X * Version 3.0- Distributed Sat Jun 18 1988
  455. X * 
  456. X * Revision 2.1  88/05/09  10:08:20  papowell
  457. X * PLP: Released Version
  458. X * 
  459. X * Revision 1.5  88/04/06  12:12:12  papowell
  460. X * Minor updates, changes in error message formats.
  461. X * Elimination of the AF_UNIX connections, use AF_INET only.
  462. X * Better error messages.
  463. X * 
  464. X * Revision 1.4  88/03/25  14:59:39  papowell
  465. X * Debugged Version:
  466. X * 1. Added the PLP control file first transfer
  467. X * 2. Checks for MX during file transfers
  468. X * 3. Found and fixed a mysterious bug involving the SYSLOG facilities;
  469. X *     apparently they open files and then assume that they will stay
  470. X *     open.
  471. X * 4. Made sure that stdin, stdout, stderr was available at all times.
  472. X * 
  473. X * Revision 1.3  88/03/12  10:03:50  papowell
  474. X * *** empty log message ***
  475. X * 
  476. X * Revision 1.2  88/03/11  19:28:26  papowell
  477. X * Minor Changes, Updates
  478. X * 
  479. X * Revision 1.1  88/03/01  11:08:29  papowell
  480. X * Initial revision
  481. X * 
  482. X * Support for the inter-machine communications
  483. X * Link_open(int retry)
  484. X *  opens a link to the remote host
  485. X * Link_close()
  486. X *  closes the link to the remote Printer
  487. X * Link_send( char *l)
  488. X *  sends a line to the remote host
  489. X * Link_line( int retry, char *l)
  490. X *  opens the link (with or without retry)
  491. X *  sends a line to the remote host
  492. X * Link_confirm()
  493. X *  gets a single character back, confirming the action
  494. X * Link_ack( c )
  495. X *  sends a single character back, confirming the action
  496. X * Link_copy( FILE *fp, count)
  497. X *  copies a file to the remote host;
  498. X *  if count bytes not transfered, an error is generated
  499. X * Link_get()
  500. X *  gets and prints all information  on stdout
  501. X * Link_port_num()
  502. X *    gets remote port number for connection
  503. X ***************************************************************************/
  504. X#ifndef lint
  505. static char id_str1[] =
  506. X    "$Header: link_support.c,v 3.1 88/06/18 09:34:21 papowell Exp $ PLP Copyright 1988 Patrick Powell";
  507. X#endif lint
  508. X
  509. X#include "lp.h"
  510. X
  511. static int Link_fd;            /* fd for the socket */
  512. X
  513. X/***************************************************************************
  514. X * Link_open(retry)
  515. X * 1. Set up an inet socket;  a socket has a local host/local port and
  516. X *    remote host/remote port address part.  The LPR software runs SUID
  517. X *    root,  and will attempt to open a privileged port (number less than
  518. X *    PRIV);  at the remote end this is checked to make sure that the
  519. X *    remote machine is running SUID root.  Primitive,  but it is adequate
  520. X *    in a trusting environment.
  521. X *
  522. X * (See Advanced 4.3 BSD IPC Tutorial for more information) The server on
  523. X * the remote machine will be listening on the port given by the entry in
  524. X * the /etc/service for the particular service desired.  If we are using
  525. X * the "real" version of lpd this will be the "Printer" service, the test
  526. X * version will use a "test" service.  The LPD daemon will open a socket
  527. X * and bind to the appropriate "port" number.  The
  528. X * getservbyname("printer","tcp"), is used to get the port information
  529. X * (sp->s_port), which is used in a bind call.
  530. X * 
  531. X * When we want to communicate with the lpd daemon on the remote machine,
  532. X * listening on that particular port, we call getseverbyname(...) to get
  533. X * the port number and protocol.  The remote host expects the local port
  534. X * to be in a range that is available only to a root UID process, i.e.-
  535. X * less than IPPORT_RESERVED.  When we open the local port, we get a local
  536. X * port in this range.  At the remote end, the port number is checked to
  537. X * ensure that it is in a valid range.  Since the reserved ports can only
  538. X * be accessed by UID 0 (root) processes, this would appear to prevent
  539. X * ordinary users from directly contacting the remote daemon.
  540. X *
  541. X ***************************************************************************/
  542. X/*
  543. X * getport()
  544. X *   gets a port,  in the correct range,  to the remote machine
  545. X *   This code comes from a description of the RLOGIN and LPD
  546. X *   materials
  547. X */
  548. static int
  549. getport()
  550. X{
  551. X    struct hostent *host;            /* host entry pointer */
  552. X    int port_num;                    /* port number to connect to */
  553. X    struct sockaddr_in sin;            /* inet socket address */
  554. X    int sock;                        /* socket */
  555. X
  556. X    /*
  557. X     * !!! Warning: zero out the sockaddr_in struct
  558. X     */
  559. X    bzero( (char *)&sin, sizeof( sin ));
  560. X    /*
  561. X     * Get the host address and port number to connect to.
  562. X     */
  563. X    if(Debug>4)log( XLOG_DEBUG, "getport: host %s", RM );
  564. X    host = gethostbyname(RM);
  565. X    if (host == NULL){
  566. X        logerr_die( XLOG_INFO,"getport: unknown host %s", RM);
  567. X    }
  568. X    /*
  569. X     * get the server name and protocol information from /etc/services
  570. X     */
  571. X    port_num = Link_port_num();
  572. X    /*
  573. X     * set up the address information
  574. X     */
  575. X    bzero((char *)&sin, sizeof(sin));
  576. X    bcopy(host->h_addr, (caddr_t)&sin.sin_addr, host->h_length);
  577. X    sin.sin_family = host->h_addrtype;
  578. X    sin.sin_port = port_num;
  579. X
  580. X    /*
  581. X     * Try connecting to the server.
  582. X     */
  583. X    if(Debug>3)log( XLOG_DEBUG, "trying connection to %s", RM );
  584. X    sock = reserveport(Maxportno,Minportno);
  585. X    if(sock < 0){
  586. X        return(-1);
  587. X    }
  588. X    if(connect(sock, (struct sockaddr *)&sin, sizeof(sin)) < 0){
  589. X        if(Debug>2)logerr( XLOG_DEBUG, "connect failed to %s", RM );
  590. X        (void) close(sock);
  591. X        return(-1);
  592. X    }
  593. X    return(sock);
  594. X}
  595. X
  596. X/*
  597. X * reserveport(int port_no, min_port_no)
  598. X * Reserve a port, starting at port_no, down to min_port_no.
  599. X * while port_no > min_port_no
  600. X *   try to grab the port;
  601. X *   if you can, then return socket
  602. X *   else return -1
  603. X * Returns: socket if successful, -1 if not
  604. X */
  605. static int
  606. reserveport(port_no, min_port_no)
  607. X    int port_no, min_port_no;
  608. X{
  609. X    struct sockaddr_in sin;
  610. X    int sock;
  611. X
  612. X    sock = socket(AF_INET, SOCK_STREAM, 0);
  613. X    if(sock < 0){
  614. X        logerr_die( XLOG_INFO, "reserveport socket call failed" );
  615. X    } else if( sock == 0 ){
  616. X        logerr_die( XLOG_INFO, "reserveport: socket returns 0" );
  617. X    }
  618. X    while( port_no >= min_port_no ){
  619. X        bzero( (char *)&sin, sizeof( sin ));
  620. X        sin.sin_family = AF_INET;
  621. X        sin.sin_addr.s_addr = 0;
  622. X        sin.sin_port = htons((u_short) port_no);
  623. X        if (bind(sock, (struct sockaddr *)&sin, sizeof(sin)) >= 0){
  624. X            if(Debug>4)log( XLOG_DEBUG, "reserveport got socket %d", port_no );
  625. X            return(sock);
  626. X        }
  627. X        if(Debug>4)logerr( XLOG_DEBUG,"reserveport bind failed on %d",port_no );
  628. X        if (errno != EADDRINUSE && errno != EADDRNOTAVAIL){
  629. X            logerr_die( XLOG_INFO, "reserveport: bind failed" );
  630. X        }
  631. X        --port_no;
  632. X    }
  633. X    (void)close(sock);
  634. X    return(-1);
  635. X}
  636. X
  637. Link_open(retry)
  638. X    int retry;
  639. X{
  640. X    unsigned int i = 1;
  641. X    int l;
  642. X
  643. X    if( Link_fd ){
  644. X        return( JSUCC );
  645. X    }
  646. X    while( Link_fd == 0 ){
  647. X        if(Debug>3)log( XLOG_DEBUG,"Link_open: retry %d, attempt %d",retry,i );
  648. X        l = getport();
  649. X        if( l < 0 ){
  650. X            if( retry == 0 ){
  651. X                if(Debug>3)log( XLOG_DEBUG,"Link_open: failed" );
  652. X                return( JFAIL );
  653. X            } else if( retry > 0 ){
  654. X                --retry;
  655. X            }
  656. X            sleep((unsigned)i);
  657. X            if( i < 512 ){
  658. X                i = i << 1;
  659. X            }
  660. X        } else if( l == 0 ){
  661. X            fatal( XLOG_INFO, "Link_open: cannot happen- fd 0" );
  662. X        } else {
  663. X            Link_fd = l;
  664. X        }
  665. X    }
  666. X    if(Debug>3)log( XLOG_DEBUG, "made connection to %s", RM );
  667. X    return( JSUCC );
  668. X}
  669. X
  670. X/***************************************************************************
  671. X * Link_close()
  672. X * 1. close the link
  673. X ***************************************************************************/
  674. void
  675. Link_close()
  676. X{
  677. X    if(Debug>4)log(XLOG_DEBUG,"Link_close: closing link (%d)", Link_fd);
  678. X    if( Link_fd ){
  679. X        (void)close( Link_fd );
  680. X    }
  681. X    Link_fd = 0;
  682. X}
  683. X
  684. X
  685. X/***************************************************************************
  686. X * Link_line( int retry; char *line )
  687. X * send a line to the remote end
  688. X * if retry != 0, blocks until connection made
  689. X ***************************************************************************/
  690. X
  691. int
  692. Link_line( retry, str )
  693. X    char *str;
  694. X{
  695. X    if( Link_open(retry) != JSUCC ){
  696. X        return( JFAIL );
  697. X    }
  698. X    return( Link_send( str ));
  699. X}
  700. X
  701. int
  702. Link_send( str )
  703. X    char *str;
  704. X{
  705. X    int i, l;        /* ACME Integers, Inc. */
  706. X
  707. X    l = strlen( str );
  708. X    if( Link_fd == 0 ){
  709. X        log(XLOG_INFO, "Link_send: link to %s not open", RM);
  710. X        return( JFAIL );
  711. X    }
  712. X    if( l != 0 && (i = write( Link_fd, str, l )) != l){
  713. X        if( i < 0 ){
  714. X            logerr( XLOG_INFO, "write error to remote site %s", RM);
  715. X        }
  716. X        Link_close();
  717. X        return( JFAIL );
  718. X    }
  719. X    if(Debug>4)log(XLOG_DEBUG,"Link_send: sent to %s- '%d'%s",RM,*str,str+1);
  720. X    return( JSUCC );
  721. X}
  722. X
  723. X/***************************************************************************
  724. X * Link_confirm()
  725. X *  gets a single character back, confirming the action
  726. X ***************************************************************************/
  727. Link_confirm()
  728. X{
  729. X    char buf[1];    /* buffer */
  730. X    int n;
  731. X
  732. X    if( Link_fd == 0 ){
  733. X        log( XLOG_INFO, "link to %s not open", RM);
  734. X        return( JFAIL );
  735. X    }
  736. X    if( (n = read( Link_fd, buf, 1 )) != 1 ){
  737. X        if( n == 0 ){
  738. X            log( XLOG_INFO, "Link_confirm: nothing from remote site %s", RM);
  739. X        } else {
  740. X            logerr( XLOG_INFO, "Link_confirm: error from remote site %s", RM);
  741. X        }
  742. X        Link_close();
  743. X        return( JFAIL );
  744. X    }
  745. X    if( buf[0] != 0 ){
  746. X        if(Debug>4)log(XLOG_DEBUG,"Link_confim: failed (%d) from %s",*buf,RM);
  747. X        Link_close();
  748. X        return( JFAIL );
  749. X    }
  750. X    if(Debug>4)log( XLOG_DEBUG, "successful confirm from %s", RM);
  751. X    return( JSUCC );
  752. X}
  753. X
  754. X/***************************************************************************
  755. X * Link_copy( FILE *fp; long count; char *name)
  756. X *  copies a file to the remote nost;
  757. X *  if count bytes not transfered, an error is generated
  758. X ***************************************************************************/
  759. Link_copy( fp, count, name )
  760. X    FILE *fp;
  761. X    long count;
  762. X    char *name;
  763. X{
  764. X    char buf[BUFSIZ];    /* buffer */
  765. X    int i, l;                /* ACME Integer, Inc. */
  766. X    long total;            /* total number of bytes */
  767. X
  768. X    if(Debug>4)log( XLOG_DEBUG, "Link_copy: %s- %d bytes to %s",name,count,RM);
  769. X    if( Link_fd == 0 ){
  770. X        log( XLOG_INFO, "Link_copy: Link_fd is not open");
  771. X        goto error;
  772. X    }
  773. X
  774. X    total = 0;
  775. X    while( (i = fread( buf, 1, sizeof(buf), fp )) > 0 ){
  776. X        total = total + i;
  777. X        if( total > count ){
  778. X            log(XLOG_DEBUG,
  779. X            "Link_copy: file '%s', length %d instead of %d bytes",
  780. X                name, total, count );
  781. X            goto error;
  782. X        }
  783. X        if( (l = write( Link_fd, buf, i )) != i ){
  784. X            if( l < 0 ){
  785. X            logerr(XLOG_INFO,"Link_copy: write error while sending '%s' to %s",
  786. X                name, RM);
  787. X            } else {
  788. X            logerr(XLOG_INFO,"Link_copy: partial write sending '%s' to %s",
  789. X                name, RM);
  790. X            }
  791. X            goto error;
  792. X        }
  793. X    }
  794. X    if( i < 0 ){
  795. X        logerr(XLOG_INFO,"Link_copy: file '%s' read error", name);
  796. X        goto error;
  797. X    } else if( total != count ){
  798. X        log(XLOG_DEBUG,
  799. X        "Link_copy: file '%s', copied %d instead of %d bytes to %s",
  800. X            name, total, count, RM);
  801. X        goto error;
  802. X    }
  803. X    if(Debug>4)log(XLOG_DEBUG,"Link_copy: file '%s' %d bytes to %s",
  804. X        name,count,RM);
  805. X    return( JSUCC );
  806. error:
  807. X    Link_close();
  808. X    return( JFAIL );
  809. X}
  810. X
  811. Link_ack( c )
  812. X    int c;
  813. X{
  814. X    char buf[1];
  815. X    int succ;
  816. X
  817. X    buf[0] = c;
  818. X    succ = JFAIL;
  819. X
  820. X    if( write( Link_fd, buf, 1 ) != 1 ){
  821. X        if(Debug>4)logerr(XLOG_DEBUG,"ack '%d' write error to %s",c,RM);
  822. X    } else {
  823. X        succ = JSUCC;
  824. X        if(Debug>4)log(XLOG_DEBUG,"ack '%d' sent to site %s",c,RM);
  825. X    }
  826. X    if( succ != JSUCC ){
  827. X        Link_close();
  828. X    }
  829. X    return( succ );
  830. X}
  831. X
  832. X/***************************************************************************
  833. X * Link_get()
  834. X * reads all information from the link, and prints on stdout
  835. X ***************************************************************************/
  836. Link_get()
  837. X{
  838. X    int i;                /* ACME Integers, Inc. */
  839. X    char buf[BUFSIZ];    /* buffer */
  840. X
  841. X    if( Link_fd == 0 ){
  842. X        fatal( XLOG_INFO, "Link_copy: Link_fd is not open");
  843. X    }
  844. X
  845. X    while( (i = read( Link_fd, buf, sizeof(buf)) ) > 0 ){
  846. X        (void)fwrite( buf, 1, i, stdout );
  847. X    }
  848. X}
  849. X
  850. X/***************************************************************************
  851. X * Link_port_num()
  852. X * - look up the service in the service directory using getservent
  853. X * - if the port number has been set, don't do it a second time.
  854. X * - Note that Setup_test will set the port number if necessary.
  855. X ***************************************************************************/
  856. X
  857. Link_port_num()
  858. X{
  859. X    static char *name = SERVERNAME;
  860. X    static char *prot = SERVERPROT;
  861. X    struct servent *sp;
  862. X    if( Lpr_port_num == 0 ){
  863. X        if( ( sp = getservbyname( name, prot )) == 0 ){
  864. X            logerr_die( XLOG_CRIT, "Get_port_nun: getservbyname(%s,%s) failed",
  865. X                name, prot );
  866. X        }
  867. X        Lpr_port_num = sp->s_port;
  868. X    }
  869. X    return( Lpr_port_num );
  870. X}
  871. END_OF_FILE
  872. if test 12422 -ne `wc -c <'src/link_support.c'`; then
  873.     echo shar: \"'src/link_support.c'\" unpacked with wrong size!
  874. fi
  875. # end of 'src/link_support.c'
  876. fi
  877. if test -f 'src/lpr.c' -a "${1}" != "-c" ; then 
  878.   echo shar: Will not clobber existing file \"'src/lpr.c'\"
  879. else
  880. echo shar: Extracting \"'src/lpr.c'\" \(10711 characters\)
  881. sed "s/^X//" >'src/lpr.c' <<'END_OF_FILE'
  882. X/***************************************************************************
  883. X * U. Minnesota LPD Software * Copyright 1987, 1988, Patrick Powell
  884. X ***************************************************************************
  885. X * MODULE: lpr.c
  886. X * lpr - off line print
  887. X ***************************************************************************
  888. X * Revision History: Created Mon Jan 25 14:04:26 CST 1988
  889. X * $Log:    lpr.c,v $
  890. X * Revision 3.2  88/06/24  17:56:01  papowell
  891. X * MODS for VAX 4.3BSD UNIX
  892. X * 
  893. X * Revision 3.1  88/06/18  09:34:46  papowell
  894. X * Version 3.0- Distributed Sat Jun 18 1988
  895. X * 
  896. X * Revision 2.1  88/05/09  10:09:00  papowell
  897. X * PLP: Released Version
  898. X * 
  899. X * Revision 1.6  88/04/27  18:02:45  papowell
  900. X * The SIGCHLD signal has an odd behaviour on some systems.  Modified so that
  901. X * it will not get set UNLESS processes are started;  also,  it is reset
  902. X * to SIG_DFL, not SIG_IGN.
  903. X * 
  904. X * Revision 1.5  88/04/15  13:06:09  papowell
  905. X * Std_environ() call added, to ensure that fd 0 (stdin), 1 (stdout), 2(stderr)
  906. X * have valid file descriptors;  if not open, then /dev/null is used.
  907. X * 
  908. X * Revision 1.4  88/04/06  12:13:28  papowell
  909. X * Minor updates, changes in error message formats.
  910. X * Elimination of the AF_UNIX connections, use AF_INET only.
  911. X * Better error messages.
  912. X * 
  913. X * Revision 1.3  88/03/25  15:00:16  papowell
  914. X * Debugged Version:
  915. X * 1. Added the PLP control file first transfer
  916. X * 2. Checks for MX during file transfers
  917. X * 3. Found and fixed a mysterious bug involving the SYSLOG facilities;
  918. X *     apparently they open files and then assume that they will stay
  919. X *     open.
  920. X * 4. Made sure that stdin, stdout, stderr was available at all times.
  921. X * 
  922. X * Revision 1.2  88/03/11  19:28:47  papowell
  923. X * Minor Changes, Updates
  924. X * 
  925. X * Revision 1.1  88/03/01  11:08:41  papowell
  926. X * Initial revision
  927. X * 
  928. X ***************************************************************************/
  929. X#ifndef lint
  930. static char id_str1[] =
  931. X    "$Header: lpr.c,v 3.2 88/06/24 17:56:01 papowell Exp $ PLP Copyright 1988 Patrick Powell";
  932. X#endif lint
  933. X#include "lpr.h"
  934. X
  935. X/***************************************************************************
  936. X * SYNOPSIS
  937. X *      lpr [ -PPrinter ] [ -#num ] [ -C class ] [ -J job ] [
  938. X *      -RremoteAccount ] [ -m[mailTo] ] [ -T title ] [-i[numcols]]
  939. X *      [ -1234 font ] [ -wnum ] [ -Zzoptions ] [ -Uuser ] [ -HHost
  940. X *      ] [ -Ffilter ] [ -bhrs ] [ -Dn ] [ -X ] [ filename ...  ]
  941. X * DESCRIPTION
  942. X *      Lpr uses a spooling server to print the named files when
  943. X *      facilities become available.  If no Names appear, the stan-
  944. X *      dard input is assumed.
  945. X *      -PPrinter  Output to the specified Printer
  946. X *      -F?  Filter or format specification
  947. X *      -p text to be printed using pr(1) to format the files.
  948. X *      -l (literal) text with control characters to be printed
  949. X *      -t output from troff(1)
  950. X *      -n output from DITROFF
  951. X *      -d output from tex(l) (DVI format from Stanford).
  952. X *      -g standard plot data as produced by the plot(3X) routines
  953. X *      -v a raster image for devices like the Benson Varian.
  954. X *      -c data produced by cifplot(l).
  955. X *      -f same as -Fr, FORTAN carriage control
  956. X *      -m[mailTo] Send mail upon completion
  957. X *      -s Use symbolic links.
  958. X *      -J jobname  Specify the job name to print on the burst page
  959. X *      -T title specify the title used by pr(1);
  960. X *      -wwidth  specify the page width for pr.
  961. X *      -C class or priority (A - Z)
  962. X *      -R remoteAccount
  963. X *      -#num number of copies of each file to be printed.
  964. X *      -i[numcols] Cause the output to be indented
  965. X *      -b The files are assumed to contain binary data
  966. X *      -Z extra options
  967. X *      -D[n] debug level
  968. X *      -X Use an Xperimental version of LPD
  969. X *      -Uuser Used by root process to specify a user
  970. X *      -HHost Used by root process to specify a Host
  971. X ****************************************************************************
  972. X * Implementation:
  973. X *     Each time lpr is invoked it creates a "job" entry in the appropriate
  974. X * spool directory.  Each job consists of a control file and zero or more
  975. X * data files.  The control file contains lines that specify the job
  976. X * parameters, such as job Name, etc., and the Names of the data files.
  977. X *      Control file format
  978. X *      First character in the line flags kind of entry, remainder of line is
  979. X *          the arguemnt.
  980. X *
  981. X *        C -- "class Name" on banner page
  982. X *        H -- "Host Name" of machine where lpr was done
  983. X *        I -- "indent" amount to indent output
  984. X *        J -- "job Name" on banner page
  985. X *        L -- "literal" user's Name to print on banner
  986. X *        M -- "mail" to user when done printing
  987. X *        N -- "Name" of file (used by lpq)
  988. X *        P -- "Person" user's login Name
  989. X *        R -- account id  for charging 
  990. X *        U -- "unlink" Name of file to remove after we print it
  991. X *        W -- "width" page width for PR
  992. X *        X -- "header" header title for PR
  993. X *        Z -- xtra options to filters 
  994. X *
  995. X *    Lower case letters are formats, and are together with the Name
  996. X *      of the file to print
  997. X *        f -- "file Name" Name of text file to print
  998. X *        l -- "file Name" text file with control chars
  999. X *        p -- "file Name" text file to print with pr(1)
  1000. X *        t -- "file Name" troff(1) file to print
  1001. X *        n -- "file Name" ditroff(1) file to print
  1002. X *        d -- "file Name" dvi file to print
  1003. X *        g -- "file Name" plot(1G) file to print
  1004. X *        v -- "file Name" plain raster file to print
  1005. X *        c -- "file Name" cifplot file to print
  1006. X ***************************************************************************/
  1007. X
  1008. X/***************************************************************************
  1009. X * main(int argc, char **argv)
  1010. X * 1. get the Host computer Name and user Name
  1011. X * 2. get the parameters and other information
  1012. X * 3. set up signals to handle abrupt termination.
  1013. X * 4. set up the control file for the job
  1014. X * 5. if we are spooling from stdin, copy stdin to a file.
  1015. X * 6. if we have -p option (use pr), run the input files through pr
  1016. X *    and save to a single file.
  1017. X * 7. create a job entry
  1018. X * 8. start the server
  1019. X ****************************************************************************/
  1020. X
  1021. extern int cleanup();
  1022. X
  1023. main(argc, argv)
  1024. X    int argc;
  1025. X    char **argv;
  1026. X{
  1027. X    int i;                        /* ACME Integers, Inc. */
  1028. X    struct passwd *pw_ent;        /* user entry in /etc/passwd */
  1029. X    int fd, job_size;    /* size of file and job */
  1030. X
  1031. X    /*
  1032. X     * set umask to avoid problems with user umask
  1033. X     */
  1034. X    (void)umask(0);
  1035. X    /*
  1036. X     * Set fd 0, 1, 2 to /dev/null if not open
  1037. X     */
  1038. X    Std_environ();
  1039. X#    ifdef XPERIMENT
  1040. X        Setup_test();
  1041. X#    endif XPERIMENT
  1042. X
  1043. X    /*
  1044. X     * set up the pathnames for information files
  1045. X     */
  1046. X    Tailor_names();
  1047. X    /*
  1048. X     * set up the From information
  1049. X     */
  1050. X    From = Host;
  1051. X    /*
  1052. X     * get user name
  1053. X     */
  1054. X    if( (pw_ent = getpwuid( getuid() )) == 0 ){
  1055. X        logerr_die( XLOG_INFO, "getpwuid failed on uid %d", getuid());
  1056. X    }
  1057. X    (void)strcpy( LOGNAME, pw_ent->pw_name );
  1058. X    Person = LOGNAME;
  1059. X    if( getuid() == 0 ){
  1060. X        /* we are being invoked by root */
  1061. X        Is_root = 1;
  1062. X    }
  1063. X    /*
  1064. X     * Get the home directory for the use
  1065. X     */
  1066. X    (void)Get_home();
  1067. X    /*
  1068. X     * setup parameters
  1069. X     */
  1070. X    Setup_parms(argc, argv);
  1071. X    /*
  1072. X     * set up chatty information for user
  1073. X     */
  1074. X    if( BNRNAME[0] == 0 ){
  1075. X        if( strcmp( LOGNAME, pw_ent->pw_name ) == 0 ){
  1076. X            (void)strncpy( BNRNAME, pw_ent->pw_gecos, MAXPARMLEN );
  1077. X        } else {
  1078. X            (void)strcpy( BNRNAME, LOGNAME );
  1079. X        }
  1080. X    }
  1081. X    /*
  1082. X     * set signals
  1083. X     */
  1084. X    (void)signal(SIGPIPE, SIG_IGN);
  1085. X    (void)signal(SIGHUP, cleanup);
  1086. X    (void)signal(SIGINT, cleanup);
  1087. X    (void)signal(SIGQUIT, cleanup);
  1088. X    (void)signal(SIGTERM, cleanup);
  1089. X    /**************************************************************************
  1090. X     * The following possibilities exist:
  1091. X     *                         Files              No Files
  1092. X     * p format,no 'f' PF      PR ->spool         input->PR -> spool
  1093. X     * p format, 'f' PF        PR->PF->spool      input->PR->PF->spool
  1094. X     * ? format, no PF         files->spool files input->spool
  1095. X     * ? format, PF            PF(files) -> file  input->spool
  1096. X     * 
  1097. X     * If we have a prefilter for a file format,  we have to run the files
  1098. X     * through the prefilter,  and spool the output of the prefilter.
  1099. X     * The prefilter will create a single output file which is printed
  1100. X     *
  1101. X     * If we have 'p' format,  we will create a printer process, and run
  1102. X     * its output into a temporary file in the spool directory.
  1103. X     * If there are no names specified, we copy the input to a temporary
  1104. X     * file in the spool directory.  The Read_stdin file is the name of the
  1105. X     * output file.  This is also used to hold the name of the output of
  1106. X     * the PR program.
  1107. X     *
  1108. X     * If we have a prefilter,  we place its output in the Read_filter
  1109. X     * file.
  1110. X     *************************************************************************/
  1111. X    if( Format == 'p' ){
  1112. X        /*
  1113. X         * run PR and put the output in a spool file
  1114. X         */
  1115. X        if(Debug>3)log(XLOG_DEBUG,"using PR" );
  1116. X        if( Run_pr() == 0 ){
  1117. X            Diemsg( "nothing to print" );
  1118. X        }
  1119. X        Format = 'f';
  1120. X    } else if( Parmcount == 0 ){
  1121. X        if(Debug>3)log(XLOG_DEBUG,"Copying stdin" );
  1122. X        if( Copy_stdin()  == 0 ){
  1123. X            Diemsg( "nothing to print" );
  1124. X        }
  1125. X    } else {
  1126. X        /*
  1127. X         * check to see that the input files are printable
  1128. X         */
  1129. X        job_size = 0;
  1130. X        for(i = 0; i < Parmcount; ++i ){
  1131. X            fd = Is_printable( Parms[i].str, &LO_statb );
  1132. X            if( fd < 0 ){
  1133. X                Parms[i].str = 0;
  1134. X            } else {
  1135. X                job_size = 1;
  1136. X            }
  1137. X            (void)close(fd);
  1138. X        }
  1139. X        if( job_size == 0 ){
  1140. X            Diemsg( "nothing to print" );
  1141. X        }
  1142. X    }
  1143. X    /*
  1144. X     * now we check for prefilter;
  1145. X     * if we have one, then we have to run all the files through it;
  1146. X     * we invoke the prefilter with the appropriate parameters.
  1147. X     * The output of the prefilter (on stdout) is spooled
  1148. X     */
  1149. X    if( Prefilter_name[Format - 'a'] ){
  1150. X        /* yes, we have prefilter */
  1151. X        if(Debug>3)log(XLOG_DEBUG,"Prefilter %c '%s'",Format,
  1152. X            Prefilter_name[Format - 'a'] );
  1153. X        if( Do_prefilter(Prefilter_name[Format - 'a'], Read_stdin) <= 0 ){
  1154. X            Diemsg( "nothing to print" );
  1155. X        }
  1156. X    }
  1157. X    /*
  1158. X     * we now either have to spool a single file, produced by the
  1159. X     * PR and/or Prefilters, or we have to spool all the input files
  1160. X     */
  1161. X    Make_job();
  1162. X    /*
  1163. X     * start up the server
  1164. X     */
  1165. X    (void)Startserver();
  1166. X    exit( 0 );
  1167. X}
  1168. X/***************************************************************************
  1169. X * cleanup()
  1170. X * remove the temp files
  1171. X ***************************************************************************/
  1172. X
  1173. cleanup()
  1174. X{
  1175. X    (void)sigblock(sigmask(SIGCHLD)|sigmask(SIGHUP)
  1176. X        |sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGTERM));
  1177. X    if( geteuid() && geteuid() != getuid() ){
  1178. X        /*
  1179. X         * whoops, we must have been caught as user
  1180. X         * try and force to EUID root
  1181. X         */
  1182. X        if( setreuid( geteuid(), 0 ) < 0 ){
  1183. X            logerr( XLOG_INFO, "cleanup: setreuid( %d, %d) failed",
  1184. X                geteuid(), 0 );
  1185. X            exit(1);
  1186. X        }
  1187. X    }
  1188. X    if( geteuid() == 0 && setreuid( -1, Daemon_uid ) < 0 ){
  1189. X        logerr( XLOG_INFO, "cleanup: setreuid( %d, %d) failed",
  1190. X            -1, Daemon_uid );
  1191. X            exit(1);
  1192. X    }
  1193. X    Remove_temp();
  1194. X    exit( 1 );
  1195. X}
  1196. END_OF_FILE
  1197. if test 10711 -ne `wc -c <'src/lpr.c'`; then
  1198.     echo shar: \"'src/lpr.c'\" unpacked with wrong size!
  1199. fi
  1200. # end of 'src/lpr.c'
  1201. fi
  1202. if test -f 'src/lpr_filters.c' -a "${1}" != "-c" ; then 
  1203.   echo shar: Will not clobber existing file \"'src/lpr_filters.c'\"
  1204. else
  1205. echo shar: Extracting \"'src/lpr_filters.c'\" \(11355 characters\)
  1206. sed "s/^X//" >'src/lpr_filters.c' <<'END_OF_FILE'
  1207. X/***************************************************************************
  1208. X * U. Minnesota LPD Software * Copyright 1987, 1988, Patrick Powell
  1209. X ***************************************************************************
  1210. X * MODULE: lpr_filters.c
  1211. X * filter programs for LPR
  1212. X * Supports the reading and enqueuing of input
  1213. X ***************************************************************************
  1214. X * Revision History: Created Sat Jan 30 08:06:50 CST 1988
  1215. X * $Log:    lpr_filters.c,v $
  1216. X * Revision 3.1  88/06/18  09:34:53  papowell
  1217. X * Version 3.0- Distributed Sat Jun 18 1988
  1218. X * 
  1219. X * Revision 2.1  88/05/09  10:09:11  papowell
  1220. X * PLP: Released Version
  1221. X * 
  1222. X * Revision 1.3  88/03/25  15:00:27  papowell
  1223. X * Debugged Version:
  1224. X * 1. Added the PLP control file first transfer
  1225. X * 2. Checks for MX during file transfers
  1226. X * 3. Found and fixed a mysterious bug involving the SYSLOG facilities;
  1227. X *     apparently they open files and then assume that they will stay
  1228. X *     open.
  1229. X * 4. Made sure that stdin, stdout, stderr was available at all times.
  1230. X * 
  1231. X * Revision 1.2  88/03/11  19:28:36  papowell
  1232. X * Minor Changes, Updates
  1233. X * 
  1234. X * Revision 1.1  88/03/01  11:08:45  papowell
  1235. X * Initial revision
  1236. X * 
  1237. X ***************************************************************************/
  1238. X#ifndef lint
  1239. static char id_str1[] =
  1240. X    "$Header: lpr_filters.c,v 3.1 88/06/18 09:34:53 papowell Exp $ PLP Copyright 1988 Patrick Powell";
  1241. X#endif lint
  1242. X#include "lpr.h"
  1243. X
  1244. X/***************************************************************************
  1245. X * Run_pr()
  1246. X *   Copies input the PR program; temp file name left in Read_stdin
  1247. X *   Returns: 0 if nothing, 1 otherwise
  1248. X * Copy_stdin()
  1249. X *   Copies input to a temporary file; temp file name left in Read_stdin
  1250. X *   Returns: 0 if nothing, 1 otherwise
  1251. X * char *Copy_file( int infile, char *name ) 
  1252. X *    copies file to temp file, returns name of temp file
  1253. X * int Open_SD(char *s) Open the file in the spool directory
  1254. X ***************************************************************************/
  1255. X
  1256. X/***************************************************************************
  1257. X * Run_pr()
  1258. X * 1. Gets the name of a temporary file for the output
  1259. X * 2. Sets up the PR command
  1260. X * 3. Forks a process
  1261. X * 4. Arranges the process output goes to the output file
  1262. X * 5. Waits for PR to complete
  1263. X ***************************************************************************/
  1264. char * estr3();        /* copies 3 strings to end */
  1265. X
  1266. Run_pr()
  1267. X{
  1268. X    int fd;                /* Data file */
  1269. X    char cmdbuf[BUFSIZ];    /* build up the command here */
  1270. X    char buf[BUFSIZ];        /* local buf up the command here */
  1271. X    char *bp;                /*  bp points to cmdbuf */
  1272. X    char *ep;                /*  ep is limit */
  1273. X    int pid;                /* pid of pr process */
  1274. X    union wait status;        /* the status.w_status is the integer value */
  1275. X    int i;                    /* ACME Integer, Inc. */
  1276. X    struct stat statb;        /* for stating the output file */
  1277. X
  1278. X    /*
  1279. X     * get name of the data file
  1280. X     */
  1281. X    Read_stdin = Get_tmp_data();
  1282. X    fd = Open_SD( Read_stdin );
  1283. X    /*
  1284. X     * set up the printer name
  1285. X     */
  1286. X    if( PR == 0 || *PR == 0 ){
  1287. X        Diemsg( "there is no pr program specified for -p format");
  1288. X    }
  1289. X    /* set up the command */
  1290. X    ep = cmdbuf + sizeof(cmdbuf);
  1291. X    bp = estr3( cmdbuf, PR,(char *)0,(char *)0, ep );
  1292. X    /*
  1293. X     * set the width, length, and title flags
  1294. X     */
  1295. X
  1296. X    if( PWIDTH[0] ){
  1297. X        bp = estr3( bp, " -w", PWIDTH, " ", ep );
  1298. X    } else if( PW ){
  1299. X        (void)sprintf( buf, " -w%d ", PW );
  1300. X        bp = estrcp( bp, buf, ep );
  1301. X    }
  1302. X    if( PL ){
  1303. X        (void)sprintf( buf, "-l%d ", PL );
  1304. X        bp = estrcp( bp, buf, ep );
  1305. X    }
  1306. X    if( PRTITLE[0] ){
  1307. X        bp = estr3( bp, "-h '", PRTITLE, "' ", ep );
  1308. X    } else if( JOBNAME[0] ){
  1309. X        bp = estr3( bp, "-h '", JOBNAME, "' ", ep );
  1310. X    } else if( Parmcount == 0 ){
  1311. X        bp = estr3( bp, "-h '", "(stdin)", "' ", ep );
  1312. X    }
  1313. X    /*
  1314. X     * Put the file names in the list
  1315. X     */
  1316. X    for( i = 0; i < Parmcount; ++i ){
  1317. X        bp = estr3( bp, Parms[i].str, " ", (char *)0, ep );
  1318. X    }
  1319. X    if( bp == 0 ){
  1320. X        Diemsg( "pr command is too long: %s", cmdbuf);
  1321. X    }
  1322. X    if(Debug>2)log(XLOG_DEBUG, "pr command is '%s'", cmdbuf);
  1323. X    /*
  1324. X     * start up the pr process
  1325. X     */
  1326. X    if( (pid = fork()) < 0 ){
  1327. X        logerr_die(XLOG_INFO,"Run_pr: fork failed");
  1328. X    } else if( pid == 0 ){
  1329. X        if( dup2(fd,1) < 0 ){
  1330. X            logerr_die(XLOG_INFO,"Run_pr: dup2 failed" );
  1331. X        }
  1332. X        if( setreuid( getuid(), getuid() )< 0 ){
  1333. X            logerr_die(XLOG_INFO,"setreuid failed" );
  1334. X        }
  1335. X        mexecv( cmdbuf );
  1336. X        exit(1);
  1337. X    }
  1338. X    /* wait for printer */
  1339. X    while ((i = wait(&status)) > 0 && i != pid);
  1340. X    if( i < 0 || status.w_status ){
  1341. X        logerr_die(XLOG_INFO,"pr failed (%s)", Decode_status(&status) );
  1342. X    }
  1343. X    if(Debug>3)log(XLOG_DEBUG,"pr done successfully");
  1344. X    if( fstat( fd, &statb ) <0 ){
  1345. X        logerr_die(XLOG_INFO, "Run_pr: cannot stat output file %s", Read_stdin);
  1346. X    }
  1347. X    if(Debug>3)log(XLOG_DEBUG,"Run_pr: %s is %d",Read_stdin,statb.st_size);
  1348. X    (void)close(fd);
  1349. X    return( statb.st_size != 0 );
  1350. X}
  1351. X
  1352. static char *
  1353. estr3( s, s1, s2, s3, e )
  1354. X    char *s, *s1, *s2, *s3, *e;
  1355. X{
  1356. X    if( s1 ) s = estrcp( s, s1, e );
  1357. X    if( s2 ) s = estrcp( s, s2, e );
  1358. X    if( s3 ) s = estrcp( s, s3, e );
  1359. X    return( s );
  1360. X}
  1361. X
  1362. X/***************************************************************************
  1363. X * int Open_SD(char *s)
  1364. X * Open the name of the file in the spool directory
  1365. X * 1. Prepend the SD name
  1366. X * 2. Create the file with the desired perms
  1367. X * Returns: fd if successful; dies otherwise
  1368. X ***************************************************************************/
  1369. X
  1370. Open_SD( s )
  1371. X    char *s;
  1372. X{
  1373. X    char buf[BUFSIZ];
  1374. X    int fd;
  1375. X
  1376. X    (void)sprintf(buf, "%s/%s", SD, s);
  1377. X    fd = Exlockcf( buf );
  1378. X    if( fd < 0 ){
  1379. X        logerr_die( XLOG_INFO, "Open_SD: could not open and lock %s", buf );
  1380. X    }
  1381. X    if(Debug>3)log(XLOG_DEBUG,"Open_SD: file %s, fd %d", buf, fd );
  1382. X    return( fd );
  1383. X}
  1384. X
  1385. X/***************************************************************************
  1386. X * Copy_stdin()
  1387. X * 1. Gets the name of a temporary file for the output
  1388. X * 2. Copies stdin to the file
  1389. X * 3. Returns 0 if empty file, 1 otherwise
  1390. X ***************************************************************************/
  1391. X
  1392. Copy_stdin()
  1393. X{
  1394. X    int fd;                    /* Data file */
  1395. X    char buf[BUFSIZ];        /* local buf up the command here */
  1396. X    int n, i;                /* bytes read */
  1397. X    int count;                /* number of bytes */
  1398. X    long blocks;                /* number of blocks */
  1399. X
  1400. X    /*
  1401. X     * get name of the data file
  1402. X     */
  1403. X    Read_stdin = Get_tmp_data();
  1404. X    fd = Open_SD( Read_stdin );
  1405. X
  1406. X    count = 0;
  1407. X    blocks = 0;
  1408. X    while( (n = fread( buf, 1, sizeof(buf), stdin )) > 0 ){
  1409. X        count += n;    /* update count */
  1410. X        while( count >= 1024 ){
  1411. X            count -= 1024;
  1412. X            ++blocks;
  1413. X        }
  1414. X        if( MX && blocks > MX ){
  1415. X            Diemsg( "input from stdin exceeds maximum file size limits" );
  1416. X        }
  1417. X        i = write( fd, buf, n );
  1418. X        if( i != n ){
  1419. X            logerr_die(XLOG_INFO,"Copy_stdin: cannot write %s",Read_stdin);
  1420. X        }
  1421. X    }
  1422. X    if( ferror( stdin ) ){
  1423. X        Diemsg( "error reading from stdin" );
  1424. X    }
  1425. X    (void)close(fd);
  1426. X    if( count ){
  1427. X        ++blocks;
  1428. X    }
  1429. X    if(Debug>3)log(XLOG_DEBUG,"Copy_stdin: %s is %d blocks", Read_stdin,blocks);
  1430. X    return( blocks != 0 );
  1431. X}
  1432. X/***************************************************************************
  1433. X * char *Copy_file( int *in_fp, char *in_file )
  1434. X * 1. Gets the name of a temporary file for the output
  1435. X * 2. Copies file to the temporary file
  1436. X * Returns: temporary file name
  1437. X ***************************************************************************/
  1438. X
  1439. char *
  1440. Copy_file( in_fd, in_file, statb )
  1441. X    int in_fd;
  1442. X    char *in_file;
  1443. X    struct stat *statb;
  1444. X{
  1445. X    int out_fd;                /* Data file */
  1446. X    char buf[BUFSIZ];        /* local buf for IO */
  1447. X    int n, i;                /* bytes read */
  1448. X    int count;                /* number of bytes */
  1449. X    long blocks;            /* number of blocks */
  1450. X    char *fname;            /* file name */
  1451. X
  1452. X    /*
  1453. X     * get name of the data file
  1454. X     */
  1455. X    fname = Get_tmp_data();
  1456. X    out_fd = Open_SD( fname );
  1457. X
  1458. X    count = 0;
  1459. X    blocks = 0;
  1460. X    while( (n = read( in_fd, buf, sizeof(buf))) > 0 ){
  1461. X        count += n;    /* update count */
  1462. X        while( count >= 1024 ){
  1463. X            count -= 1024;
  1464. X            ++blocks;
  1465. X        }
  1466. X        if( MX && blocks > MX ){
  1467. X            Diemsg( "file %s too large",in_file);
  1468. X        }
  1469. X        i = write( out_fd, buf, n );
  1470. X        if( i != n ){
  1471. X            logerr_die(XLOG_INFO,"Copy_file: cannot write to file %s",in_file);
  1472. X        }
  1473. X    }
  1474. X    if( n < 0 ){
  1475. X        logerr_die( XLOG_INFO,"Copy_file: error reading from %s", in_file );
  1476. X    }
  1477. X    if( fstat( out_fd, statb ) < 0 ){
  1478. X        logerr_die( XLOG_INFO,"Copy_file: cannot stat %s", fname);
  1479. X    }
  1480. X    (void)close( out_fd );
  1481. X    return( fname );
  1482. X}
  1483. X/***************************************************************************
  1484. X * Do_prefilter( char *cmd, char *file )
  1485. X *
  1486. X *    Prefilter handler
  1487. X *  1. Sets up a prefilter command.
  1488. X *  filtername arguments \   <- from filtername
  1489. X *      -PPrinter -wwidth -llength -xwidth -ylength [-c] [-iindent] \
  1490. X *      [-Zoptions] [-Cclass] [-Jjob] [-Raccntname] -nlogin -hHost
  1491. X *      -Fformat [file]
  1492. X *     Note: the filter parameter is of the form "filter,X", where
  1493. X *     output format is specified.  If there is no specified format,
  1494. X *     'f' will be used.
  1495. X *  2. Gets a temporary file for output
  1496. X *  3. If file is explicitly named,  uses that for input instead of
  1497. X *     parameter files.
  1498. X *  4. Forks and runs the command.
  1499. X *  5. Filter must return 0 for successful status, otherwise we abort
  1500. X ***************************************************************************/
  1501. X
  1502. Do_prefilter( cmd, file )
  1503. X    char *cmd;
  1504. X    char *file;
  1505. X{
  1506. X    char cmdbuf[BUFSIZ];    /* build up the command here */
  1507. X    union wait status;        /* the status.w_status is the integer value */
  1508. X    char *cp, *ep;            /* ACME Pointers, Inc. */
  1509. X    int i, l, pid;            /* ACME Integers, Inc. */
  1510. X    int new_format = 'f';    /* new format */
  1511. X    int fd;                    /* the output file */
  1512. X    struct stat statb;        /* for stating the output file */
  1513. X    
  1514. X    /*
  1515. X     * get the output format
  1516. X     */
  1517. X    (void)strcpy(cmdbuf, cmd);
  1518. X    l = strlen( cmdbuf );
  1519. X    if( l > 2 ){
  1520. X        if( cmdbuf[l-2] == ',' ){
  1521. X            new_format = cmdbuf[l-1];
  1522. X            cmdbuf[l-2] = 0;
  1523. X        }
  1524. X    }
  1525. X    if( !isascii(new_format) || !islower(new_format)){
  1526. X        fatal(XLOG_INFO, "bad prefilter new format, %s", cmd);
  1527. X    }
  1528. X    /*
  1529. X     * set up the basic filter command 
  1530. X     */
  1531. X    AF = 0;
  1532. X    cp = Setup_filter( Format, cmdbuf );
  1533. X    Format = new_format;
  1534. X    ep = cmdbuf+sizeof(cmdbuf);
  1535. X    /*
  1536. X     * copy command to buffer
  1537. X     */
  1538. X    cp = estrcp( cmdbuf, cp, ep );
  1539. X
  1540. X    /*
  1541. X     * add the file names
  1542. X     */
  1543. X    if( file ){
  1544. X        /*
  1545. X         * we have an explicitly named file
  1546. X         */
  1547. X        cp = estrcp( cp, " ", ep );
  1548. X        cp = estrcp( cp, file, ep );
  1549. X    } else {
  1550. X        for( l = 0; l < Parmcount; ++l ){
  1551. X            cp = estrcp( cp, " ", ep );
  1552. X            cp = estrcp( cp, Parms[l].str, ep );
  1553. X        }
  1554. X    }
  1555. X    if( cp == 0 ){
  1556. X        fatal( XLOG_INFO, "Do_prefilter: command too long: %s", cmd);
  1557. X    }
  1558. X    if(Debug>3)log(XLOG_DEBUG, "Do_prefilter: command '%s'", cmdbuf);
  1559. X    /*
  1560. X     * get the output file name
  1561. X     */
  1562. X    Filter_out = Get_tmp_data();
  1563. X    fd = Open_SD( Filter_out );
  1564. X
  1565. X    /*
  1566. X     * start the prefilter up and wait for output
  1567. X     */
  1568. X    if( (pid = fork()) < 0 ){
  1569. X        logerr_die(XLOG_INFO,"Do_prefilter: fork failed");
  1570. X    } else if( pid == 0 ){
  1571. X        if( dup2(fd,1) < 0 ){
  1572. X            logerr_die(XLOG_INFO,"Do_prefilter: dup2 failed" );
  1573. X        }
  1574. X        if( setreuid( getuid(), Daemon_uid ) < 0 ){
  1575. X            logerr_die(XLOG_INFO,"Do_prefilter: setreuid failed" );
  1576. X        }
  1577. X        mexecv( cmdbuf );
  1578. X        logerr_die(XLOG_INFO,"Do_prefilter: execv failed");
  1579. X    }
  1580. X    /*
  1581. X     * wait for prefilter
  1582. X     */
  1583. X    while ((i = wait(&status)) > 0 && i != pid) ;
  1584. X    if( i < 0 || status.w_status ){
  1585. X        logerr_die(XLOG_INFO,"Do_prefilter: prefilter %d failed (%s)", i,
  1586. X            Decode_status( &status ) );
  1587. X    }
  1588. X    if(Debug>3)log(XLOG_DEBUG,"Do_prefilter: prefilter successful");
  1589. X    if( fstat( fd, &statb ) <0 ){
  1590. X        logerr_die(XLOG_INFO, "Do_prefilter: cannot stat output file %s",
  1591. X            Filter_out);
  1592. X    }
  1593. X    if(Debug>3)log(XLOG_DEBUG,"Do_prefilter: %s is %ld",
  1594. X            Filter_out,statb.st_size);
  1595. X    (void)close(fd);
  1596. X    return( statb.st_size != 0 );
  1597. X}
  1598. END_OF_FILE
  1599. if test 11355 -ne `wc -c <'src/lpr_filters.c'`; then
  1600.     echo shar: \"'src/lpr_filters.c'\" unpacked with wrong size!
  1601. fi
  1602. # end of 'src/lpr_filters.c'
  1603. fi
  1604. echo shar: End of archive 8 \(of 16\).
  1605. cp /dev/null ark8isdone
  1606. MISSING=""
  1607. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ; do
  1608.     if test ! -f ark${I}isdone ; then
  1609.     MISSING="${MISSING} ${I}"
  1610.     fi
  1611. done
  1612. if test "${MISSING}" = "" ; then
  1613.     echo You have unpacked all 16 archives.
  1614.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1615. else
  1616.     echo You still need to unpack the following archives:
  1617.     echo "        " ${MISSING}
  1618. fi
  1619. ##  End of shell archive.
  1620. exit 0
  1621.  
  1622.