home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #27 / NN_1992_27.iso / spool / alt / sources / 2544 < prev    next >
Encoding:
Text File  |  1992-11-17  |  39.8 KB  |  1,566 lines

  1. Newsgroups: alt.sources
  2. Path: sparky!uunet!charon.amdahl.com!pacbell.com!sgiblab!zaphod.mps.ohio-state.edu!wupost!gumby!yale!yale.edu!ira.uka.de!math.fu-berlin.de!news.netmbx.de!Germany.EU.net!logixwi!jpm
  3. From: jpm@Logix.DE (Jan-Piet Mens)
  4. Subject: SLPD-1.0PL2 - lpr/lpd interface to SYSV LP
  5. Organization: Logix GmbH, Wiesbaden, Germany
  6. Date: Tue, 17 Nov 1992 20:15:28 GMT
  7. Message-ID: <1992Nov17.201528.17134@Logix.DE>
  8. Lines: 1556
  9.  
  10.  
  11. Submitted-by: jpm@Logix.DE
  12. Archive-name: SLPD/part01
  13.  
  14. ---- Cut Here and feed the following to sh ----
  15. #!/bin/sh
  16. # This is SLPD, a shell archive (produced by shar 3.49)
  17. # To extract the files from this archive, save it to a file, remove
  18. # everything above the "!/bin/sh" line above, and type "sh file_name".
  19. #
  20. # made 11/17/1992 20:14 UTC by jpm@Logix.DE
  21. # Source directory /home/jpm/src/slpd
  22. #
  23. # existing files will NOT be overwritten unless -c is specified
  24. #
  25. # This shar contains:
  26. # length  mode       name
  27. # ------ ---------- ------------------------------------------
  28. #   2862 -rw-r--r-- README
  29. #    897 -rw-r--r-- Makefile
  30. #   2816 -rw-r--r-- slpd.8
  31. #    482 -rw-r--r-- TODO
  32. #   6868 -rw-r--r-- slpd.c
  33. #   5233 -rw-r--r-- util.c
  34. #   3967 -rw-r--r-- print.c
  35. #   4021 -rw-r--r-- command.c
  36. #    609 -rw-r--r-- lock.c
  37. #    401 -rw-r--r-- copyright.h
  38. #   5310 -rw-r--r-- config.h
  39. #     21 -rw-r--r-- patchlevel.h
  40. #
  41. # ============= README ==============
  42. if test -f 'README' -a X"$1" != X"-c"; then
  43.     echo 'x - skipping README (File already exists)'
  44. else
  45. echo 'x - extracting README (Text)'
  46. sed 's/^X//' << 'SHAR_EOF' > 'README' &&
  47. This SLPD 1.0 PL02
  48. ==================
  49. X
  50. SLPD is an lpd daemon designed for SYSV. It translates requests initiated
  51. from LPR clients to the System V LP-spooler equivalent (if possible). 
  52. Having seen that so many in the USENET community are looking for something
  53. like this, and having the need ourselves, we decided to try an implementation.
  54. X
  55. SLPD only supports a limited amount of requests from an LPR client at the
  56. moment. I am very willing to increase the functionality of SLPD if I get
  57. appropriate requests from you. The following are implemented so far:
  58. X
  59. X    Client (BSD-LPR)            Server (SysV-LP)
  60. X    lpr filename            ->    lp -s -c filename
  61. X    lpr -P<printer> filename    ->    lp -d<printer> -s -c filename
  62. X    lpr -l filename            ->    lp -s -c filename
  63. X    lpr -p filename            ->    pr -h filename | lp ....
  64. X    lpr -p -T title filename    ->    pr -h title filename | lp ...
  65. X
  66. LPRM and LPQ are not supported, because I have not quite yet figured out
  67. what the protocol is. Help anyone ?
  68. X
  69. Please send comments and requests for additions to me. My name is
  70. Jan-Piet Mens, and my Email address is jpm@Logix.DE
  71. X
  72. X    -JP
  73. X
  74. X
  75. Here is how to configure SLPD:
  76. X
  77. - Edit config.h and follow instructions on setting pathnames etc.
  78. - Edit command.c and make sure USG is defined 
  79. - Edit the Makefile, and set your preferred compiler and CFLAGS.
  80. X  [ For testing, you can define -DDEBUG in DEFS. This will produce
  81. X    some crypting output, showing what is actually happening ]
  82. X  Set BINDIR to the directory where the executable should be installed.
  83. - Do a ``make''
  84. - Run ``./slpd -c'' to check the configuration. SLPD will show you
  85. X  how it was configured!
  86. - Insert a line like the following in your /etc/services file.
  87. X
  88. X    printer    515/tcp    spooler      # line printer spooler
  89. X
  90. - Create the spool directory. The name of the spool directory is in
  91. X  config.h [SPOOLDIR]
  92. X
  93. - Do an ``su'' and become root.
  94. - Execute ./spld -d and test your first spool from a client.
  95. - If everything works, do a ``make install''
  96. - Format the man-page. [Please install it manually...]
  97. - Good luck :-)
  98. X
  99. History
  100. =======
  101. X    This was built on SCO 3.2.4 with both CC and GCC-2.2.2. [Both work]
  102. X    I built it because we have several clients on the net who have a
  103. X    BSD lpr interface, and I don't have a "real" lpd on the SCO machine.
  104. X    I believe that SCO have released a LPD server in the mean time, but
  105. X    we can't upgrade at the moment.
  106. X
  107. X
  108. X
  109. The files command.[c3] in this directory are from:
  110. |
  111. |    Mod.sources:  Volume 3, Issue 27
  112. |    Submitted by: mirror!rs (Rich Salz)
  113. |
  114. |    This shar package provides the code and manpage for "command",
  115. |    a suggested replacement for the "system" routine.  It will avoid
  116. |    calling a shell if possible, as it can handle >, <, |, and >>
  117. |    meta-characters internally.
  118. |
  119. |    Enjoy,
  120. |        /r$
  121. |    Rich $alz {mit-eddie, ihnp4!inmet, wjh12, cca, datacube} !mirror!rs
  122. |    Mirror Systems    2067 Massachusetts Ave.
  123. |    617-661-0777    Cambridge, MA, 02140
  124. SHAR_EOF
  125. chmod 0644 README ||
  126. echo 'restore of README failed'
  127. Wc_c="`wc -c < 'README'`"
  128. test 2862 -eq "$Wc_c" ||
  129.     echo 'README: original size 2862, current size' "$Wc_c"
  130. fi
  131. # ============= Makefile ==============
  132. if test -f 'Makefile' -a X"$1" != X"-c"; then
  133.     echo 'x - skipping Makefile (File already exists)'
  134. else
  135. echo 'x - extracting Makefile (Text)'
  136. sed 's/^X//' << 'SHAR_EOF' > 'Makefile' &&
  137. # Makefile for SLPD
  138. # by Jan-Piet Mens - <jpm@Logix.DE>
  139. X
  140. # SLPD will be installed in this directory
  141. BINDIR=/etc
  142. X
  143. X
  144. CC=cc
  145. #CC=gcc
  146. X
  147. # Add -DDEBUG to DEFS if you want cryptic debugging output.
  148. DEFS= -DDEBUG
  149. CFLAGS=-O $(DEFS)
  150. X
  151. X
  152. TARGET    = slpd
  153. OBJS    = slpd.o util.o print.o command.o lock.o
  154. SRCS    = slpd.c util.c print.c command.c lock.c
  155. H    = copyright.h config.h patchlevel.h
  156. X
  157. all: $(TARGET)
  158. X
  159. $(TARGET): $(OBJS)
  160. X    $(CC) $(CFLAGS) -o $@ $(OBJS) -lsocket
  161. install: $(TARGET)
  162. X    strip $(TARGET)
  163. X    [ -x /usr/bin/mcs ] && /usr/bin/mcs -d $(TARGET)
  164. X    [ -d $(BINDIR) ] || mkdir $(BINDIR)
  165. X    cp $(TARGET) $(BINDIR)/$(TARGET)
  166. X    chmod 111 $(BINDIR)/$(TARGET)
  167. X    chown root $(BINDIR)/$(TARGET)
  168. X
  169. $(OBJS): $(H)
  170. X
  171. clean:
  172. X    rm -f *.o core a.out
  173. clobber: clean
  174. X    rm -f $(TARGET)
  175. X
  176. SHARFILES=README Makefile slpd.8 TODO
  177. X
  178. dist: $(SRCS) $(SHARFILES) $(H)
  179. X    shar49 -n SLPD -a -s 'jpm@Logix.DE' -o Part -l 50 -c \
  180. X        $(SHARFILES) $(SRCS) $(H)
  181. X
  182. SHAR_EOF
  183. chmod 0644 Makefile ||
  184. echo 'restore of Makefile failed'
  185. Wc_c="`wc -c < 'Makefile'`"
  186. test 897 -eq "$Wc_c" ||
  187.     echo 'Makefile: original size 897, current size' "$Wc_c"
  188. fi
  189. # ============= slpd.8 ==============
  190. if test -f 'slpd.8' -a X"$1" != X"-c"; then
  191.     echo 'x - skipping slpd.8 (File already exists)'
  192. else
  193. echo 'x - extracting slpd.8 (Text)'
  194. sed 's/^X//' << 'SHAR_EOF' > 'slpd.8' &&
  195. .TH SLPD 8 "Logix GmbH"
  196. .SH NAME
  197. slpd \- pseudo line printer daemon
  198. .SH SYNOPSIS
  199. .B slpd
  200. [
  201. .B -c
  202. ] [
  203. .B -v
  204. ]
  205. .SH DESCRIPTION
  206. .I slpd
  207. is a line printer daemon and is normally invoked at boot time from the
  208. .IR rc (8)
  209. files. It is designed as an interface between the
  210. .B BSD
  211. .I lpr
  212. and the
  213. .B "System V"
  214. .I lp
  215. spoolers.
  216. .PP
  217. Upon startup,
  218. .I slpd
  219. uses the system calls
  220. .IR listen (2)
  221. and
  222. .IR accept (2)
  223. to receive requests to print files from remote clients, who have submitted
  224. print jobs via the
  225. .I lpr
  226. interface. In each case
  227. .I slpd
  228. forks off a child to handle the request so the parent can continue to
  229. listen for further requests. The Internet port-number used to rendezvous
  230. with other processes is obtained with
  231. .IR getservbyname (3).
  232. .PP
  233. Access control is provided as follows: all requests must originate from
  234. systems listed in the
  235. .B "host authorization"
  236. file.
  237. The
  238. .I lock
  239. file in the spool directory is used to prevent mulitple instances of
  240. .I slpd
  241. from competing against eachother.
  242. .SH OPTIONS
  243. .I slpd
  244. recognizes the following options:
  245. .IP "\fB-v\fR 1i
  246. show version string and release number.
  247. .IP "\fB-c\fR 1i
  248. Show how
  249. .I slpd
  250. was originally configured. The output could look like
  251. .sp
  252. .nf
  253. .in 1i
  254. X    SPOOLDIR          = /usr/spool/slpd
  255. X    LP_CMD            = /usr/bin/lp
  256. X    LP_LISTNAMES      = |lpstat -p | awk '{if ($1 == "printer") {print $2}}'
  257. X    MAXPRINTERS       = 20
  258. X    HOSTAUTHFILE      = /etc/slpd-hosts
  259. X    Remove Spool files= TRUE
  260. .in
  261. .fi
  262. .sp
  263. .SH FILES
  264. .IP "\fB/etc/services\fR" 1.5i
  265. This file contains the port number for the
  266. .B printer
  267. service.
  268. .IP "\fB/etc/hosts\fR"
  269. and the resolver files for querying client names.
  270. .IP "\fBhost authorization\fR"
  271. This file contains a list of hostnames (clients) that are allowed to print
  272. on the server.
  273. .IP "\fBSPOOLDIR/lock\fR"
  274. The lock file. It is locked by the first copy of the daemon to prevent multiple
  275. daemons from running simultaneously.
  276. .SH DIAGNOSTICS
  277. .IP "\fBCannot create lockfile. Errno=%d\fR"
  278. The daemon is not able to creat a new lock file. Is the daemon running as priviledged user ?
  279. .IP "\fBDaemon %s is already running on pid=%d\fR"
  280. Self explanatory. The PID of the daemon running is shown.
  281. .IP "\fBRequested printer [%s] does not exist on server\fR"
  282. This message is sent to the initiating
  283. .IR lpr .
  284. .IP "\fBCannot create spool file on server!\fR"
  285. Deadly.
  286. .IP "\fBCan't change into spool-dir [%s]\n\fR"
  287. Deadly.
  288. .IP "\fBHost [%s] is not authorized to print files\fR"
  289. Self explanatory.
  290. .PP
  291. In DEBUG mode, diagnostics are more or less self-explanatory.
  292. .SH NOTES
  293. Many of the original
  294. .I lpd
  295. capabilities are missing in
  296. .IR slpd .
  297. The author is willing to receive requests for modifications, and will try
  298. to implement these, time permitting ;-)
  299. .SH SEE ALSO
  300. .IR lp (1),
  301. .IR lpadmin (1m),
  302. .br
  303. .IR command (3)
  304. by Rich Salz
  305. .SH AUTHOR
  306. Jan-Piet Mens - <jpm@Logix.DE>
  307. SHAR_EOF
  308. chmod 0644 slpd.8 ||
  309. echo 'restore of slpd.8 failed'
  310. Wc_c="`wc -c < 'slpd.8'`"
  311. test 2816 -eq "$Wc_c" ||
  312.     echo 'slpd.8: original size 2816, current size' "$Wc_c"
  313. fi
  314. # ============= TODO ==============
  315. if test -f 'TODO' -a X"$1" != X"-c"; then
  316.     echo 'x - skipping TODO (File already exists)'
  317. else
  318. echo 'x - extracting TODO (Text)'
  319. sed 's/^X//' << 'SHAR_EOF' > 'TODO' &&
  320. I'm still working at:
  321. X
  322. - Run through spool directory upon startup of daemon and process any spool
  323. X  files left over from a previous run.
  324. X
  325. - Add code to ensure only one copy of the daemon is running
  326. X    Done.
  327. X
  328. - Add code for authorization in /etc/hosts.equiv and perhaps other base.
  329. X    Done.
  330. X
  331. - This will probably break on SCO 3.2 < version 4 if POSIX truncate is
  332. X  set in the kernel. Shorten the file names that are transmitted to
  333. X  14 chars max.
  334. X
  335. - Add logging and debugging per switch
  336. SHAR_EOF
  337. chmod 0644 TODO ||
  338. echo 'restore of TODO failed'
  339. Wc_c="`wc -c < 'TODO'`"
  340. test 482 -eq "$Wc_c" ||
  341.     echo 'TODO: original size 482, current size' "$Wc_c"
  342. fi
  343. # ============= slpd.c ==============
  344. if test -f 'slpd.c' -a X"$1" != X"-c"; then
  345.     echo 'x - skipping slpd.c (File already exists)'
  346. else
  347. echo 'x - extracting slpd.c (Text)'
  348. sed 's/^X//' << 'SHAR_EOF' > 'slpd.c' &&
  349. #include "copyright.h"
  350. #include "config.h"
  351. #include "patchlevel.h"
  352. #include <ctype.h>
  353. X
  354. static char rcs_id[] = "@(#)$Id: slpd.c,v 1.1 1992/11/17 18:06:25 jpm Exp jpm $";
  355. char *progname;                    /* My name */
  356. X
  357. int usage()
  358. {
  359. X    extern char *progname;
  360. X    static char *help[] = {
  361. X    "-v    Show version",
  362. X    "-c    Show configuration",
  363. X    NULL };
  364. X    int i;
  365. X
  366. X    fprintf(stderr, "Usage: %s [-v] [-c]\n", progname);
  367. X    for (i = 0; help[i]; i++)
  368. X        fprintf(stderr, "\t%s\n", help[i]);
  369. X    
  370. X    return (EX_USAGE);
  371. }
  372. X
  373. int main(argc, argv)
  374. int argc;
  375. char *argv[];
  376. {
  377. X    int sockfd, newsockfd, clen, pid, lockfd, c;
  378. X    struct sockaddr_in ca;            /* Client Address */
  379. X    extern int errno;
  380. X    static char vs[] = "SLPD 1.0 PL%02d by Jan-Piet Mens - <jpm@Logix.DE>\n";
  381. X
  382. X    progname = *argv;
  383. X
  384. X    while ((c = getopt(argc, argv, "vc")) != EOF) {
  385. X        switch (c) {
  386. X            case 'v':
  387. X                printf(vs, PATCHLEVEL);
  388. X                return (0);
  389. X            case 'c':
  390. X                return showconfig();
  391. X            default:
  392. X                return usage();
  393. X        }
  394. X    }
  395. X
  396. X    /*
  397. X     * Change into the spool directory and create a lock file "lock", to
  398. X     * prevent several copies of the daemon running.
  399. X     */
  400. X
  401. X    if (chdir(SPOOLDIR) == -1)
  402. X        fatal(EX_DATAERR, M_NOSPOOL, SPOOLDIR);
  403. X    if (((lockfd = open("lock", 2)) == -1) &&
  404. X             ((lockfd = creat("lock", 0666)) == -1))
  405. X        fatal(EX_DATAERR, M_CANTLOCK, errno);
  406. X    lockit(lockfd);
  407. X
  408. X    cache_printers();
  409. X    sockfd = sockopen();
  410. X
  411. X    while (1)
  412. X    {
  413. X        /*
  414. X         * Wait for a connection from a client process, and then 
  415. X         * fork-off a new child to do the work.
  416. X         */
  417. X
  418. X        clen = sizeof(ca);
  419. X        newsockfd = accept(sockfd, (struct sockaddr *) &ca, &clen);
  420. X        if (newsockfd < 0)
  421. X            fatal(EX_OSERR, "server: accept error");
  422. X
  423. X        switch (pid = fork()) {
  424. X            case -1:
  425. X                fatal(EX_OSERR, "server: fork error");
  426. X                /*NOTREACHED*/
  427. X                break;
  428. X            case 0:                /* Child */
  429. #ifdef DEBUG
  430. X                fprintf(stderr, "STARTUP CHILD\n");
  431. #endif
  432. X                close(sockfd);        /* Close socket */
  433. X                print(newsockfd);    /* Process request */
  434. X                close(newsockfd);
  435. X                exit(EX_OK);
  436. X            default:            /* Parent */
  437. X                close(newsockfd);    
  438. X                break;
  439. X        }
  440. X    }
  441. }
  442. X
  443. /*
  444. X * This is executed only by the child process. Wait for lines of text
  445. X * arriving from the client LPR, and try to find out what it wants.
  446. X * FD is an open socket to the client.
  447. X */
  448. X
  449. void print(fd)
  450. int fd;
  451. {
  452. X    char buf[BUFSIZ];
  453. X    long bytes;
  454. X    char fname[256];
  455. X    int state = S_START;
  456. X    string printer, hname;
  457. X
  458. X    /*
  459. X     * Lines of text will come in, telling us in the first byte what is
  460. X     * to be done.
  461. X     */
  462. X
  463. X    while (readline(fd, buf, BUFSIZ-1) > 0)
  464. X    {
  465. X        switch (*buf)
  466. X        {
  467. X            /*
  468. X             * 0x02 <printername> \n
  469. X             *    <printername> was requested by -P to LPR
  470. X             */
  471. X
  472. X            case REQ_START:
  473. X                if (state == S_START)
  474. X                {
  475. X                    if (!auth(fd, hname)) {
  476. X                        cpr(fd, M_NOAUTH, hname);
  477. X                        (void) close(fd);
  478. X                        fatal(EX_PROTOCOL, 
  479. X                            M_NOAUTH, hname);
  480. X                    }
  481. X                    sscanf(buf+1, "%s\n", printer);
  482. #ifdef DEBUG
  483. X                    printf("Req.Printer = [%s]\n", printer);
  484. #endif
  485. X                    if (!legal_printer(printer)) {
  486. X                        cpr(fd, M_NOPRINTER, printer);
  487. X                        close(fd);
  488. X                        exit(EX_DATAERR);
  489. X                    }
  490. X
  491. X                    state = S_STARTED;
  492. X                    ack(fd, "\0", 1);
  493. X                    break;
  494. X                }
  495. X                else if (state == S_STARTED)
  496. X                {
  497. X                    /* We have the data file. Here comes
  498. X                     * the control file. */
  499. X
  500. X                    sscanf(buf+1, "%ld %s\n", &bytes,fname);
  501. X                    copyfile(fd, fname, bytes);
  502. X                    close(fd);
  503. X
  504. X                    /* 
  505. X                     * Now start the real work!
  506. X                     */
  507. X                    
  508. X                    printout(fname, printer);
  509. X                    exit(EX_OK);
  510. X                }
  511. X                break;
  512. X
  513. X            /*
  514. X             * 0x03 <bytes> <filename> \n
  515. X             *    <bytes>  holds the size of the data file
  516. X             *    <filename> is like "dfA860host.my.domain"
  517. X             */
  518. X
  519. X            case REQ_FILE:
  520. X                sscanf(buf+1, "%ld %s\n", &bytes, fname);
  521. X                copyfile(fd, fname, bytes);
  522. X                break;
  523. X            case REQ_NOTHING:
  524. X                ack(fd, "\0", 1);
  525. X                break;
  526. X        }
  527. X    }
  528. }
  529. X
  530. /*
  531. X * Create a file FNAME in the spool directory. Read BYTES bytes from socket
  532. X * FD into that file. If something goes wrong, tell the client, and die.
  533. X */
  534. X
  535. void copyfile(fd, fname, bytes)
  536. int fd;
  537. char *fname;
  538. long bytes;
  539. {
  540. X    int outfile;
  541. X    long bytesgot = 0L, n;
  542. X    char buf[BUFSIZ];
  543. X
  544. X    if ((outfile = creat(fname, 0644)) == -1) {
  545. X        cpr(fd, M_CANTCREATE);
  546. X        fatal(EX_OSERR, "Can't create file");
  547. X        close(fd);
  548. X        exit(EX_OSERR);
  549. X    }
  550. X
  551. X    /* Ack receipt of file name */
  552. X    ack(fd, "\0", 1);
  553. X
  554. X    bytesgot = 0L;
  555. X    while (bytesgot < bytes) {
  556. X        n = bytes - bytesgot;
  557. X        if (n > BUFSIZ - 1)
  558. X            n = BUFSIZ - 1;
  559. X        if ((n = readn(fd, buf, n)) < 0)
  560. X            fatal(EX_PROTOCOL, "readn()");
  561. X        else if (n == 0)
  562. X            break;
  563. X        bytesgot += n;
  564. X        write(outfile, buf, n);
  565. X    }
  566. X    close(outfile);
  567. X
  568. X    /* Ack receipt of file */
  569. X    read(fd, buf, 1);
  570. X    ack(fd, "\0", 1);
  571. }
  572. X
  573. /*
  574. X * Open a socket, and bind.
  575. X */
  576. X
  577. int sockopen()
  578. {
  579. X    int sockfd; 
  580. X    struct sockaddr_in serv_addr;
  581. X    struct servent *sp;
  582. X
  583. X    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
  584. X        fatal(EX_OSERR, "server: can't open stream socket");
  585. X
  586. X    if ((sp = getservbyname("printer", "tcp")) == (struct servent *)0)
  587. X        fatal(EX_OSERR, "Can't get port for printer daemon");
  588. X
  589. X    /*
  590. X     * Bind our local address so that the client can send to us.
  591. X     */
  592. X
  593. X    bzero((char *) &serv_addr, sizeof(serv_addr));
  594. X    serv_addr.sin_family      = AF_INET;
  595. X    serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
  596. X    serv_addr.sin_port        = sp->s_port;
  597. X
  598. X    if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
  599. X        fatal(EX_OSERR, "server: can't bind local address");
  600. X
  601. X    listen(sockfd, 5);
  602. X
  603. X    return (sockfd);
  604. }
  605. X
  606. /*
  607. X * Return ZERO if the client on socket SOCKFD is not authorized to use our
  608. X * printers, TRUE otherwise.
  609. X */
  610. X
  611. #define ALLOWED        (1)
  612. #define NOTALLOWED    (0)
  613. X
  614. int auth(sockfd, hname)
  615. int sockfd;
  616. char *hname;
  617. {
  618. X    struct sockaddr_in client;
  619. X    int client_len, rc = NOTALLOWED;
  620. X    struct hostent *h;
  621. X    char *inetaddr, *hostname;
  622. X
  623. X    client_len = sizeof(client);
  624. X    if (getpeername(sockfd, &client, &client_len) == -1) {
  625. X        perror("getpeername");
  626. X        return (NOTALLOWED);
  627. X    }
  628. X    inetaddr = (char *)inet_ntoa(client.sin_addr);
  629. X    client.sin_port = ntohs((u_short)client.sin_port);
  630. X        h = gethostbyaddr(&client.sin_addr, sizeof(struct in_addr),client.sin_family);
  631. X        if (h == (struct hostent *)0)
  632. X        {
  633. X                hostname = "unknown";
  634. X                herror("gethostbyaddr()");
  635. X        rc = NOTALLOWED;
  636. X        }
  637. X        else 
  638. X    {
  639. X        hostname = h->h_name;
  640. X        rc = ALLOWED;
  641. X    }
  642. X    strcpy(hname, hostname);
  643. X
  644. #ifdef DEBUG
  645. X        fprintf(stderr, "Remote caller is: %s [%s]\n", hostname, inetaddr);
  646. #endif
  647. X
  648. X    rc = in_auth_file(hname);
  649. X
  650. X    return (rc);
  651. }
  652. X
  653. /*
  654. X * Return ALLOWED if HNAME is in the host-authorization file, and NOTALLOWED
  655. X * if not. Hosts are matched by whatever is in HNAME.
  656. X * Blank lines and lines starting with a pound sign are ignored.
  657. X */
  658. X
  659. int in_auth_file(hname)
  660. char *hname;
  661. {
  662. X    FILE *fp = fopen(HOSTAUTHFILE, "r");
  663. X    char buf[BUFSIZ];
  664. X    int rc = NOTALLOWED;
  665. X
  666. X    if (!fp || ferror(fp))
  667. X        return (rc);
  668. X
  669. X    while (fgets(buf, BUFSIZ, fp) != (char *)0) {
  670. X        if (*buf == '#' || *buf == '\n')
  671. X            continue;
  672. X        buf[strlen(buf) - 1] = '\0';
  673. X        if (!strcmp(hname, buf)) {
  674. X            rc = ALLOWED;
  675. X            break;
  676. X        }
  677. X    }
  678. X    fclose(fp);
  679. X    return (rc);
  680. }
  681. SHAR_EOF
  682. chmod 0644 slpd.c ||
  683. echo 'restore of slpd.c failed'
  684. Wc_c="`wc -c < 'slpd.c'`"
  685. test 6868 -eq "$Wc_c" ||
  686.     echo 'slpd.c: original size 6868, current size' "$Wc_c"
  687. fi
  688. # ============= util.c ==============
  689. if test -f 'util.c' -a X"$1" != X"-c"; then
  690.     echo 'x - skipping util.c (File already exists)'
  691. else
  692. echo 'x - extracting util.c (Text)'
  693. sed 's/^X//' << 'SHAR_EOF' > 'util.c' &&
  694. #include "copyright.h"
  695. #include "config.h"
  696. #include <ctype.h>
  697. X
  698. #ifdef __STDC__
  699. #    include <stdarg.h>
  700. #else
  701. #    include <varargs.h>
  702. #endif
  703. X
  704. static char rcs_id[] = "@(#)$Id: util.c,v 1.1 1992/11/17 18:06:25 jpm Exp jpm $";
  705. static char *pcache[MAXPRINTERS];        /* Printername cache */
  706. X
  707. /*
  708. X * Build a list of legal printer names on this system, and put them into
  709. X * PC (null-terminated). This is our printer-cache, which will be used
  710. X * to check whether a legal printername has been requested.
  711. X * The macro LP_LISTNAMES is the name of a file which must contain one
  712. X * name per line. Note, this is only done at startup. If LP_LISTNAMES
  713. X * begins with a vertical bar (|) a pipe from LP_LISTNAMES is read.
  714. X */
  715. X
  716. void cache_printers()
  717. {
  718. X    int count = 0;
  719. X    FILE *fp;
  720. X    string buf;
  721. X    unsigned n;
  722. X    int havepipe = 0;
  723. X
  724. #ifdef DEBUG
  725. X    printf("Doing: %s\n", LP_LISTNAMES);
  726. #endif
  727. X    if (*(LP_LISTNAMES) == '|')
  728. X    {
  729. X        if ((fp = popen(LP_LISTNAMES+1, "r")) == (FILE *)0)
  730. X            fatal(EX_OSERR, "Can't read pipe from [%s]\n", 
  731. X                LP_LISTNAMES+1);
  732. X        havepipe = 1;
  733. X    }
  734. X    else if ((fp = fopen(LP_LISTNAMES, "r")) == (FILE *)0)
  735. X        fatal(EX_OSERR, "Can't open file [%s]\n", LP_LISTNAMES);
  736. X    
  737. X    for (count = 0; (fgets(buf, sizeof(buf), fp) != (char *)0) &&
  738. X                        (count < MAXPRINTERS); ++count)
  739. X    {
  740. X        buf[(n = strlen(buf)) - 1] = '\0';    /* Chop NL */
  741. X        pcache[count] = strsave(buf);
  742. #ifdef DEBUG
  743. X        printf("Cached %02d %s\n", count, pcache[count]);
  744. #endif
  745. X    }
  746. X    pcache[count] = (char *)0;
  747. X    if (havepipe)
  748. X        pclose(fp);
  749. X    else
  750. X        fclose(fp);
  751. }
  752. X
  753. /*
  754. X * Return TRUE if PNAME is the name of a legal printer on our system, and
  755. X * FALSE otherwise.
  756. X */
  757. X
  758. int legal_printer(pname)
  759. char *pname;
  760. {
  761. X    int n;
  762. X
  763. X    for (n = 0; pcache[n] && n < MAXPRINTERS; n++)
  764. X        if (!strcmp(pcache[n], pname))
  765. X            return (1);
  766. X    
  767. X    return (0);
  768. }
  769. X
  770. #ifdef __STDC__
  771. void fatal(int excode, char *fmt, ...)
  772. #else
  773. void fatal(excode, fmt, va_alist)
  774. int excode;
  775. char *fmt;
  776. va_dcl
  777. #endif
  778. {
  779. X    va_list args;
  780. X    extern char *progname;
  781. X
  782. #ifdef __STDC__
  783. X    va_start(args, fmt);
  784. #else
  785. X    va_start(args);
  786. #endif
  787. X    fprintf(stderr, "%s: ", progname);
  788. X    vfprintf(stderr, fmt, args);
  789. X    fprintf(stderr, "\n");
  790. X    fflush(stderr);
  791. X    va_end(args);
  792. X    exit(excode);
  793. }
  794. X
  795. void ack(sockfd, ptr, nbytes)
  796. int sockfd;
  797. char *ptr;
  798. int nbytes;
  799. {
  800. X    if (writen(sockfd, ptr, nbytes) <= 0)
  801. X        fatal(EX_PROTOCOL, "Can't write %d bytes to client\n", nbytes);
  802. }
  803. X
  804. /*
  805. X * Read "n" bytes from a descriptor.
  806. X * Use in place of read() when fd is a stream socket.
  807. X */
  808. X
  809. int readn(fd, ptr, nbytes)
  810. register int    fd;
  811. register char    *ptr;
  812. register int    nbytes;
  813. {
  814. X    int    nleft, nread;
  815. X
  816. X    nleft = nbytes;
  817. X    while (nleft > 0) {
  818. X        nread = read(fd, ptr, nleft);
  819. X        if (nread < 0)
  820. X            return(nread);        /* error, return < 0 */
  821. X        else if (nread == 0)
  822. X            break;            /* EOF */
  823. X
  824. X        nleft -= nread;
  825. X        ptr   += nread;
  826. X    }
  827. X    return(nbytes - nleft);        /* return >= 0 */
  828. }
  829. /*
  830. X * Write "n" bytes to a descriptor.
  831. X * Use in place of write() when fd is a stream socket.
  832. X */
  833. X
  834. int writen(fd, ptr, nbytes)
  835. register int    fd;
  836. register char    *ptr;
  837. register int    nbytes;
  838. {
  839. X    int    nleft, nwritten;
  840. X
  841. X    nleft = nbytes;
  842. X    while (nleft > 0) {
  843. X        nwritten = write(fd, ptr, nleft);
  844. X        if (nwritten <= 0)
  845. X            return(nwritten);        /* error */
  846. X
  847. X        nleft -= nwritten;
  848. X        ptr   += nwritten;
  849. X    }
  850. X    return(nbytes - nleft);
  851. }
  852. X
  853. /*
  854. X * Read a line from a descriptor.  Read the line one byte at a time,
  855. X * looking for the newline.  We store the newline in the buffer,
  856. X * then follow it with a null (the same as fgets(3)).
  857. X * We return the number of characters up to, but not including,
  858. X * the null (the same as strlen(3)).
  859. X */
  860. X
  861. int readline(fd, ptr, maxlen)
  862. register int    fd;
  863. register char    *ptr;
  864. register int    maxlen;
  865. {
  866. X    int n, rc;
  867. X    char c;
  868. #ifdef DEBUG
  869. X    char *sp = ptr;
  870. #endif
  871. X
  872. X    for (n = 1; n < maxlen; n++) {
  873. X        if ( (rc = read(fd, &c, 1)) == 1) {
  874. X            *ptr++ = c;
  875. X            if (c == '\n')
  876. X                break;
  877. X        } else if (rc == 0) {
  878. X            if (n == 1)
  879. X                return(0);    /* EOF, no data read */
  880. X            else
  881. X                break;        /* EOF, some data was read */
  882. X        } else
  883. X            return(-1);    /* error */
  884. X    }
  885. X
  886. X    *ptr = 0;
  887. #ifdef DEBUG
  888. X        vis(sp);
  889. #endif
  890. X    return(n);
  891. }
  892. X
  893. #ifdef DEBUG
  894. X
  895. /*
  896. X * Show the content of string S visibly
  897. X */
  898. X
  899. void vis(s)
  900. char *s;
  901. {
  902. X    while (*s) {
  903. X        if (isprint(*s))
  904. X            fputc(*s, stderr);
  905. X        else fprintf(stderr, "\\%03o", *s);
  906. X        ++s;
  907. X    }
  908. X    fprintf(stderr, "\n");
  909. X    fflush(stderr);
  910. }
  911. #endif /* DEBUG */
  912. X
  913. /*
  914. X * cpr(sockfd, fmt, ...)
  915. X *
  916. X * Do a printf() into socket fd.
  917. X */
  918. X
  919. #ifdef __STDC__
  920. void cpr(int sockfd, char *fmt, ...)
  921. #else
  922. void cpr(sockfd, fmt, va_alist)
  923. int sockfd;
  924. char *fmt;
  925. va_dcl
  926. #endif
  927. {
  928. X    va_list args;
  929. X    char buf[1024];
  930. X
  931. #ifdef __STDC__
  932. X    va_start(args, fmt);
  933. #else
  934. X    va_start(args);
  935. #endif
  936. X    vsprintf(buf, fmt, args);
  937. X    va_end(args);
  938. X    
  939. X    strcat(buf, "\n");
  940. X    writen(sockfd, buf, strlen(buf));
  941. }
  942. X
  943. char *strsave(s)
  944. char *s;
  945. {
  946. X    char *p = (char *)malloc((unsigned)(strlen(s) + 1));
  947. X
  948. X    if (!p)
  949. X        fatal(EX_OSERR, "No memory in strsave()");
  950. X
  951. X    (void) strcpy(p, s);
  952. X    return (p);
  953. }
  954. X
  955. int showconfig()
  956. {
  957. X    printf("Compiled-in Configuration:\n");
  958. X    printf("\tSPOOLDIR          = %s\n", SPOOLDIR);
  959. X    printf("\tLP_CMD            = %s\n", LP_CMD  );
  960. X    printf("\tLP_LISTNAMES      = %s\n", LP_LISTNAMES);
  961. X    printf("\tMAXPRINTERS       = %d\n", MAXPRINTERS );
  962. X    printf("\tHOSTAUTHFILE      = %s\n", HOSTAUTHFILE);
  963. X    printf("\tRemove Spool files= %s\n",
  964. #ifdef NOREMOVE
  965. X                "FALSE"
  966. #else
  967. X                "TRUE"
  968. #endif
  969. X        );
  970. X    return (0);
  971. }
  972. SHAR_EOF
  973. chmod 0644 util.c ||
  974. echo 'restore of util.c failed'
  975. Wc_c="`wc -c < 'util.c'`"
  976. test 5233 -eq "$Wc_c" ||
  977.     echo 'util.c: original size 5233, current size' "$Wc_c"
  978. fi
  979. # ============= print.c ==============
  980. if test -f 'print.c' -a X"$1" != X"-c"; then
  981.     echo 'x - skipping print.c (File already exists)'
  982. else
  983. echo 'x - extracting print.c (Text)'
  984. sed 's/^X//' << 'SHAR_EOF' > 'print.c' &&
  985. #include "copyright.h"
  986. #include "config.h"
  987. X
  988. static char rcs_id[] = "@(#)$Id: print.c,v 1.1 1992/11/17 18:06:25 jpm Exp jpm $";
  989. X
  990. /*
  991. X * CFNAME is the name of the control file in the spool directory. Parse 
  992. X * through it, finding out what we actually have to do, and print the output
  993. X * onto printer PRINTER.
  994. X *
  995. X * Control files contain lines of text starting with a capital letter,
  996. X * specifying what is to be done.
  997. X * The following was extracted from a 1983 BSD manual [lpd(8)]
  998. X *
  999. X * +    J<jobname>    String to be used for the job name on the burst page
  1000. X *    C<class>    String to be used for the classification on burst page
  1001. X *    L<literal>    Contains identification info from /etc/passwd
  1002. X * +    T<title>    String to be used as title for pr(1)
  1003. X *    H<host>        Name of machine where LPR was invoked
  1004. X *    P<person>    Login name of person who invoked LPR.
  1005. X *    M<user>        Send mail to the specified user when print job completes
  1006. X * +    f<filename>    Name of formatted file to print (ascii text ?)
  1007. X * +    l<filename>    Like f but passs control chars (Binary)
  1008. X * +    p<filename>    Name of file to print with pr(1)
  1009. X *    t<filename>    Troff file. The file contains troff(1) OUTPUT
  1010. X *    d<filename>    DVI file
  1011. X *    g<filename>    Graph file
  1012. X *    v<filename>    Raster image
  1013. X *    1<filename>    Troff font R
  1014. X *    2<filename>    Troff font I
  1015. X *    3<filename>    Troff font B
  1016. X *    4<filename>    Troff font S
  1017. X *    I<indent>    The number of chars to indent the output by (in ascii)
  1018. X *    U<unlink>    Name of file to remove upon completion of printing
  1019. X *    N<filename>    The name of the file which is being printed, or a blank
  1020. X *            for the standard input (when LPR is invoked in a pipe)
  1021. X *
  1022. X * The entries marked with a + are those implemented here.
  1023. X */
  1024. X
  1025. #define MAXF        200        /* I keep all the file names that come
  1026. X                     * in in an array of this size, so
  1027. X                     * that I can unlink them all when
  1028. X                     * we are finished.
  1029. X                     */
  1030. X
  1031. void printout(cfname, printer)
  1032. char *cfname, *printer;
  1033. {
  1034. X    FILE *fp = fopen(cfname, "r");
  1035. X    char buf[BUFSIZ];
  1036. X    char lpcmd[1024];
  1037. X    string title, options;
  1038. X    int rc;
  1039. #if !defined(NOREMOVE)
  1040. X    int count = 0, i;
  1041. X    char **filenames = (char **)calloc((unsigned)MAXF, sizeof(char *));
  1042. #endif /* !NOREMOVE */
  1043. X
  1044. #ifdef DEBUG
  1045. X    fprintf(stderr, "printout(%s)\n", cfname);
  1046. #endif
  1047. X    if (!fp || ferror(fp))
  1048. X        fatal(EX_OSERR, "Can't re-open control file [%s]\n", cfname);
  1049. #if !defined(NOREMOVE)
  1050. X    if (!filenames)
  1051. X        fatal(EX_OSERR, "No more memory");
  1052. #endif /* !NOREMOVE */
  1053. X
  1054. X    strcpy(options, "-");
  1055. X
  1056. X    /*
  1057. X     * LP flags
  1058. X     * -d    destination
  1059. X     * -s    silent 
  1060. X     * -c     copy. (is default now-a-days, but you never know...)
  1061. X     */
  1062. X
  1063. X    while (fgets(buf, sizeof(buf), fp) != (char *)0)
  1064. X    {
  1065. X        buf[strlen(buf) - 1] = '\0';
  1066. X        switch (*buf) {
  1067. X            case 'f':
  1068. X            case 'l':
  1069. X                sprintf(lpcmd, "%s -d%s -s -c -o%s %s",
  1070. X                    LP_CMD,
  1071. X                    printer,
  1072. X                    options,
  1073. X                    buf + 1);
  1074. #if !defined(NOREMOVE)
  1075. X                if (count < MAXF) 
  1076. X                    filenames[count++] = strsave(buf+1);
  1077. #endif /* !NOREMOVE */
  1078. X                break;
  1079. X            case 'T':
  1080. X                strcpy(title, buf + 1);
  1081. X                continue;
  1082. X            /*
  1083. X             * The Job request from LPR is translated into the
  1084. X             * ``-o'' option for LP.
  1085. X             */
  1086. X
  1087. X            case 'J':
  1088. X                strcpy(options, buf + 1);
  1089. X                continue;
  1090. X            case 'p':
  1091. X                sprintf(lpcmd,
  1092. X                "/bin/pr -h '%s' %s | %s -d%s -s -o'%s'",
  1093. X                    title,
  1094. X                    buf+1,        /* Filename */
  1095. X                    LP_CMD,
  1096. X                    printer,
  1097. X                    options);
  1098. #if !defined(NOREMOVE)
  1099. X                if (count < MAXF) 
  1100. X                    filenames[count++] = strsave(buf+1);
  1101. #endif /* !NOREMOVE */
  1102. X                break;
  1103. X            default:
  1104. #ifdef DEBUG
  1105. X                fprintf(stderr, "Unsupported option '%c'\n",
  1106. X                        *buf);
  1107. X                continue;
  1108. #endif
  1109. X        } /* switch */
  1110. #ifdef DEBUG
  1111. X        fprintf(stderr, "EXEC: %s\n", lpcmd);
  1112. #endif
  1113. X        if ((rc = command(lpcmd, 0)) == 0)
  1114. X            fprintf(stderr, "command [%s] returned %d\n", lpcmd, rc);
  1115. X    }
  1116. X    fclose(fp);
  1117. X    
  1118. #if !defined(NOREMOVE)
  1119. X    /*
  1120. X     * Remove all files that were processed.
  1121. X     */
  1122. X
  1123. X    for (i = 0; (i < count) && (filenames[i]); i++) {
  1124. #ifdef DEBUG
  1125. X        fprintf(stderr, "unlink(%s)\n", filenames[i]);
  1126. #endif
  1127. X        if (unlink(filenames[i]) == -1)
  1128. X            perror(filenames[i]);
  1129. X    }
  1130. X    unlink(cfname);
  1131. #endif /* !NOREMOVE */
  1132. }
  1133. SHAR_EOF
  1134. chmod 0644 print.c ||
  1135. echo 'restore of print.c failed'
  1136. Wc_c="`wc -c < 'print.c'`"
  1137. test 3967 -eq "$Wc_c" ||
  1138.     echo 'print.c: original size 3967, current size' "$Wc_c"
  1139. fi
  1140. # ============= command.c ==============
  1141. if test -f 'command.c' -a X"$1" != X"-c"; then
  1142.     echo 'x - skipping command.c (File already exists)'
  1143. else
  1144. echo 'x - extracting command.c (Text)'
  1145. sed 's/^X//' << 'SHAR_EOF' > 'command.c' &&
  1146. /*COMMAND:  FORK AND EXEC COMMAND STRING
  1147. **
  1148. **  DESCRIPTION:
  1149. **        doneok = command(string, inbackground)
  1150. **  This routine takes a full command string and executes it.  It's
  1151. **  different from "system(3)" in that ">", "<", ">>", and "|" are
  1152. **  handled internally.
  1153. **
  1154. **  This code may be freely copied provided that this sentence and
  1155. **  the copyright are retained; all other rights reserved.  Copyright
  1156. **  1985, Richard E. $alz (rs@mirror.UUCP).
  1157. */
  1158. X
  1159. #include "config.h"
  1160. /* LINTLIBRARY */
  1161. #include <errno.h>
  1162. X
  1163. /* Pick a dialect, any dialect. */
  1164. #undef BSD            /* Bezerkeley    */
  1165. #define USG            /* Deathstar    */
  1166. X
  1167. X
  1168. #ifdef    BSD
  1169. #include <sys/file.h>
  1170. #include <sys/wait.h>
  1171. X
  1172. typedef union wait    WAITER;
  1173. #define W_STATUS(w)    w.w_status
  1174. static char        SHELL[] = "/bin/csh";
  1175. #endif
  1176. X
  1177. X
  1178. #ifdef    USG
  1179. #include <fcntl.h>
  1180. X
  1181. typedef int        WAITER;
  1182. #define W_STATUS(w)    w;
  1183. static char        SHELL[] = "/bin/sh";
  1184. #endif
  1185. X
  1186. X
  1187. /* Handy shorthands. */
  1188. #define STDIN        0
  1189. #define STDOUT      1
  1190. #define SH         (&SHELL[sizeof SHELL - 3])
  1191. X
  1192. /* Globals and externals. */
  1193. extern int         errno;
  1194. int             cmndno;
  1195. int               (*cmndclean)();
  1196. X
  1197. X
  1198. X
  1199. int
  1200. command(text, background)
  1201. X    register char     *text;
  1202. X    int              background;
  1203. {
  1204. X    register char    **vp;
  1205. X    register char    **vector;
  1206. X    register char     *s;
  1207. X    register char     *t;
  1208. X    register int      pid;
  1209. X    register short      count;
  1210. X    WAITER          w;
  1211. X    int              dead;
  1212. X    int              poop[2];
  1213. X
  1214. X    /* "Vfork" is probably not the right thing to do. */
  1215. X    if ((pid = fork()) == 0)
  1216. X    {
  1217. X    /* Call child cleanup routine, if there is one. */
  1218. X    if (cmndclean)
  1219. X        (*cmndclean)();
  1220. X
  1221. X    /* If any meta-characters, pass on to the shell. */
  1222. X    for (t = text; *t; t++)
  1223. X        for (s = ";!~&?*\"\'`\\$(){}"; *s; s++)
  1224. X        if (*s == *t)
  1225. X        {
  1226. X            (void)execl(SHELL, SH, "-c", text, NULL);
  1227. X            _exit(99);
  1228. X        }
  1229. X
  1230. X    /* Get number of words, get an array to hold it. */
  1231. X    for (t = text, count = 2; *t; )
  1232. X        if (*t++ <= ' ')
  1233. X        count++;
  1234. X    vector = (char **)calloc((unsigned int)count, sizeof(char *));
  1235. X
  1236. X    /* Skip leading whitespace. */
  1237. X    while (*text <= ' ')
  1238. X        text++;
  1239. X
  1240. X    /* Loop over command string. */
  1241. X    for (vp = vector; *text; vp++)
  1242. X    {
  1243. X        /* Put pointer to start of word in array, move to next. */
  1244. X        for (*vp = text; *text; text++)
  1245. X        if (*text <= ' ')
  1246. X        {
  1247. X            /* Null out end, skip multiple spaces. */
  1248. X            for (*text++ = '\0'; *text <= ' '; )
  1249. X            text++;
  1250. X            break;
  1251. X        }
  1252. X
  1253. X        /* Handle redirection of input; note we back up the array
  1254. X           pointer to overwrite the "<file", but pick up the filename
  1255. X           as the second character.  Lots of work being done by that
  1256. X           "*vp-- + 1"! */
  1257. X        if (**vp == '<')
  1258. X        {
  1259. X        (void)close(STDIN);
  1260. X        (void)open(*vp-- + 1, O_RDONLY);
  1261. X        }
  1262. X
  1263. X        /* Handle redirection of output. */
  1264. X        if (**vp == '>')
  1265. X        {
  1266. X        (void)close(STDOUT);
  1267. X        /* Undocumented; handle ">>file", too. */
  1268. X        if ((*vp)[1] == '>')
  1269. X            (void)open(*vp-- + 2, O_WRONLY | O_CREAT | O_APPEND, 0666);
  1270. X        else
  1271. X            (void)open(*vp-- + 1, O_WRONLY | O_CREAT | O_TRUNC, 0666);
  1272. X        }
  1273. X
  1274. X        /* Handle piping. */
  1275. X        if (!strcmp(*vp, "|"))
  1276. X        {
  1277. X        (void)pipe(poop);
  1278. X        if (fork() == 0)
  1279. X        {
  1280. X            /* Kid is left side of "|"; change stdout, close pipe. */
  1281. X            (void)close(STDOUT);
  1282. X            (void)dup(poop[1]);
  1283. X            (void)close(poop[0]);
  1284. X            (void)close(poop[1]);
  1285. X            /* Break out to the exec() part. */
  1286. X            break;
  1287. X        }
  1288. X        /* Parent is right side of "|"; change stdin, close pipe. */
  1289. X        (void)close(STDIN);
  1290. X        (void)dup(poop[0], STDIN);
  1291. X        (void)close(poop[0]);
  1292. X        (void)close(poop[1]);
  1293. X        /* Cheat; vp is incremented in next pass through loop. */
  1294. X        vp = vector - 1;
  1295. X        }
  1296. X    }
  1297. X    *vp = NULL;
  1298. X    (void)execvp(*vector, vector);
  1299. X    _exit(99);
  1300. X    }
  1301. X
  1302. X    if (background || pid < 0)
  1303. X    return(pid);
  1304. X
  1305. X    /* Wait until the kid exits, or until errno tells us that we have
  1306. X       no kid (what happened?)  NOTE:  if the caller has other processes
  1307. X       in the background, and they exit first, they will be found, and
  1308. X       ignored, here. */
  1309. X    do
  1310. X    dead = wait(&w);
  1311. X    while (dead != pid && (dead > 0 || errno != ECHILD));
  1312. X
  1313. X    cmndno = W_STATUS(w);
  1314. X    return(cmndno == 0);
  1315. }
  1316. SHAR_EOF
  1317. chmod 0644 command.c ||
  1318. echo 'restore of command.c failed'
  1319. Wc_c="`wc -c < 'command.c'`"
  1320. test 4021 -eq "$Wc_c" ||
  1321.     echo 'command.c: original size 4021, current size' "$Wc_c"
  1322. fi
  1323. # ============= lock.c ==============
  1324. if test -f 'lock.c' -a X"$1" != X"-c"; then
  1325.     echo 'x - skipping lock.c (File already exists)'
  1326. else
  1327. echo 'x - extracting lock.c (Text)'
  1328. sed 's/^X//' << 'SHAR_EOF' > 'lock.c' &&
  1329. #include "copyright.h"
  1330. X
  1331. #include "config.h"
  1332. #include <errno.h>
  1333. #include <fcntl.h>
  1334. X
  1335. int lockit(fd)
  1336. int fd;
  1337. {
  1338. X    struct flock l;
  1339. X    extern char *progname;
  1340. X
  1341. X    l.l_type = F_WRLCK;
  1342. X    l.l_whence = 0;
  1343. X    l.l_start = 0;
  1344. X    l.l_len = 0;
  1345. X
  1346. X    if (fcntl(fd, F_GETLK, &l) == -1)
  1347. X    {
  1348. X        if (errno == EACCES)
  1349. X            fatal(EX_OSERR,M_ISRUNNING, progname, l.l_pid);
  1350. X        perror("fcntl");
  1351. X        exit(99);
  1352. X    }
  1353. X    l.l_type = F_WRLCK;
  1354. X    l.l_whence = 0;
  1355. X    l.l_start = 0;
  1356. X    l.l_len = 0;
  1357. X
  1358. X    if (fcntl(fd, F_SETLK, &l) == -1)
  1359. X    {
  1360. X        if (errno == EACCES || errno == EAGAIN)
  1361. X        {
  1362. X            fatal(EX_OSERR,M_ISRUNNING, progname, l.l_pid);
  1363. X            exit(1);
  1364. X        }
  1365. X        perror("fcntl");
  1366. X    }
  1367. }
  1368. SHAR_EOF
  1369. chmod 0644 lock.c ||
  1370. echo 'restore of lock.c failed'
  1371. Wc_c="`wc -c < 'lock.c'`"
  1372. test 609 -eq "$Wc_c" ||
  1373.     echo 'lock.c: original size 609, current size' "$Wc_c"
  1374. fi
  1375. # ============= copyright.h ==============
  1376. if test -f 'copyright.h' -a X"$1" != X"-c"; then
  1377.     echo 'x - skipping copyright.h (File already exists)'
  1378. else
  1379. echo 'x - extracting copyright.h (Text)'
  1380. sed 's/^X//' << 'SHAR_EOF' > 'copyright.h' &&
  1381. /*
  1382. X * SLPD, Copyright 1992,   Jan-Piet Mens [Logix GmbH, Wiesbaden, Germany]
  1383. X * License to freely use and distribute this software is hereby granted 
  1384. X * by the author, subject to the condition that this copyright notice 
  1385. X * remains intact.  The author retains the exclusive right to publish 
  1386. X * derivative works based on this work, including, but not limited
  1387. X * to, revised versions of this work.
  1388. X */
  1389. SHAR_EOF
  1390. chmod 0644 copyright.h ||
  1391. echo 'restore of copyright.h failed'
  1392. Wc_c="`wc -c < 'copyright.h'`"
  1393. test 401 -eq "$Wc_c" ||
  1394.     echo 'copyright.h: original size 401, current size' "$Wc_c"
  1395. fi
  1396. # ============= config.h ==============
  1397. if test -f 'config.h' -a X"$1" != X"-c"; then
  1398.     echo 'x - skipping config.h (File already exists)'
  1399. else
  1400. echo 'x - extracting config.h (Text)'
  1401. sed 's/^X//' << 'SHAR_EOF' > 'config.h' &&
  1402. #include "copyright.h"
  1403. X
  1404. /*=====================================================================
  1405. X * SPOOLDIR            One of the first things the daemon will
  1406. X *                do is to change into this directory.
  1407. X * The daemon must have write permission here, because it will create
  1408. X * the data and control files in this directory.
  1409. X *====================================================================*/
  1410. #define SPOOLDIR        "/usr/spool/slpd"
  1411. X
  1412. /*=====================================================================
  1413. X * LP_CMD            The full pathname to ``lp''. Options
  1414. X *                are added in print.c
  1415. X *====================================================================*/
  1416. X #define LP_CMD            "/usr/bin/lp"
  1417. X
  1418. /*=====================================================================
  1419. X * LP_LISTNAMES            If this command contains a vertical bar
  1420. X *                as its first character, it will be
  1421. X * considered as the name of a pipe to be read via popen(3).
  1422. X * Otherwise, it is the name of a file that contains a list of printer
  1423. X * names, one on each line.
  1424. X * Both the FILE and the PIPE must produce one legal printer destination
  1425. X * per line. This printer destination will be given to LP_CMD in the
  1426. X * ``-d'' switch.
  1427. X * 
  1428. X *      lpr -Pmyprinter         becomes        ... lp -dmyprinter ...
  1429. X *          ^^^^^^^^^^^                               ^^^^^^^^^^^
  1430. X * A configuration suggestion is
  1431. X *       #define LP_LISTNAMES        \
  1432. X        "|lpstat -p | awk '{if ($1 == \"printer\") {print $2}}'"
  1433. X
  1434. X        ^^^^ NOTE THE VERTICAL BAR!
  1435. X * which will read the current printer configuration upon startup of the
  1436. X * SLPD daemon. Note, that this is rather slow.
  1437. X *
  1438. X * In either case, the SLPD daemon will have to be restarted if a new
  1439. X * printer is added to the system.
  1440. X *====================================================================*/
  1441. /* #define LP_LISTNAMES        "/etc/Printers" */
  1442. #define LP_LISTNAMES        \
  1443. X        "|lpstat -p | awk '{if ($1 == \"printer\") {print $2}}'"
  1444. X
  1445. /*=====================================================================
  1446. X * MAXPRINTERS            The maximum number of printer names that
  1447. X *                 should be cached upon startup of the
  1448. X * daemon. Caching is done by parsing the output of LP_LISTNAMES, and
  1449. X * inserting the names of the printers into a dynamically built array.
  1450. X *====================================================================*/
  1451. #define MAXPRINTERS        (20)
  1452. X
  1453. /*=====================================================================
  1454. X * HOSTAUTHFILE            Absolute pathname of a file containing
  1455. X *                a list of host names which are allowed
  1456. X * to access the daemon. The file contains one host per line. Note, that
  1457. X * host names are matched by whatever gethostbyname() returns.
  1458. X *====================================================================*/
  1459. /*#define HOSTAUTHFILE        "/etc/hosts.equiv" */
  1460. #define HOSTAUTHFILE        "/etc/hostlist"
  1461. X
  1462. /*=====================================================================
  1463. X * NOREMOVE            If you want the temporary spool & control
  1464. X *                files to remain in the spool directory,
  1465. X * define NOREMOVE. If this symbol is *not* defined, files will be removed
  1466. X * automagically. This should only be interesting for debugging purposes.
  1467. X *====================================================================*/
  1468. X #undef NOREMOVE
  1469. X
  1470. X
  1471. /*
  1472. X * Messages
  1473. X */
  1474. X
  1475. #define M_CANTLOCK    "Cannot create lockfile. Errno=%d"
  1476. #define M_ISRUNNING    "Daemon %s is already running on pid=%d"
  1477. #define M_NOPRINTER    "\r\nRequested printer [%s] does not exist on server"
  1478. #define M_CANTCREATE    "Cannot create spool file on server!"
  1479. #define M_NOSPOOL    "Can't change into spool-dir [%s]\n"
  1480. #define M_NOAUTH    "Host [%s] is not authorized to print files"
  1481. X
  1482. X
  1483. /* ----- DON'T CHANGE ANYTHING BELOW THIS LINE --------------------------*/
  1484. typedef char string[128];
  1485. X
  1486. #define S_START        (1)    /* Client initiated connection */
  1487. #define S_STARTED    (2)    /* Client has started transferring file */
  1488. #define S_CONTROL    (3)    /* Control file expected */
  1489. X
  1490. #define REQ_NOTHING    0x00    /* ^@ */
  1491. #define REQ_START    0x02    /* ^B */
  1492. #define REQ_FILE    0x03    /* ^C */
  1493. X
  1494. X
  1495. #include <stdio.h>
  1496. #include <sys/types.h>
  1497. #include <sys/socket.h>
  1498. #include <netinet/in.h>
  1499. #include <arpa/inet.h>
  1500. #include <sysexits.h>
  1501. #include <netdb.h>
  1502. #include <string.h>
  1503. X
  1504. #include <stdlib.h>            /* Remove this line if you don't have */
  1505. X
  1506. X
  1507. #if defined(__STDC__) || defined(__cplusplus)
  1508. #define P_(s) s
  1509. #else
  1510. #define P_(s) ()
  1511. #endif
  1512. X
  1513. int main P_((int argc, char *argv[]));
  1514. void print P_((int fd));
  1515. void fatal P_((int excode, char *fmt, ...));
  1516. void cpr P_((int fd, char *fmt, ...));
  1517. int readn P_((register int fd, register char *ptr, register int nbytes));
  1518. int writen P_((register int fd, register char *ptr, register int nbytes));
  1519. int readline P_((register int fd, register char *ptr, register int maxlen));
  1520. void vis P_((char *s));
  1521. int sockopen P_((void));
  1522. void copyfile P_((int fd, char *name, long bytes));
  1523. void cache_printers P_((void));
  1524. void ack P_((int fd, char *s, int nbytes));
  1525. void printout P_((char *filename, char *printer));
  1526. int legal_printer P_((char *pname));
  1527. int command P_((char *shstring, int back));
  1528. char *strsave P_((char *s));
  1529. int auth P_((int sockfd, char *hname));
  1530. int in_auth_file P_((char *hname));
  1531. int lockit P_((int fd));
  1532. int showconfig P_((void));
  1533. X
  1534. extern int accept(), bind(), bzero(), chdir(), close(), creat(),
  1535. X        dup(), execl(), execvp(), fork(), listen(), open(),
  1536. X        pipe(), read(), socket(), wait(), write(), unlink();
  1537. X
  1538. #undef P_
  1539. SHAR_EOF
  1540. chmod 0644 config.h ||
  1541. echo 'restore of config.h failed'
  1542. Wc_c="`wc -c < 'config.h'`"
  1543. test 5310 -eq "$Wc_c" ||
  1544.     echo 'config.h: original size 5310, current size' "$Wc_c"
  1545. fi
  1546. # ============= patchlevel.h ==============
  1547. if test -f 'patchlevel.h' -a X"$1" != X"-c"; then
  1548.     echo 'x - skipping patchlevel.h (File already exists)'
  1549. else
  1550. echo 'x - extracting patchlevel.h (Text)'
  1551. sed 's/^X//' << 'SHAR_EOF' > 'patchlevel.h' &&
  1552. #define PATCHLEVEL    2
  1553. SHAR_EOF
  1554. chmod 0644 patchlevel.h ||
  1555. echo 'restore of patchlevel.h failed'
  1556. Wc_c="`wc -c < 'patchlevel.h'`"
  1557. test 21 -eq "$Wc_c" ||
  1558.     echo 'patchlevel.h: original size 21, current size' "$Wc_c"
  1559. fi
  1560. exit 0
  1561. -- 
  1562.     __  _____   __  __ 
  1563.    |  ||  _  \ |  \/  |    Logix GmbH                             jpm@Logix.DE
  1564.  __|  ||  ___/ |      |    Moritzstrasse 50, +49-611-309797   jpm@logixwi.UUCP
  1565. |_____||__|    |__||__|    D-6200 Wiesbaden  ...!uunet!mcsun!unido!logixwi!jpm
  1566.