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

  1. Subject:  v16i020:  Public lineprinter spooler package, Part07/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 20
  8. Archive-name: plp/part07
  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 7 (of 16)."
  17. # Contents:  doc/PLP/06.t doc/PLP/07.t src/checkpc.c
  18. #   src/remoteprinter.c src/startprinter.c
  19. # Wrapped by papowell@attila on Wed Aug 10 10:44:57 1988
  20. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  21. if test -f 'doc/PLP/06.t' -a "${1}" != "-c" ; then 
  22.   echo shar: Will not clobber existing file \"'doc/PLP/06.t'\"
  23. else
  24. echo shar: Extracting \"'doc/PLP/06.t'\" \(10628 characters\)
  25. sed "s/^X//" >'doc/PLP/06.t' <<'END_OF_FILE'
  26. X.ig
  27. X$Header: 06.t,v 1.1 88/05/21 18:39:41 papowell Locked $
  28. X$log$
  29. X..
  30. X.NH 1
  31. Local Spool Queues and Servers
  32. X.PP
  33. The 
  34. X.I lpd
  35. process
  36. handles the unspooling process for local and remote spool queues in
  37. much the same manner.
  38. X.I Lpd
  39. forks a server process to unspool entries from a queue.
  40. The server (or unspooler) process checks the spool queue lock file to see if
  41. unspooling is enabled,
  42. sorts jobs according to priority,
  43. and then takes printing actions as specified by the
  44. printcap entry for the spool queue.
  45. In order to provide fine control over the printing process,
  46. the unspooler forks a set of filter processes
  47. based on information in the printcap entry to handle specialized printer
  48. requirements.
  49. These filter processes are used to:
  50. X.IP 1). 3
  51. Provide control over device dependencies,
  52. above that allowed by the simple serial line control functions.
  53. X.IP 2). 3
  54. Print banners or job separator information.
  55. X.IP 3). 3
  56. Provide specific processing for a particular job format.
  57. X.IP 4). 3
  58. Provide accounting information.
  59. X.PP
  60. Different classes of output devices require different amounts or kinds of
  61. filter support.
  62. The following sections outline the different options
  63. and the filter support provided for them.
  64. X.NH 2
  65. Job Format and Filter Selection
  66. X.PP
  67. Associated with each data file of a job is a unspooling format.
  68. When unspooling a job,
  69. the server uses this format to select a filter to be used to process
  70. the data file.
  71. By convention,
  72. the format used for printing a job is specified by
  73. a lower case letter (a\-z),
  74. and the corresponding filter for the format is specified by
  75. the printcap field
  76. x\c
  77. X.B f,
  78. where x represents the format.
  79. This is not uniformly true,
  80. as the
  81. X.B af
  82. X(accounting file name),
  83. X.B lf
  84. X(log file name),
  85. and
  86. X.B ff
  87. X(form feed string)
  88. entries are used for other purposes.
  89. In Figure 6.1,
  90. X.B af
  91. specifies the accounting file,
  92. X.B lf
  93. is the log file,
  94. and
  95. X.B of ,
  96. X.B if ,
  97. and
  98. X.B tf
  99. are filter programs.
  100. X.KF
  101. X.DT
  102. X.nf
  103. X.SM
  104. X.L
  105. X.in +1i
  106. X# Versatec Printer, Lind 33
  107. X#   Uses the new filters
  108. versatec_lind33\||\|versatec:\e
  109. X    :fx=flpdt:mx#2000:\e
  110. X    :lp=/dev/va0:sd=/usr/spool/versatec_lind33:\e
  111. X    :af=vaacct:\e
  112. X    :lf=logfile:\e
  113. X    :of=/usr/lib/vpf:\e
  114. X    :if=/usr/lib/vpf:\e
  115. X    :df=/usr/lib/vpf:\e
  116. X    :tf=/usr/lib/rvcat:
  117. X.in -1i
  118. X.LG
  119. X.R
  120. X.ce
  121. XFigure 6.1.  Local Printer Printcap Entry
  122. X.KE
  123. X.NH 2
  124. No Filter Support Specified
  125. X.PP
  126. If no output filters are specified,
  127. the server opens the output device,
  128. sets the serial line characteristics if it is a serial line,
  129. and prints directly to the output device.
  130. X.NH 2
  131. Banners and Separators
  132. X.PP
  133. By default,
  134. jobs are separated by a banner page or separator page that is generated by the
  135. server process.
  136. The default banner is a single page,
  137. with the user name and job information printed in large letters.
  138. The
  139. X.B sb
  140. X(short banner)
  141. option specifies a single line banner of the following form:
  142. X.nf
  143. X.ti +5
  144. X.L "[user]:[host] Job: [jobname] Date: [date]"
  145. X.ti +5
  146. X.L "papowell:attila.cs.umn.edu Job: (stdin) Date: Fri May 20 11:29:05 1988"
  147. X.fi
  148. X.PP
  149. The
  150. X.B sh
  151. X(suppress header)
  152. flag suppress banner printing.
  153. The
  154. X.I lpr
  155. no header option 
  156. X(\-h)
  157. allows the user to request no header or banner for the job;
  158. the
  159. X.B ab
  160. X(always print banner) printcap flag
  161. causes the server to ignore the no banner request.
  162. X.PP
  163. Consecutive printer jobs are normally separated by a form feed;
  164. the default (c
  165. X.B \ef )
  166. can be changed by specifying a value for the
  167. X.B ff
  168. X(form feed string) field.
  169. The
  170. X.B sf
  171. X(suppress form feeds)
  172. can be used to suppress any printing of form feeds between jobs.
  173. When the printer is started,
  174. it may be necessary to initialize the printer by sending some additional
  175. information.
  176. The
  177. X.B fo
  178. X(form feed on open) flag specifies that the
  179. X.B ff
  180. string is printed before the first job,
  181. and the
  182. X.B fq
  183. X(form feed on quitting)
  184. flag specifies that a form feed is printed after the last job.
  185. In addition,
  186. X.B ld
  187. X(leader on open) specifies a string to be printed before the
  188. X(optional) intial form feed
  189. and the
  190. X.B tr
  191. X(trailer) specifies a string to be printed after the
  192. the (optional) final form feed.
  193. The
  194. X.B ld
  195. and
  196. X.B tr
  197. strings are useful for specifying an escape sequence that sets up
  198. form length, etc.
  199. X.PP
  200. In addition to the built in banner printer,
  201. the
  202. X.B bp
  203. X(banner printer)
  204. and
  205. X.B ep
  206. X(end printer)
  207. fields can be used to specify banner and trailer printing programs.
  208. These programs are invoked to print banners or other information after the
  209. built in banner or separator has been printed.
  210. Custom banner printing may be done by suppressing built in banners with
  211. X.B sh
  212. and
  213. X.B sf
  214. and using the
  215. X.B bp
  216. and
  217. X.B ep
  218. entries.
  219. X.NH 2
  220. Simple OF and IF Filter Support
  221. X.PP
  222. The
  223. X.B OF
  224. X(output filter)
  225. specified by the
  226. X.B of
  227. field is used by the server to
  228. print banners and provide a simple filter action for devices that
  229. need a minmum amount of control.
  230. The OF filter
  231. is not intended to perform accounting since it is started only once
  232. and no provision is made for passing
  233. owners' login name,
  234. identifying the begining and ending of jobs,
  235. etc.
  236. X.PP
  237. The OF filter is started when the server discovers that it has a
  238. job to print.
  239. The server will open the output device,
  240. do any line control operations,
  241. and then start the OF filter.
  242. Banner and job separator strings will be sent to the
  243. OF filter,
  244. which filters them and sends them to the output device.
  245. In order to use other filters,
  246. the server will request the OF
  247. filter to suspend itself by sending it the two character sequence
  248. X\e031\e001 or ESC ^A.
  249. The OF filter should then suspend itself by using a
  250. X.L "kill(0,SIGSTOP)" .
  251. The server will wait for this event,
  252. and then start up other filters.
  253. After they have completed,
  254. the server will signal the OF filter to continue by using
  255. X.L "kill(OF_pid,SIGCONT)" .
  256. X.PP
  257. The IF filter
  258. specified by the
  259. X.B if
  260. field is used to format jobs with the
  261. X.B f
  262. format,
  263. which is for ordinary textual output.
  264. The
  265. X.I lpr
  266. program will use 
  267. X.B f
  268. format by default if no format is specified,
  269. and also for printing literal output
  270. X(lpr \-l option)
  271. or
  272. X.I pr
  273. output (lpr \-p option).
  274. The IF filter is expected to do formatting and update an accounting file.
  275. If there is no IF filter and an
  276. X.B f
  277. format job is printed,
  278. it is filtered through the
  279. X.B OF
  280. filter.
  281. If there is no OF filter,
  282. then the printer will copy the file directly to the output device.
  283. X.NH 2
  284. Non-standarstandard Formats and Filters
  285. X.PP
  286. The
  287. X.B lpr
  288. program allows the user to specify a job format;
  289. the
  290. X.B f
  291. format is the default format for text files.
  292. The
  293. X.B fx
  294. printcap field specifies the formats allowed on the printer;
  295. the default permitted formats are
  296. X.L "f, l,"
  297. and
  298. X.L "p" .
  299. The
  300. X.B lpr
  301. program checks to see if the requested format is allowed when
  302. it spools a job.
  303. XEach format must have a corresponding filter,
  304. which is used to process data files of the specified format.
  305. Note that these filters may be invoked once per data file,
  306. or the entire set of data files may be combined into a single file
  307. and passed through a single invocation of the filter.
  308. Usually the effects of doing this are indistinguishable,
  309. but some filters will cause an alignment of printer media
  310. to be done for each invocation.
  311. This is an implementation dependent phenomina.
  312. X.PP
  313. The commonly available set of formats is specified in the
  314. X.I lpr
  315. man page.
  316. The
  317. X.I "f"
  318. X(default),
  319. X.I "l"
  320. X(literal),
  321. and
  322. X.I p
  323. X(use the ``pr'' program to format output)
  324. formats are printed using the
  325. X.B if
  326. output filter.
  327. The
  328. X.I lpr
  329. X\-f option is used to specify printing with a filter that
  330. handles FORTRAN formats;
  331. this flag is translated by
  332. X.I lpr
  333. into printing with the
  334. X.B r
  335. format.
  336. The
  337. X.I "a, i, l,"
  338. and
  339. X.I "o"
  340. formats are unavailable,
  341. as their filter names
  342. X(\c
  343. X.L af,
  344. X.L if,
  345. X.L lf
  346. and
  347. X.L of )
  348. are used for other purposes.
  349. X.NH 2
  350. Prefilters
  351. X.PP
  352. The 
  353. X.I lpr
  354. program can pre-filter files before spooling them.
  355. The
  356. X.B Xe
  357. field is used to specify that format
  358. X.B X
  359. files are to processed by the specified prefilter.
  360. The prefilter specification consists of the pathname and arguments of the
  361. prefilter program,
  362. followed by the format that is to be used for spooling the output.
  363. X.KF
  364. X.DT
  365. X.L
  366. X.SM
  367. X.nf
  368. X.in +1i
  369. X# Versatec Printer, Lind 33
  370. X#   Uses a prefilter for f format
  371. versatec_lind33\||\|versatec:\e
  372. X    :fx=flpdt:mx#2000:\e
  373. X    :lp=/dev/va0:sd=/usr/spool/versatec_lind33:\e
  374. X    :af=/usr/adm/vaacct:\e
  375. X    :of=/usr/lib/vpf:\e
  376. X    :if=/usr/lib/vpf:\e
  377. X    :df=/usr/lib/vpf:\e
  378. X    :tf=/usr/lib/rvcat:\e
  379. X    :fe=/usr/local/lib/vprintup -X w4,f:
  380. X.R
  381. X.LG
  382. X.in -1i
  383. X.ce
  384. XFigure 6.2 Prefilter Printcap Entry
  385. X.KE
  386. XFor example,
  387. the printcap entry in Figure 6.2 specifies that
  388. X.B f
  389. format files are prefiltered through
  390. X.I vprintup
  391. and the output is in the
  392. X.I f
  393. format.
  394. X.NH 2
  395. Special Queue Handlers
  396. X.PP
  397. If the user does not like the way that the PLP server handles files,
  398. the printcap can be used to specify a queue handler program
  399. to handle processing of the job and data files.
  400. This is useful when you are sending files to a remote machine
  401. using a special protocol or a remote procedure call.
  402. The printcap queue handler field
  403. X.B qh
  404. specifies a program which will be responsible
  405. for handling the job.
  406. X.KF
  407. X.DT
  408. X.L
  409. X.SM
  410. X.nf
  411. X.in +1i
  412. X.ta 4n +4n +4n +4n +4n +4n +4n +4n +4n +4n +4n 8i
  413. X# Special queue entry, used for bizzare purposes
  414. X# The queue_handler program will take care of everything
  415. special:\e
  416. X    :lp=/dev/null:\e
  417. X    :qh=/usr/local/lib/queue_handler:
  418. X.R
  419. X.LG
  420. X.in -1i
  421. X.ce
  422. XFigure 6.3 Queue Handler Printcap Entry
  423. X.KE
  424. X.PP
  425. The queue handler is invoked once per queue entry,
  426. and exits with a 0 (successful),
  427. X1 (unsuccessful, retry),
  428. or other (give up and delete entry) status.
  429. XError messages printed on
  430. X.I stderr
  431. X(file descriptor 2) will be placed in the spool queue log file.
  432. X.NH 2
  433. Multiple Servers For a Spool Queue
  434. X.PP
  435. If a spool queue has multiple servers,
  436. they are specified using the
  437. X.B sv
  438. X(servers) parameter,
  439. which contains a comma separated list of server entries in the printcap file.
  440. The printcap entry for a server contains a
  441. X.B ss
  442. X(serves) parameter which contains the name of the spool queue that it
  443. serves.
  444. X.PP
  445. Printcap entries for the server are determined in the following manner.
  446. When the spool queue server starts up,
  447. it reads the spool queue printcap entry,
  448. and determines that there are multiple servers for the queue.
  449. It then forks a printer server process for each name in the
  450. X.B sv
  451. list.
  452. X.PP
  453. The individual printer server process reads the printcap entry for the
  454. individual printer,
  455. overwriting or adding any existing values read from printcap for the
  456. spool queue.
  457. Since server entries use the
  458. the spool directory of the spool queue,
  459. their individual log and other files should have
  460. distinct names.
  461. Common information can be put in the spool queue printcap entry,
  462. and entries that differ for each printer,
  463. such as the output device,
  464. need to appear the individual printer printcap entry.
  465. END_OF_FILE
  466. if test 10628 -ne `wc -c <'doc/PLP/06.t'`; then
  467.     echo shar: \"'doc/PLP/06.t'\" unpacked with wrong size!
  468. fi
  469. # end of 'doc/PLP/06.t'
  470. fi
  471. if test -f 'doc/PLP/07.t' -a "${1}" != "-c" ; then 
  472.   echo shar: Will not clobber existing file \"'doc/PLP/07.t'\"
  473. else
  474. echo shar: Extracting \"'doc/PLP/07.t'\" \(9734 characters\)
  475. sed "s/^X//" >'doc/PLP/07.t' <<'END_OF_FILE'
  476. X.ig
  477. X$Header: 07.t,v 1.1 88/05/21 18:39:43 papowell Locked $
  478. X$log$
  479. X..
  480. X.bp
  481. X.NH 1
  482. XFilter Support
  483. X.PP
  484. The filter programs are started by a queue server
  485. in order to support specialized unspooling operations.
  486. While the server process runs SUID 
  487. X.L root ,
  488. and the filter process will also run SUID
  489. X.L daemon .
  490. The ownerships of files,
  491. etc.,
  492. which have to be manipulated by filter programs should
  493. have the appropriate permissions for the
  494. X.L daemon
  495. userid.
  496. X.PP
  497. There are a set of template filters supplied with the PLP software
  498. that can be easily modified to meet most common requirements.
  499. A common method of incorporating new filters is to use a shell
  500. script as a filter,
  501. and have the shell script invoke a specialized program with the
  502. appropriate parameters.
  503. This techique has a slight penalty in performance,
  504. but is very quick to implement.
  505. X.PP
  506. X.NH 2
  507. XFilter Program Invocation and Actions
  508. X.PP
  509. Output filters are invoked by the queue server daemon,
  510. and take their input from stdin
  511. X(file descriptor 0),
  512. have stdout (file descriptor 1) connected to the output device,
  513. and stderr (file descriptor 2) connected either to
  514. X.B lf
  515. X(log file) or to a data sink (/dev/null).
  516. Normal completion of the filter results when
  517. it reads EOF on stdin,
  518. and should exit with user status 0 if there were no errors.
  519. It should ignore any SIGPIPE signals.
  520. A user status 1 indicates that the job did not complete
  521. normally and should be reprinted,
  522. and any other status will cause the job to be discarded.
  523. The filter should also check for successful writes to stdout.
  524. X.PP
  525. A filter process runs setuid 
  526. X.I daemon
  527. and is in the same process group as its creating server process.
  528. This allows
  529. X.IR killpg \|(2)
  530. to kill both the queue server process and any filters it has created.
  531. XFor example,
  532. X.I lprm
  533. terminates a running queue handler by
  534. sending a SIGINT signal to the queue servers process group using
  535. X.I killpg.
  536. This signal can be trapped by filters which need
  537. to perform cleanup operations such as
  538. deleting temporary files.
  539. X.NH 2
  540. XFilter Parameters and Invocation
  541. X.PP
  542. XFilters are invoked with a set of parameters determined by the
  543. entries in the printcap,
  544. their intended purpose,
  545. and other actions.
  546. XFigure 7.1 is an example of a filter specification.
  547. X.KF
  548. X.in +1i
  549. X.nf
  550. X.DT
  551. X.L
  552. X.SM
  553. X# Versatec Printer, Lind 33
  554. X# Patrick Powell, 3 Nov 87
  555. X#   Uses the new filters
  556. versatec\||\|versatec_lind33:\e
  557. X    :fx=flpdt:mx#2000:\e
  558. X    :lp=/dev/va0:sd=/usr/spool/versatec_lind33:\e
  559. X    :af=/usr/adm/vaacct:\e
  560. X    :of=/usr/lib/vpf -v3 -m '-K prefix \e013\e015':
  561. X.LG
  562. X.in -1i
  563. X.R
  564. X.ce
  565. XFigure 7.1. Filter Specification Example
  566. X.KE
  567. X.PP
  568. A filter is invoked with the parameters in Figure 7.2,
  569. which may be present or missing,
  570. and in any order.
  571. The accounting file (if present) will always be the last parameter,
  572. and is the only one without a
  573. X.B \-
  574. prefix.
  575. X.KF
  576. X.nf
  577. X.DT
  578. X.L
  579. X.SM
  580. X.in +1i
  581. filtername arguments \e
  582. X    -Pprinter -wwidth -llength -xwidth -ylength [-c] [-iindent] \e
  583. X    [-Zoptions] [-Cclass] [-Jjob] [-Raccntname] -nlogin -hHost \e
  584. X    -Fformat [affile]
  585. X.R
  586. X.in -1i
  587. X.LG
  588. X.ce
  589. XFigure 7.2  Filter Arguments
  590. X.KE
  591. X.PP
  592. The
  593. X.I filtername
  594. and
  595. X.I arguments
  596. values are provided in the printcap filter information.
  597. Arguments can be quoted and will be passed as a single argument to the
  598. filter program,
  599. similar to the method used by the Bourne shell.
  600. Note that the escape sequences in Figure 7.1 will be translated into
  601. a single character value,
  602. and the resulting string will be an arguement for the filter.
  603. X.PP
  604. The
  605. X.B \-P
  606. X(printer) option is used to pass the printcap entry printer name.
  607. The
  608. X.B \-w
  609. and
  610. X.B \-l
  611. options specify the horizontal and vertical page
  612. size in characters and lines (obtained from the
  613. X.B pw
  614. and
  615. X.B pl
  616. printcap entries).
  617. Note that the
  618. X.L "lpr -wNNN"
  619. value will be passed if it has been specified by a user as the
  620. X.B \-w
  621. option value.
  622. The
  623. X.B \-x
  624. and
  625. X.B \-y
  626. options specify the horizontal and vertical page
  627. size in pixels (from the
  628. X.B px
  629. and
  630. X.B py
  631. printcap entries).
  632. The
  633. X.B \-F
  634. X(format)
  635. option specifies the format that this filter is being used for.
  636. X.PP
  637. The above parameters are provided for all filters,
  638. including the OF filter and
  639. BP and EP banner printing filters.
  640. The OF filter must detect the character sequence ESC\ ^A
  641. X(\e031, \e001),
  642. flush its output,
  643. and suspend itself using \fIkill\fP\|(\fIgetpid\fP(),\ SIGSTOP).
  644. The server will then start up other filters,
  645. and use them to print jobs.
  646. After the job has been printed,
  647. the server will signal the OF filter to continue using
  648. SIGCONT.
  649. X.PP
  650. All filters are invoked with the above parameters,
  651. and the additional ones may be provided depending on functionality.
  652. The
  653. X.B \-c
  654. X(literal) flag is optional,
  655. and is specified for literal or
  656. X.B \-l
  657. output being printed using the
  658. X.B IF
  659. filter.
  660. The
  661. X.B \-i
  662. X(indent)
  663. value is optional,
  664. and is the value specified by the
  665. X.B \-i
  666. option of
  667. X.I lpr .
  668. The
  669. X.B \-Z
  670. X(extra parameters) are parameters passed to the filter by the
  671. X.I lpr
  672. X.B \-Z
  673. option.
  674. The
  675. X.B \-C
  676. X(class or priority)
  677. and
  678. X.B \-J
  679. X(job name)
  680. are optional and generated by
  681. X.IR lpr .
  682. The
  683. X.B \-n
  684. and
  685. X.B \-h
  686. parameters specify the login name and host name respectively of the
  687. originator of the job.
  688. X.PP
  689. The last (optional) entry is the name of the
  690. accounting file,
  691. taken from the
  692. X.B af
  693. printcap entry.
  694. This may be a default value,
  695. or specified by the user.
  696. If the accounting file does not exist or is unable to be opened in
  697. append mode,
  698. then accounting action is suppressed.
  699. X.NH 2
  700. Banner Printing Filters
  701. X.PP
  702. The
  703. X.B bp
  704. X(banner printer BP)
  705. and
  706. X.B ep
  707. X(end printer EP)
  708. entries specify a banner and end printing program that is invoked
  709. at the start and end of a job.
  710. The BP and EP filters are invoked with the same parameters as the
  711. IF filter,
  712. and with the
  713. X.B -Ff
  714. format option.
  715. Special flags and parameters for these filters may be specified 
  716. in the printcap entry.
  717. X.PP
  718. The banner printing programs will have
  719. their standard input
  720. X(file descriptor 0) set to
  721. X.L /dev/null ,
  722. standard output
  723. X(file descriptor 1) to the output device,
  724. and standard error
  725. X(file descriptor 2)
  726. to the error logging file.
  727. They must exit with 0 user status for successful completion;
  728. any other value indicates unsuccessful completion and the
  729. and an error reported.
  730. X.NH 2
  731. Accounting Information
  732. X.PP
  733. Accounting information is appended to the accounting file by the
  734. appropriate output filter.
  735. Rather than have a complex binary accounting database,
  736. this version assumes that accounting information will be simple and easy
  737. to maintain and understand.
  738. The
  739. X.I pac
  740. program has been supplied to make accounting information easily managable,
  741. but most accounting procedures can be carried out with a simple
  742. shell script,
  743. and a hearty use of
  744. X.I sort ,
  745. X.I sed ,
  746. and
  747. X.I awk .
  748. In order to keep track of accounting information,
  749. it must be maintained in a consistent manner.
  750. XEntries in the raw accounting file should have the form
  751. illustrated in
  752. XFigure 7.3.
  753. X.KF
  754. X.L
  755. X.SM
  756. X.in +1i
  757. X.nf
  758. host              user printer       format pages date
  759. attila.cs.umn.edu root imagen_lind22 n      5     Fri May 20 21:29:22 CDT 1988
  760. X.R
  761. X.LG
  762. X.in -1i
  763. X.ce
  764. XFigure 7.3 Accounting File Entry
  765. X.KE
  766. X.PP
  767. The host,
  768. user,
  769. printer,
  770. and format
  771. information
  772. can be obtained from the parameters passed to the filter.
  773. The page entry is the number of billable pages.
  774. When the
  775. X.I pac
  776. program produces a summary,
  777. the summary file has the format as in
  778. XFigure 7.4.
  779. X.KF
  780. X.L
  781. X.SM
  782. X.in +1i
  783. X.nf
  784. host              user printer       format pages  jobs
  785. attila.cs.umn.edu root imagen_lind22 n      5      1
  786. attila.cs.umn.edu root imagen_lind22 l      220    7
  787. X.R
  788. X.LG
  789. X.in -1i
  790. X.ce
  791. XFigure 7.4 Summary File Entry
  792. X.KE
  793. X.PP
  794. XExperience has indicated that most sites use a differing approaches
  795. to accounting,
  796. with little requirement commonality.
  797. Thus,
  798. these accounting procedures and information may be
  799. added or modified as required.
  800. Note that the accounting is done by the filter programs,
  801. and not by the PLP software.
  802. X.NH 2
  803. Prefilters
  804. X.PP
  805. The 
  806. X.I lpr 
  807. program can use
  808. X.I prefilters
  809. to process the text before spooling.
  810. The prefilters are invoked with the the following arguments,
  811. which are the same as specified for the output filter.
  812. X.DS
  813. X.DT
  814. X.SM
  815. X.L
  816. filtername arguments \e
  817. X    -Pprinter -wwidth -llength -xwidth -ylength [-c] [-iindent] \e
  818. X    [-Zoptions] [-Cclass] [-Jjob] [-Raccntname] -nlogin -hHost \e
  819. X    -Fformat file [files]
  820. X.R
  821. X.DE
  822. X.PP
  823. The options are specified in exactly the same manner
  824. as for the filter for the specified format.
  825. The file names are either those specified to
  826. X.I lpr
  827. by the user,
  828. or a copy of the input from stdin.
  829. The prefilter must copy these files to stdout,
  830. performing whatever filter functions are neccessary.
  831. X.PP
  832. If successful,
  833. the prefilter should exit with a 0 user status;
  834. anything else will indicate failure and the user job will be discarded.
  835. XErrors written to
  836. X.L stderr
  837. will be directed to the
  838. X.I lpr
  839. X.L stderr
  840. output.
  841. X.NH 2
  842. Adapting Existing Filters and Writing Filters
  843. X.PP
  844. If you have an existing set of filters for the Berkeley LPD
  845. daemon,
  846. you can use the
  847. X.L compat
  848. program supplied with this package to adapt them to use with PLP.
  849. This program invokes an OF, IF,
  850. or other filter with the old Berkeley style of parameters.
  851. XFor example,
  852. the following entry printcap
  853. X.B if
  854. entry will invoke the
  855. X.L imfilter
  856. program to be used as the IF filter.
  857. X.ti +.5i
  858. X.L "if=/usr/local/lib/compat /usr/local/lib/imfilter"
  859. X.PP
  860. If a new filter is needed,
  861. you can start with the 
  862. programs supplied with this distribution,
  863. found in the
  864. X.I filters
  865. directory.
  866. A sample filter would consist of an application independent
  867. X.L main
  868. routine which parses the command line input flags
  869. and calls a user supplied
  870. X.L filter()
  871. function,
  872. and support functions.
  873. These are available in the
  874. X.L filter/main.c
  875. file.
  876. The 
  877. X.I suspend()
  878. support routine
  879. suspends the filter when the appropriate string is detected in the input.
  880. XError message and termination routines are provided.
  881. END_OF_FILE
  882. if test 9734 -ne `wc -c <'doc/PLP/07.t'`; then
  883.     echo shar: \"'doc/PLP/07.t'\" unpacked with wrong size!
  884. fi
  885. # end of 'doc/PLP/07.t'
  886. fi
  887. if test -f 'src/checkpc.c' -a "${1}" != "-c" ; then 
  888.   echo shar: Will not clobber existing file \"'src/checkpc.c'\"
  889. else
  890. echo shar: Extracting \"'src/checkpc.c'\" \(9770 characters\)
  891. sed "s/^X//" >'src/checkpc.c' <<'END_OF_FILE'
  892. X/***************************************************************************
  893. X * U. Minnesota LPD Software * Copyright 1987, 1988, Patrick Powell
  894. X ***************************************************************************
  895. X * MODULE: checkpc.c
  896. X * Check out a print cap,  and create entries
  897. X ***************************************************************************
  898. X * Revision History: Created Tue Mar  1 07:56:38 CST 1988
  899. X * $Log:    checkpc.c,v $
  900. X * Revision 3.1  88/06/18  09:33:56  papowell
  901. X * Version 3.0- Distributed Sat Jun 18 1988
  902. X * 
  903. X * Revision 2.2  88/05/14  10:20:42  papowell
  904. X * Modified -X flag handling
  905. X * 
  906. X * Revision 2.1  88/05/09  10:07:42  papowell
  907. X * PLP: Released Version
  908. X * 
  909. X * Revision 1.6  88/04/15  13:06:27  papowell
  910. X * Std_environ() call added, to ensure that fd 0 (stdin), 1 (stdout), 2(stderr)
  911. X * have valid file descriptors;  if not open, then /dev/null is used.
  912. X * 
  913. X * Revision 1.5  88/04/07  12:30:22  papowell
  914. X * 
  915. X * Revision 1.4  88/03/25  14:59:05  papowell
  916. X * Debugged Version:
  917. X * 1. Added the PLP control file first transfer
  918. X * 2. Checks for MX during file transfers
  919. X * 3. Found and fixed a mysterious bug involving the SYSLOG facilities;
  920. X *     apparently they open files and then assume that they will stay
  921. X *     open.
  922. X * 4. Made sure that stdin, stdout, stderr was available at all times.
  923. X * 
  924. X * Revision 1.3  88/03/12  10:03:28  papowell
  925. X * *** empty log message ***
  926. X * 
  927. X * Revision 1.2  88/03/11  19:28:12  papowell
  928. X * Minor Changes, Updates
  929. X * 
  930. X * Revision 1.1  88/03/01  11:08:16  papowell
  931. X * Initial revision
  932. X * 
  933. X ***************************************************************************/
  934. X#ifndef lint
  935. static char id_str1[] =
  936. X    "$Header: checkpc.c,v 3.1 88/06/18 09:33:56 papowell Exp $ PLP Copyright 1988 Patrick Powell";
  937. X#endif lint
  938. X/*
  939. X * checkpc: check out the entries in the printcap,
  940. X * checking to see that the default files and directories are present
  941. X * or absent as are indicated by the printcap entry.
  942. X *
  943. X * checkpc [-l] [-s] [-a] [-o] [-f] [-Pprinter] [printcapfile]
  944. X * The default is to create all the various files;
  945. X * the following flags are used to disable automatic creation:
  946. X * -l - no log file
  947. X * -s - no status file
  948. X * -o - no output device
  949. X * -a - no accounting file
  950. X * -f - fix, attempt to create with the desired perms
  951. X * -P printer this printer only
  952. X * printcapfile: name of the printcap file to be used; default is /etc/printcap
  953. X */
  954. X
  955. X#include "lp.h"
  956. X
  957. int    noout;            /* no output file */
  958. int    nolog;            /* no log file */
  959. int noout;            /* no output file */
  960. int nostat;            /* no status file */
  961. int noacct;            /* no accounting file */
  962. int fix;            /* fix if bad or missing */
  963. struct passwd *pwent, *getpwnam();    /* password entry */
  964. int DU, DG;
  965. int canchown;        /* can do chown */
  966. X
  967. main( argc, argv )
  968. X    int argc;
  969. X    char **argv;
  970. X{
  971. X    char **prlist;
  972. X    int option;
  973. X
  974. X    /*
  975. X     * Set fd 0, 1, 2 to /dev/null if not open
  976. X     */
  977. X    Std_environ();
  978. X    /*
  979. X     * set umask to avoid problems with user umask
  980. X     */
  981. X    (void)umask(0);
  982. X
  983. X#    ifdef XPERIMENT
  984. X        Setup_test();
  985. X#    endif XPERIMENT
  986. X    /*
  987. X     * set up the pathnames for information files
  988. X     */
  989. X    fprintf( stdout, "before printcap  '%s'\n", Printcap );
  990. X    Tailor_names();
  991. X    fprintf( stdout, "after printcap  '%s'\n", Printcap );
  992. X
  993. X    while ((option = Getopt( argc, argv, "D:afolsXP:" )) != EOF ){
  994. X        switch (option) {
  995. X        case 'D':       /* turn on Debugging */
  996. X            if( Optarg ){
  997. X                Debug = atoi( Optarg );
  998. X            }
  999. X            break;
  1000. X        default:
  1001. X            usage();
  1002. X            break;
  1003. X        case 'a':    /* no acct file */
  1004. X            ++noacct;
  1005. X            break;
  1006. X        case 'f':    /* no acct file */
  1007. X            ++fix;
  1008. X            break;
  1009. X        case 'o':    /* no output file */
  1010. X            ++noout;
  1011. X            break;
  1012. X        case 'l':    /* no log file */
  1013. X            ++nolog;
  1014. X            break;
  1015. X        case 's':    /* no status file */
  1016. X            ++nostat;
  1017. X            break;
  1018. X        case 'X':    /* Test version */
  1019. X#    ifdef DEBUG
  1020. X            Setup_test();
  1021. X            Tailor_names();
  1022. X#    else
  1023. X            usage();
  1024. X#    endif DEBUG
  1025. X            break;
  1026. X        case 'P':    /* printer */
  1027. X            if( Optarg ){
  1028. X                Printer = Optarg;
  1029. X            } else {
  1030. X                usage();
  1031. X            }
  1032. X            break;
  1033. X        }
  1034. X    }
  1035. X    if( Optind < argc ){
  1036. X        (void)strcpy(Printcap, argv[Optind]);
  1037. X        ++Optind;
  1038. X    }
  1039. X    if( Optind < argc ){
  1040. X        usage();
  1041. X    }
  1042. X
  1043. X    canchown = (geteuid() == 0 );
  1044. X
  1045. X    if( canchown == 0 ){
  1046. X        (void)fprintf(stdout, "%s: not running root\n", Name );
  1047. X        (void)fflush(stdout);
  1048. X    }
  1049. X
  1050. X    if((pwent = getpwnam(DAEMON) ) == NULL){
  1051. X        logerr_die( XLOG_DEBUG, "getpwnam failed for daemon" );
  1052. X    }
  1053. X    DU = pwent->pw_uid;
  1054. X    DG = pwent->pw_gid;
  1055. X    (void)fprintf(stdout, "Printcap file: %s\n", Printcap );
  1056. X        (void)fflush(stdout);
  1057. X    if( Printcap[0] != '/' ){
  1058. X        (void)fprintf(stdout, "Printcap file must be absolute path name\n");
  1059. X        (void)fflush(stdout);
  1060. X        exit(1);
  1061. X    }
  1062. X
  1063. X    if( Printer ){
  1064. X        doprinter();
  1065. X    } else {
  1066. X        (void)fprintf(stdout, "Doing all printers\n" );
  1067. X        (void)fflush(stdout);
  1068. X        for(prlist = All_printers(); Printer = *prlist; ++prlist ){
  1069. X            doprinter();
  1070. X        }
  1071. X    }
  1072. X}
  1073. X
  1074. X/*
  1075. X *    doprinter:
  1076. X *    1. get the printcap entry
  1077. X *    2. check the spool direcotry for ownership, etc.
  1078. X *  3. check the log, accounting, and lock file for existence.
  1079. X */
  1080. doprinter()
  1081. X{
  1082. X    if( Get_pc_entry(Printer, All_pc_vars, All_pc_len ) == 0){
  1083. X        (void)fprintf(stdout,"no printer %s", Printer );
  1084. X        (void)fflush(stdout);
  1085. X        return;
  1086. X    }
  1087. X    (void)fprintf(stdout, "checking printer %s: ", Printer );
  1088. X        (void)fflush(stdout);
  1089. X    /*
  1090. X     * check to see if the spool directory exists
  1091. X     */
  1092. X    (void)fprintf(stdout, "SD %s, ",SD);
  1093. X        (void)fflush(stdout);
  1094. X    (void)all_check( 0,S_IFDIR, SD, 0755, "daemon", "daemon" );
  1095. X    if( chdir( SD ) < 0 ){
  1096. X        logerr( XLOG_DEBUG, "cannot chdir to SD" );
  1097. X        return;
  1098. X    }
  1099. X    if( noout == 0 && LP  && *LP ){
  1100. X        (void)fprintf(stdout, "LP %s, ",LP);
  1101. X        (void)fflush(stdout);
  1102. X        (void)all_check( noout,S_IFREG, LP, 0644, "daemon", "daemon" );
  1103. X    }
  1104. X    if( nolog == 0 && LF && *LF ){
  1105. X        (void)fprintf(stdout, "LF %s, ",LF);
  1106. X        (void)fflush(stdout);
  1107. X        (void)all_check( nolog,S_IFREG, LF, 0664, "daemon", "daemon" );
  1108. X    }
  1109. X    if( LO && *LO ){
  1110. X        (void)fprintf(stdout, "LO %s, ",LO);
  1111. X        (void)fflush(stdout);
  1112. X        (void)all_check( 0,S_IFREG, LO, 0644, "daemon", "daemon" );
  1113. X    }
  1114. X    if( noacct || AF == 0 ||  *AF == 0 ){
  1115. X        (void)fprintf(stdout, "no AF, ");
  1116. X            (void)fflush(stdout);
  1117. X    } else {
  1118. X        (void)fprintf(stdout, "AF %s, ",AF);
  1119. X            (void)fflush(stdout);
  1120. X        (void)all_check( noacct,S_IFREG, AF, 0664, "daemon", "daemon" );
  1121. X    }
  1122. X    if( nostat == 0 && ST && *ST ){
  1123. X        (void)fprintf(stdout, "ST %s, ",ST);
  1124. X        (void)fflush(stdout);
  1125. X        (void)all_check( nostat,S_IFREG, ST, 0664, "daemon", "daemon" );
  1126. X    }
  1127. X    if( PS && *PS ){
  1128. X        (void)fprintf(stdout, "PS %s, ",PS);
  1129. X        (void)fflush(stdout);
  1130. X        (void)all_check( nostat,S_IFREG, PS, 0664, "daemon", "daemon" );
  1131. X    }
  1132. X    (void)fprintf(stdout, "\n" );
  1133. X        (void)fflush(stdout);
  1134. X}
  1135. X
  1136. X/*
  1137. X * check and fix if necessary
  1138. X */
  1139. all_check(remove,type,path,perms, owner, group)
  1140. X    int type;    /* S_IFDIR or S_IFREG */
  1141. X    char *path;    /* pathname of thing */
  1142. X    int perms;    /* perms for the file/directory */
  1143. X    char *owner, *group;
  1144. X{
  1145. X    struct stat statbuf;
  1146. X    char cmd[BUFSIZ];
  1147. X    int status;
  1148. X    int ok;
  1149. X
  1150. X    ok = 1;
  1151. X    if( stat( path, &statbuf ) < 0 ){
  1152. X        logerr( XLOG_DEBUG, "%s cannot be stated", path);
  1153. X        if( remove ){
  1154. X            return 1;
  1155. X        }
  1156. X        if( fix ){
  1157. X            fixup( type, path, perms, owner, group );
  1158. X        }
  1159. X        return(0);
  1160. X    }
  1161. X    if( remove ){
  1162. X        (void)fprintf(stdout, "removing %s", path );
  1163. X        (void)fflush(stdout);
  1164. X        (void)sprintf( cmd, "rm -f %s", path );
  1165. X        status = system(cmd);
  1166. X        if(status){
  1167. X            (void)fprintf(stdout, "fix: %s failed, try by hand\n", cmd);
  1168. X        (void)fflush(stdout);
  1169. X            exit(1);
  1170. X        }
  1171. X    }
  1172. X    if( (statbuf.st_mode & type) == 0 ){
  1173. X        (void)fprintf(stdout,"not a %s ",(type==S_IFDIR)?"directory":"file" );
  1174. X        (void)fflush(stdout);
  1175. X        return(0);
  1176. X    }
  1177. X    if( statbuf.st_uid != DU ){
  1178. X        ok = 0;
  1179. X        (void)fprintf(stdout, "not owner '%s' ",owner );
  1180. X        (void)fflush(stdout);
  1181. X        if( fix  && canchown ){
  1182. X            fixup( type, path, perms, owner, group );
  1183. X            return 0;
  1184. X        }
  1185. X    }
  1186. X    if( statbuf.st_gid != DG ){
  1187. X        ok = 0;
  1188. X        (void)fprintf(stdout, "not group '%s' ",group );
  1189. X        (void)fflush(stdout);
  1190. X        if( fix  && canchown ){
  1191. X            fixup( type, path, perms, owner, group );
  1192. X            return 0;
  1193. X        }
  1194. X    }
  1195. X    if( (statbuf.st_mode & 0777) != perms ){
  1196. X        ok = 0;
  1197. X        (void)fprintf(stdout, "perms are %o ", (statbuf.st_mode & 0777) );
  1198. X        (void)fflush(stdout);
  1199. X        if( fix ){
  1200. X            fixup( type, path, perms, owner, group );
  1201. X            return 0;
  1202. X        }
  1203. X    }
  1204. X    putchar( '\n' );
  1205. X    (void)fflush(stdout);
  1206. X    return ( ok );
  1207. X}
  1208. X
  1209. X/*
  1210. X * fixup( type, path, perms, owner, group )
  1211. X * -- try to create the file/directory with the appropriate
  1212. X * permissions
  1213. X */
  1214. fixup( type, path, perms, owner, group )
  1215. X    int type, perms;
  1216. X    char *path, *owner, *group;
  1217. X{
  1218. X    int status;
  1219. X    char cmd[BUFSIZ];
  1220. X    struct stat statbuf;
  1221. X
  1222. X    (void)fprintf(stdout, "trying to fix %s %s\n",(type==S_IFDIR)?"directory":"file",path);
  1223. X        (void)fflush(stdout);
  1224. X    if( type==S_IFDIR ){
  1225. X        (void)sprintf( cmd, "mkdir %s", path );
  1226. X    } else {
  1227. X        (void)sprintf( cmd, "touch %s", path );
  1228. X    }
  1229. X    (void)fprintf(stdout, "fix: %s\n", cmd );
  1230. X        (void)fflush(stdout);
  1231. X    status = system( cmd );
  1232. X    if( stat( path, &statbuf ) < 0 ){
  1233. X        (void)fprintf(stdout, "cannot stat %s, you have to try by hand\n", path );
  1234. X        (void)fflush(stdout);
  1235. X    }
  1236. X    /*
  1237. X     * fix up ownership and perms, you are root
  1238. X     */
  1239. X    if( canchown ){
  1240. X        (void)sprintf(cmd, "chown %s %s", owner, path );
  1241. X        (void)fprintf(stdout, "fix: %s\n", cmd );
  1242. X            (void)fflush(stdout);
  1243. X        status = system( cmd );
  1244. X        if(status){
  1245. X            (void)fprintf(stdout, "fix: %s failed, try by hand\n", cmd);
  1246. X        }
  1247. X        (void)sprintf(cmd, "chgrp %s %s", group, path );
  1248. X        (void)fprintf(stdout, "fix: %s\n", cmd );
  1249. X            (void)fflush(stdout);
  1250. X        status = system( cmd );
  1251. X        if(status){
  1252. X            (void)fprintf(stdout, "fix: %s failed, try by hand\n", cmd);
  1253. X        }
  1254. X    }
  1255. X    (void)sprintf(cmd, "chmod %o %s", perms, path );
  1256. X    (void)fprintf(stdout, "fix: %s\n", cmd );
  1257. X        (void)fflush(stdout);
  1258. X    status = system( cmd );
  1259. X    if(status){
  1260. X        (void)fprintf(stdout, "fix: %s failed, try by hand\n", cmd);
  1261. X    }
  1262. X}
  1263. X
  1264. usage()
  1265. X{
  1266. X    (void)fprintf(stdout,
  1267. X    "use: %s [-aflso][-Pprinter] [printcapfile]", Name);
  1268. X        (void)fflush(stdout);
  1269. X    exit(1);
  1270. X}
  1271. X
  1272. cleanup()
  1273. X{ ; }
  1274. END_OF_FILE
  1275. if test 9770 -ne `wc -c <'src/checkpc.c'`; then
  1276.     echo shar: \"'src/checkpc.c'\" unpacked with wrong size!
  1277. fi
  1278. # end of 'src/checkpc.c'
  1279. fi
  1280. if test -f 'src/remoteprinter.c' -a "${1}" != "-c" ; then 
  1281.   echo shar: Will not clobber existing file \"'src/remoteprinter.c'\"
  1282. else
  1283. echo shar: Extracting \"'src/remoteprinter.c'\" \(9823 characters\)
  1284. sed "s/^X//" >'src/remoteprinter.c' <<'END_OF_FILE'
  1285. X/***************************************************************************
  1286. X * U. Minnesota LPD Software * Copyright 1987, 1988, Patrick Powell
  1287. X ***************************************************************************
  1288. X * MODULE: remoteprinter.c
  1289. X * send a job to a remote Printer
  1290. X ***************************************************************************
  1291. X * Revision History: Creation Fri Jan 15 19:28:22 CST 1988
  1292. X * $Log:    remoteprinter.c,v $
  1293. X * Revision 3.1  88/06/18  09:35:31  papowell
  1294. X * Version 3.0- Distributed Sat Jun 18 1988
  1295. X * 
  1296. X * Revision 2.3  88/05/14  10:18:22  papowell
  1297. X * Use long format for job file names;
  1298. X * Added 'fd', no forward flag;
  1299. X * Control file has to have hostname and origination agree.
  1300. X * 
  1301. X * Revision 2.2  88/05/11  09:52:49  papowell
  1302. X * Remote printer file transfer error fixed.
  1303. X * 
  1304. X * Revision 2.1  88/05/09  10:10:04  papowell
  1305. X * PLP: Released Version
  1306. X * 
  1307. X * Revision 1.4  88/04/06  12:12:35  papowell
  1308. X * Minor updates, changes in error message formats.
  1309. X * Elimination of the AF_UNIX connections, use AF_INET only.
  1310. X * Better error messages.
  1311. X * 
  1312. X * Revision 1.3  88/03/25  15:01:27  papowell
  1313. X * Debugged Version:
  1314. X * 1. Added the PLP control file first transfer
  1315. X * 2. Checks for MX during file transfers
  1316. X * 3. Found and fixed a mysterious bug involving the SYSLOG facilities;
  1317. X *     apparently they open files and then assume that they will stay
  1318. X *     open.
  1319. X * 4. Made sure that stdin, stdout, stderr was available at all times.
  1320. X * 
  1321. X * Revision 1.2  88/03/12  10:03:32  papowell
  1322. X * *** empty log message ***
  1323. X * 
  1324. X * Revision 1.1  88/03/01  11:09:10  papowell
  1325. X * Initial revision
  1326. X * 
  1327. X ***************************************************************************/
  1328. X#ifndef lint
  1329. static char id_str1[] =
  1330. X    "$Header: remoteprinter.c,v 3.1 88/06/18 09:35:31 papowell Exp $ PLP Copyright 1988 Patrick Powell";
  1331. X#endif lint
  1332. X
  1333. X#include "lp.h"
  1334. X
  1335. X/***************************************************************************
  1336. X * int Setup_xfer()
  1337. X * sends the "\02Printer" message to the remote Host
  1338. X * Returns: successful JSUCC, otherwise JFAIL
  1339. X ***************************************************************************/
  1340. int
  1341. Setup_xfer()
  1342. X{
  1343. X    char buf[BUFSIZ];
  1344. X
  1345. X    if( RP == 0 || *RP == 0 ){
  1346. X        fatal(XLOG_INFO, "no RP specified for RM (%s)", RM );
  1347. X    }
  1348. X    (void)sprintf( buf, "%c%s\n",  REQ_RECV, RP );
  1349. X    if(Debug>3)log(XLOG_DEBUG,
  1350. X        "Setup_xfer: request %d, (REQ_RECV) Host '%s' pr '%s'",
  1351. X        REQ_RECV,RM,RP);
  1352. X    if( JSUCC == Link_line( -1, buf )){
  1353. X        if(Debug>3)log(XLOG_DEBUG,"Setup_xfer: request sent");
  1354. X        if( JSUCC == Link_confirm()){
  1355. X            if(Debug>3)log(XLOG_DEBUG,"Setup_xfer: request to %s confirmed",RM);
  1356. X            return(JSUCC);
  1357. X        }
  1358. X        if(Debug>3)log(XLOG_DEBUG,"Setup_xfer: request to %s not confirmed",RM);
  1359. X    } else {
  1360. X        if(Debug>3)log(XLOG_DEBUG,"Setup_xfer: request not sent");
  1361. X    }
  1362. X    setstatus("request for file transfer to %s failed %s", RM, Time_str() );
  1363. X    fatal( XLOG_INFO, "Setup_xfer: cannot start transfer to %s", RM );
  1364. X    /*NOTREACHED*/
  1365. X}
  1366. X
  1367. X/***************************************************************************
  1368. X * Sendjob( FILE *cfp; struct queue *q)
  1369. X *   1.  First scan extracts information which controls printing
  1370. X *            and finds the names of the files to send.
  1371. X *     2.     The data files are then sent.
  1372. X *     3.     Control file is then sent.
  1373. X *   4.  Job files are removed
  1374. X *   5.  Control file is removed
  1375. X * Returns:  JBUSY, JFAIL, JSUCC, JABORT
  1376. X * NOTE: this code was based on a description of the LPD file transfer
  1377. X *    protocol.
  1378. X *
  1379. X * File transfer protocol:
  1380. X * Sender: sends line of form 'flag' length filename
  1381. X * Receiver: acknowledges with 0 (single byte)
  1382. X * Sender: sends file (length bytes of information), then a teminating 0
  1383. X * Receiver: acknowledges with 0 (single byte)
  1384. X *
  1385. X * Tne end is signalled by closing the stream, which results in a read error.
  1386. X * 
  1387. X *************************************************************************/
  1388. Sendjob(cfp, q)
  1389. X    FILE *cfp;            /* control file */
  1390. X    struct queue *q;    /* job entry */
  1391. X{
  1392. X    FILE *fp;                    /* File to send */
  1393. X    char parm[MAXPATHLEN];            /* holds a line read in */
  1394. X    char *arg;                    /* control line argument */
  1395. X    char opt;                    /* control line option */
  1396. X    int  jstatus;                /* job status */
  1397. X    int  i;                        /* ACME Integers, Inc. */
  1398. X
  1399. X    /*
  1400. X     * set job status
  1401. X     */
  1402. X    jstatus = JFAIL;    /* default */
  1403. X
  1404. X    /*
  1405. X     * read the control file and extract user information
  1406. X     */
  1407. X    Parmcount = 0;
  1408. X    while(fgets( parm, sizeof(parm), cfp )){
  1409. X        if( (arg = index(parm, '\n')) == 0 ){
  1410. X            log( XLOG_INFO, "Sendjob: bad control file format (%s), no endline",
  1411. X                q->q_name);
  1412. X            jstatus = JABORT;
  1413. X            goto error;
  1414. X        }
  1415. X        *arg = 0;
  1416. X        opt = parm[0];
  1417. X        arg = parm+1;
  1418. X        if( !isascii(opt) || !isalnum( opt ) || strlen( arg ) > MAXPARMLEN ){
  1419. X            log( XLOG_INFO, "Sendjob: bad control file (%s), line(%s)",
  1420. X                q->q_name,parm);
  1421. X            jstatus = JABORT;
  1422. X            goto error;
  1423. X        }
  1424. X        if( !islower( opt ) && opt != 'U' ){
  1425. X            continue;
  1426. X        }
  1427. X        if( Job_match( q->q_name, arg ) == 0 ){
  1428. X            log( XLOG_INFO, "Sendjob: bad file name format (%s)", arg );
  1429. X            jstatus = JABORT;
  1430. X            goto error;
  1431. X        }
  1432. X        if( islower( opt )){
  1433. X            if( Add_name(arg) < 0 ){
  1434. X                log( XLOG_INFO, "Sendjob: too many files (%s)", arg );
  1435. X                jstatus = JABORT;
  1436. X                goto error;
  1437. X            }
  1438. X        } else {
  1439. X            if( (i = Find_name(arg) ) < 0 ){
  1440. X                log(XLOG_INFO,"Sendjob: job(%s)U specified for '%s' not in job",
  1441. X                    q->q_name,parm);
  1442. X                jstatus = JABORT;
  1443. X                goto error;
  1444. X            }
  1445. X        }
  1446. X    }
  1447. X    /*
  1448. X     * We send the control file first if we are using the PLP protocol
  1449. X     */
  1450. X    if( FJ ){
  1451. X        jstatus = sendfile( cfp, q->q_name, CNAME);
  1452. X        if( jstatus != JSUCC ){
  1453. X            setstatus("transfer %s to %s failed %s",q->q_name,RM,Time_str());
  1454. X            log(XLOG_INFO,"Sendjob: sendname %s to %s failed",q->q_name,RM);
  1455. X            goto error;
  1456. X        }
  1457. X    }
  1458. X    /*
  1459. X     * send the jobs in the file
  1460. X     */
  1461. X    for( i = 0; i < Parmcount; ++i ){
  1462. X        arg = Parms[i].filename;
  1463. X        if( (fp = fopen_daemon( arg, "r" )) == NULL ){
  1464. X            jstatus = JABORT;
  1465. X            logerr( XLOG_INFO,"Sendjob: cannot open data file %s",arg);
  1466. X            goto error;
  1467. X        }
  1468. X        /*
  1469. X         * send the file
  1470. X         */
  1471. X        if(Debug>3)log(XLOG_DEBUG,"Sendjob: sending file %s", arg );
  1472. X        jstatus = sendfile( fp, arg, DFILE );
  1473. X        (void)fclose(fp);
  1474. X        if( jstatus != JSUCC ){
  1475. X            setstatus("transfer %s to %s failed %s",arg,RM,Time_str());
  1476. X            log(XLOG_INFO,"Sendjob: transfer %s to host %s failed",arg,RM);
  1477. X            goto error;
  1478. X        }
  1479. X    }
  1480. X    /*
  1481. X     * send the control file
  1482. X     */
  1483. X    if(Debug>3)log(XLOG_DEBUG,"sending file %s", q->q_name );
  1484. X    if( FJ ){
  1485. X        jstatus = sendname( cfp, q->q_name, CEND );
  1486. X    } else {
  1487. X        jstatus = sendfile( cfp, q->q_name, CFILE );
  1488. X    }
  1489. X    if( jstatus != JSUCC ){
  1490. X        setstatus("transfer %s to %s failed %s",q->q_name,RM,Time_str());
  1491. X        log(XLOG_INFO,"Sendjob: transfer %s to host %s failed",q->q_name,RM);
  1492. X        goto error;
  1493. X    }
  1494. X    /*
  1495. X     * finished!
  1496. X     */
  1497. X    jstatus = JSUCC;
  1498. error:
  1499. X    if( jstatus != JSUCC ){
  1500. X        Link_close();
  1501. X    }
  1502. X    return (jstatus);
  1503. X}
  1504. X
  1505. X/***************************************************************************
  1506. X * sendfile( FILE* fp; char *name; int flag )
  1507. X *   sendfile protocol:
  1508. X * 1. line containing the flag, number of bytes, and file name is sent.
  1509. X *     This has the format:
  1510. X *        "%c%d %s", flag, filesize, name
  1511. X *    DFILE (data file) flag is 03,  a CFILE (control file) flag is 02
  1512. X * 2. the remote end responds by sending back a single 0 character;
  1513. X *    anything else is an error condition and terminates transfer
  1514. X * 3. the file is then copied to the remote end and terminated with 0
  1515. X * 4. if an error is detected, we send a non-zero character
  1516. X *    and close the link.
  1517. X ***************************************************************************/
  1518. X
  1519. sendfile( fp, name, flag )
  1520. X    FILE *fp;
  1521. X    char *name;
  1522. X    int flag;
  1523. X{
  1524. X    int succ;            /* ACME Integer, Inc. */
  1525. X    struct stat statb;    /* status buffer */
  1526. X
  1527. X    /*
  1528. X     * stat the file
  1529. X     */
  1530. X    if( fstat( fileno(fp), &statb) < 0 ){
  1531. X        logerr( XLOG_INFO, "sendname: could not stat %s", name );
  1532. X        return( JFAIL );
  1533. X    }
  1534. X    /*
  1535. X     * rewind the file
  1536. X     */
  1537. X    if( fseek(fp, 0L, 0) < 0 ){
  1538. X        logerr_die( XLOG_INFO, "sendfile: fseek failed '%s'", name );
  1539. X    }
  1540. X    succ = sendname( fp, name, flag );
  1541. X    if( succ == JSUCC ){
  1542. X        succ = Link_copy( fp, (long)statb.st_size, name );
  1543. X    }
  1544. X    if( succ == JSUCC ){
  1545. X        succ = Link_ack( 0 );
  1546. X    }
  1547. X    if( succ == JSUCC ){
  1548. X        succ = Link_confirm();
  1549. X    }
  1550. X    if( succ != JSUCC ){
  1551. X        succ = JFAIL;
  1552. X        Link_close();
  1553. X    }
  1554. X    return( succ );
  1555. X}
  1556. X
  1557. X/***************************************************************************
  1558. X * Send_error()
  1559. X * Called when you have retried a couple of times; bad job, needs attention
  1560. X ***************************************************************************/
  1561. void
  1562. Send_error()
  1563. X{
  1564. X    log(XLOG_CRIT, "job cannot be sent from %s to %s", Host, RM );
  1565. X    exit( 0 );
  1566. X}
  1567. X
  1568. X/***************************************************************************
  1569. X * sendname( FILE *fp; char *name; int flag )
  1570. X *   sendname protocol:
  1571. X * 1. line containing the flag and file name is sent
  1572. X *     This has the format:
  1573. X *        "%c%d %s", flag, filesize, name
  1574. X *    DFILE (data file) flag is 03,  a CFILE (control file) flag is 02
  1575. X * 2. the remote end responds by sending back a single 0 character;
  1576. X *    anything else is an error condition and terminates transfer
  1577. X ***************************************************************************/
  1578. sendname( fp, name, flag )
  1579. X    FILE *fp;
  1580. X    char *name;
  1581. X    int flag;
  1582. X{
  1583. X    struct stat statb;    /* status buffer */
  1584. X    int succ;            /* ACME Integer, Inc. */
  1585. X    char buf[BUFSIZ];
  1586. X
  1587. X    /*
  1588. X     * stat the file
  1589. X     */
  1590. X    if( fstat( fileno(fp), &statb) < 0 ){
  1591. X        logerr( XLOG_INFO, "sendfile: could not stat %s", name );
  1592. X        return( JFAIL );
  1593. X    }
  1594. X    (void)sprintf( buf, "%c%d %s\n", flag, statb.st_size, name);
  1595. X    succ = Link_send( buf );
  1596. X    if( succ == JSUCC ){
  1597. X        succ = Link_confirm();
  1598. X    }
  1599. X    return( succ );
  1600. X}
  1601. X
  1602. X/***************************************************************************
  1603. X * Allsent( )
  1604. X *    all files have been sent; send a closing 0 and shut down link
  1605. X ***************************************************************************/
  1606. void
  1607. Allsent()
  1608. X{
  1609. X    (void)Link_ack( 0 );
  1610. X    Link_close();
  1611. X}
  1612. END_OF_FILE
  1613. if test 9823 -ne `wc -c <'src/remoteprinter.c'`; then
  1614.     echo shar: \"'src/remoteprinter.c'\" unpacked with wrong size!
  1615. fi
  1616. # end of 'src/remoteprinter.c'
  1617. fi
  1618. if test -f 'src/startprinter.c' -a "${1}" != "-c" ; then 
  1619.   echo shar: Will not clobber existing file \"'src/startprinter.c'\"
  1620. else
  1621. echo shar: Extracting \"'src/startprinter.c'\" \(10002 characters\)
  1622. sed "s/^X//" >'src/startprinter.c' <<'END_OF_FILE'
  1623. X/***************************************************************************
  1624. X * U. Minnesota LPD Software * Copyright 1987, 1988, Patrick Powell
  1625. X ***************************************************************************
  1626. X * MODULE: Startprinter.c
  1627. X * Printer queue job handler
  1628. X * 
  1629. X * StartPrinter is responsible for handling the Printer queue.
  1630. X * 1.  Get the printcap entry.
  1631. X * 2.  Check the spool directory to see if printing is enabled
  1632. X * 3.  Check to see if there are any jobs
  1633. X * 4.  If a remote Printer, call remotePrinter()
  1634. X *     If a local Printer, call localPrinter()
  1635. X ***************************************************************************
  1636. X * Revision History: Created Sat Feb 13 09:11:38 CST 1988
  1637. X * $Log:    startprinter.c,v $
  1638. X * Revision 3.1  88/06/18  09:35:49  papowell
  1639. X * Version 3.0- Distributed Sat Jun 18 1988
  1640. X * 
  1641. X * Revision 2.4  88/05/21  10:28:30  papowell
  1642. X * Minor editing
  1643. X * 
  1644. X * Revision 2.3  88/05/14  10:18:27  papowell
  1645. X * Use long format for job file names;
  1646. X * Added 'fd', no forward flag;
  1647. X * Control file has to have hostname and origination agree.
  1648. X * 
  1649. X * Revision 2.2  88/05/11  09:50:52  papowell
  1650. X * Remote printer file transfer error fixed.
  1651. X * 
  1652. X * Revision 2.1  88/05/09  10:10:30  papowell
  1653. X * PLP: Released Version
  1654. X * 
  1655. X * Revision 1.6  88/04/27  18:02:36  papowell
  1656. X * The SIGCHLD signal has an odd behaviour on some systems.  Modified so that
  1657. X * it will not get set UNLESS processes are started;  also,  it is reset
  1658. X * to SIG_DFL, not SIG_IGN.
  1659. X * 
  1660. X * Revision 1.5  88/04/07  21:24:27  papowell
  1661. X * changed calls of init to (*init)().  Sigh.
  1662. X * 
  1663. X * Revision 1.4  88/04/06  12:13:05  papowell
  1664. X * Minor updates, changes in error message formats.
  1665. X * Elimination of the AF_UNIX connections, use AF_INET only.
  1666. X * Better error messages.
  1667. X * 
  1668. X * Revision 1.3  88/03/25  15:01:47  papowell
  1669. X * Debugged Version:
  1670. X * 1. Added the PLP control file first transfer
  1671. X * 2. Checks for MX during file transfers
  1672. X * 3. Found and fixed a mysterious bug involving the SYSLOG facilities;
  1673. X *     apparently they open files and then assume that they will stay
  1674. X *     open.
  1675. X * 4. Made sure that stdin, stdout, stderr was available at all times.
  1676. X * 
  1677. X * Revision 1.2  88/03/11  19:29:20  papowell
  1678. X * Minor Changes, Updates
  1679. X * 
  1680. X * Revision 1.1  88/03/01  11:09:24  papowell
  1681. X * Initial revision
  1682. X * 
  1683. X ***************************************************************************/
  1684. X#ifndef lint
  1685. static char id_str1[] =
  1686. X    "$Header: startprinter.c,v 3.1 88/06/18 09:35:49 papowell Exp $ PLP Copyright 1988 Patrick Powell";
  1687. X#endif lint
  1688. X
  1689. X#include "lp.h"
  1690. extern int Printjob(), Sendjob();
  1691. extern int Printinit(), Setup_xfer();
  1692. extern void Printfinal(), Printerror(), Allsent(), Send_error();
  1693. X
  1694. Startprinter()
  1695. X{
  1696. X    int pid;                /* process id */
  1697. X    char *ps, *st;            /* ACME Pointers */
  1698. X
  1699. X    /*
  1700. X     * ignore SIGCHILD,  explicitly wait for them
  1701. X     */
  1702. X    (void)signal(SIGCHLD, SIG_DFL);
  1703. X    /*
  1704. X     * get the printcap entry
  1705. X     */
  1706. X    if( Get_pc_entry(Printer, All_pc_vars, All_pc_len ) == 0){
  1707. X        log( XLOG_INFO, "trying to start non-existent Printer" );
  1708. X        exit(0);
  1709. X    }
  1710. X    if( SS && *SS ){
  1711. X        /*
  1712. X         * we have a spool server that is to be started
  1713. X         */
  1714. X        ps = PS;
  1715. X        st = ST;
  1716. X        if( Set_pc_entry(SS, All_pc_vars, All_pc_len ) == 0){
  1717. X            log( XLOG_INFO, "queue %s does not entry", SS );
  1718. X            exit(0);
  1719. X        }
  1720. X        PS = ps;
  1721. X        ST = st;
  1722. X        LO = Printer;
  1723. X        SV = 0;
  1724. X    }
  1725. X    if( SD == 0 || *SD == 0 ){
  1726. X        /*
  1727. X         * no spooling directory, not a Printer
  1728. X         */
  1729. X        if(Debug>0)log(XLOG_DEBUG, "Startprinter: not a Printer");
  1730. X        exit(0);
  1731. X    }
  1732. X    if( RM && NW ){
  1733. X        (void)Remote_start();
  1734. X        exit(0);
  1735. X    }
  1736. X    /* chdir to spool directory */
  1737. X    if (chdir(SD) < 0) {
  1738. X        logerr_die( XLOG_NOTICE,"Startprinter: cannot chdir to %s", SD);
  1739. X    }
  1740. X    /*
  1741. X     * check to see if there is a deamon running
  1742. X     */
  1743. X    Lfd = Getlockfile( LO, &pid, (char *)0, 0, &LO_statb );
  1744. X    if( Lfd == NULL ){
  1745. X        if(Debug>2)log(XLOG_DEBUG, "Startprinter: server present, pid %u",pid);
  1746. X        exit(0);
  1747. X    }
  1748. X    if( fseek( Lfd, 0L, 0 ) < 0 ){
  1749. X        logerr_die( XLOG_INFO, "Startprinter: T1 fseek failed");
  1750. X    }
  1751. X    /*
  1752. X     * check for unspooling enabled
  1753. X     */
  1754. X    if( LO_statb.st_mode & DISABLE_PRINT) {
  1755. X        if(Debug>0)log( XLOG_DEBUG,"Startprinter: unspooling disabled");
  1756. X        exit(0);
  1757. X    }
  1758. X    /*
  1759. X     * handle multiple servers
  1760. X     */
  1761. X    if( SV && *SV ){
  1762. X        Closelockfile(LO, Lfd );
  1763. X        Lfd = 0;
  1764. X        Start_server();
  1765. X        /*
  1766. X         * Check on the status of the queue lock file
  1767. X         */
  1768. X        Lfd = Getlockfile( LO, &pid, (char *)0, 0, &LO_statb );
  1769. X        if( Lfd == NULL ){
  1770. X            if(Debug>2)log(XLOG_DEBUG, "Startprinter: server present, pid %u",pid);
  1771. X            exit(0);
  1772. X        }
  1773. X    }
  1774. X    /*
  1775. X     * set up log file
  1776. X     */
  1777. X    if( fseek( Lfd, 0L, 0 ) < 0 ){
  1778. X        logerr_die( XLOG_INFO, "Startprinter: T2 fseek failed");
  1779. X    }
  1780. X    if(Debug>0)log(XLOG_DEBUG, "Startprinter: should log into %s",
  1781. X        LF?LF:"/dev/null");
  1782. X    Setuplog( LF, 0 );
  1783. X    if( fseek( Lfd, 0L, 0 ) < 0 ){
  1784. X        logerr_die( XLOG_INFO, "Startprinter: T3 fseek failed");
  1785. X    }
  1786. X    /*
  1787. X     * OK, you are the server, go to it.
  1788. X     * set process group to the queue handler process
  1789. X     */
  1790. X    (void) setpgrp(0, getpid());
  1791. X
  1792. X    Setlockfile( LO, Lfd, getpid(), "(checking queue)");
  1793. X    setstatus( "checking queue at %s", Time_str());
  1794. X
  1795. X    /*
  1796. X     * search the spool directory for work and sort by queue order.
  1797. X     */
  1798. X    if(Debug>0)log(XLOG_DEBUG, "Startprinter: unqueueing jobs");
  1799. X    if( RM ){
  1800. X        unspool(Setup_xfer, Sendjob, Allsent, Send_error);
  1801. X    } else {
  1802. X        unspool(Printinit, Printjob, Printfinal,Printerror);
  1803. X    }
  1804. X    if(Debug>2)log( XLOG_DEBUG, "Startprinter: work done" );
  1805. X    setstatus( "work done at %s", Time_str() );
  1806. X    Closelockfile(LO,Lfd);
  1807. X    exit( 0 );
  1808. X}
  1809. X
  1810. X
  1811. X/***********************************************************
  1812. X * unspool( init, jobhandler, closer)
  1813. X * 
  1814. X * do{
  1815. X *   check queue for new jobs
  1816. X *   jobdone = 0
  1817. X *   for(n = 0;n < Jobcount; ++n)
  1818. X *      if queue needs to be resorted then
  1819. X *         set jobdone and break from "for" loop;
  1820. X *      while not successful and retry count is less than a limit do
  1821. X *         init();
  1822. X *         success = jobhandler(job n);
  1823. X *     -- note: job can be busy (no action), done successfully,
  1824. X *              done unsuccessfully and should be abandoned,
  1825. X *              or done unsuccessfully and should be repeated
  1826. X *      if action was done then set jobdone and remove job
  1827. X *          else call closer();
  1828. X * }while( jobdone )
  1829. X * call closer()
  1830. X ***********************************************************/
  1831. X
  1832. unspool( init, dojob, closer, err )
  1833. X    int (*init)();
  1834. X    int (*dojob)();
  1835. X    void (*closer)();
  1836. X    void (*err)();
  1837. X{
  1838. X    int n;                /* job number */
  1839. X    int retries;        /* number of retries */
  1840. X    int success;        /* job success status */
  1841. X    struct queue *q;    /* job entry  */
  1842. X    int jobdone;        /* job done in this pass */
  1843. X    FILE *cfp;            /* control file */
  1844. X    int init_done;    /* initialization done */
  1845. X
  1846. X    /*
  1847. X     * the big loop
  1848. X     */
  1849. X    init_done = 0;
  1850. X    do{
  1851. X        /*
  1852. X         * search the spool directory for more work.
  1853. X         */
  1854. X        Jobcount = Getq();
  1855. X        /*
  1856. X         * reset "update queue order" flag
  1857. X         */
  1858. X        if(fstat(fileno(Lfd), &LO_statb ) < 0 ){
  1859. X            logerr_die( XLOG_NOTICE,"unspool: cannot stat %s", LO);
  1860. X        }
  1861. X        if(Debug>5)log(XLOG_DEBUG,"unspool: '%s' perms 0%o",LO,
  1862. X            LO_statb.st_mode);
  1863. X        if(fchmod(fileno(Lfd), (int)(LO_statb.st_mode & CLEAR_REQUE)) < 0){
  1864. X            logerr_die( XLOG_NOTICE,"unspool: cannot chmod '%s'", LO);
  1865. X        }
  1866. X        jobdone = 0;
  1867. X        /*
  1868. X         * scan the queue
  1869. X         */
  1870. X        for(n=0; n < Jobcount; ++n ){
  1871. X            q = &Queue[n];
  1872. X            /*
  1873. X             * lock the control file
  1874. X             */
  1875. X            if( (cfp = Lockcf(q->q_name) )!= NULL ){
  1876. X                Setlockfile( LO, Lfd, getpid(), q->q_name );
  1877. X                /*
  1878. X                 * try printing this file until successful,
  1879. X                 *  number of attempts exceeds limit, or abort
  1880. X                 * try sending indefinately until successful
  1881. X                 */
  1882. X                success = JFAIL;
  1883. X                for( retries = 0;
  1884. X                    success == JFAIL && retries <= RT;
  1885. X                    ++retries ){
  1886. X                    /*
  1887. X                     * STDIO file error reset, needed on some implementations
  1888. X                     */
  1889. X                    clearerr( cfp );
  1890. X                    /*
  1891. X                     * seek to the start of the file
  1892. X                     */
  1893. X                    if( fseek( cfp, 0L, 0 ) < 0 ){
  1894. X                        logerr_die(XLOG_INFO,"unspool: fseek failed (%s)",
  1895. X                            q->q_name );
  1896. X                    }
  1897. X                    /*
  1898. X                     * update status information
  1899. X                     */
  1900. X                    if(Debug)log(XLOG_DEBUG,"unspool: doing %s, %d retry",
  1901. X                        q->q_name,retries);
  1902. X                    /*
  1903. X                     * initialize
  1904. X                     */
  1905. X                    if( init_done == 0 ){
  1906. X                        init_done = (*init)();
  1907. X                        if( init_done != JSUCC ){
  1908. X                            setstatus( "initialization failure, %s",Last_errormsg);
  1909. X                            return;
  1910. X                        }
  1911. X                    }
  1912. X                    setstatus( "processing, active job started %s, attempt %d",
  1913. X                        Time_str(), retries+1);
  1914. X                    /*
  1915. X                     * try to print the job
  1916. X                     */
  1917. X                    success = (*dojob)(cfp, q);
  1918. X                }
  1919. X                if(Debug>4)log(XLOG_DEBUG,"unspool: %s status %d", q->q_name,
  1920. X                    success );
  1921. X                if( success == JFAIL ){
  1922. X                    (*err)();
  1923. X                    init_done = 0;
  1924. X                }
  1925. X                jobdone = 1;
  1926. X                Remove_job( cfp, q );
  1927. X                (void)fclose(cfp);
  1928. X            }
  1929. X            /*
  1930. X             * collect any garbage
  1931. X             */
  1932. X            Reapchild();
  1933. X        }
  1934. X        /*
  1935. X         * collect any garbage
  1936. X         */
  1937. X        Reapchild();
  1938. X    } while( jobdone );
  1939. X    /*
  1940. X     * collect any garbage
  1941. X     */
  1942. X    Reapchild();
  1943. X    /*
  1944. X     * queue finished
  1945. X     */
  1946. X    if(Debug>0)log(XLOG_DEBUG, "unspool: no more work to do" );
  1947. X    (*closer)();
  1948. X}
  1949. X
  1950. X/***************************************************************************
  1951. X * Start_server()
  1952. X * start multiple servers for a single queue.  The SV printcap parameter
  1953. X * has a list of the servers.  These servers use the spool queues
  1954. X * directory,  and have a lock file in the server directory.
  1955. X * This routine will extract the names of each server,  fork a process
  1956. X * for it,  and then will read the printcap information for the server
  1957. X * from the queue.
  1958. X * The printer names are separated by commas.
  1959. X ***************************************************************************/
  1960. X
  1961. Start_server()
  1962. X{
  1963. X    char *ps;
  1964. X    char *last;
  1965. X    int pid;
  1966. X    
  1967. X    last = 0;
  1968. X    ps = SV;
  1969. X    while( ps ){
  1970. X        Printer = ps;
  1971. X        if( last = index( ps, ',' ) ){
  1972. X            *last = 0;
  1973. X            ps = last+1;
  1974. X        } else {
  1975. X            ps = 0;
  1976. X        }
  1977. X        if( ps ){
  1978. X            if( (pid = fork()) < 0 ){
  1979. X                logerr_die( XLOG_INFO, "Start_server: fork failed" );
  1980. X            } else if( pid == 0 ){
  1981. X                ps = 0;
  1982. X            }
  1983. X        }
  1984. X    }
  1985. X    if( Set_pc_entry(Printer, All_pc_vars, All_pc_len ) == 0){
  1986. X        fatal( XLOG_INFO, "trying to start non-existent server" );
  1987. X    }
  1988. X    LO = Printer;
  1989. X    if(Debug>3)log(XLOG_DEBUG,"Start_server: started" );
  1990. X}
  1991. END_OF_FILE
  1992. if test 10002 -ne `wc -c <'src/startprinter.c'`; then
  1993.     echo shar: \"'src/startprinter.c'\" unpacked with wrong size!
  1994. fi
  1995. # end of 'src/startprinter.c'
  1996. fi
  1997. echo shar: End of archive 7 \(of 16\).
  1998. cp /dev/null ark7isdone
  1999. MISSING=""
  2000. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ; do
  2001.     if test ! -f ark${I}isdone ; then
  2002.     MISSING="${MISSING} ${I}"
  2003.     fi
  2004. done
  2005. if test "${MISSING}" = "" ; then
  2006.     echo You have unpacked all 16 archives.
  2007.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2008. else
  2009.     echo You still need to unpack the following archives:
  2010.     echo "        " ${MISSING}
  2011. fi
  2012. ##  End of shell archive.
  2013. exit 0
  2014.  
  2015.