home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume16 / plp / part13 < prev    next >
Encoding:
Internet Message Format  |  1988-09-14  |  38.3 KB

  1. Subject:  v16i026:  Public lineprinter spooler package, Part13/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 26
  8. Archive-name: plp/part13
  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 13 (of 16)."
  17. # Contents:  src/print_support.c src/recvfiles.c
  18. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  19. if test -f 'src/print_support.c' -a "${1}" != "-c" ; then 
  20.   echo shar: Will not clobber existing file \"'src/print_support.c'\"
  21. else
  22. echo shar: Extracting \"'src/print_support.c'\" \(17575 characters\)
  23. sed "s/^X//" >'src/print_support.c' <<'END_OF_FILE'
  24. X/***************************************************************************
  25. X * U. Minnesota LPD Software * Copyright 1987, 1988, Patrick Powell
  26. X ***************************************************************************
  27. X * MODULE: Print_support.c
  28. X * handle the actual output to the Printer
  29. X ***************************************************************************
  30. X * Revision History: Created Wed Jan 13 16:21:39 CST 1988
  31. X * $Log:    print_support.c,v $
  32. X * Revision 3.1  88/06/18  09:35:18  papowell
  33. X * Version 3.0- Distributed Sat Jun 18 1988
  34. X * 
  35. X * Revision 2.4  88/05/27  08:28:01  papowell
  36. X * Added a SIGCONT to start up the output filter.
  37. X * 
  38. X * Revision 2.3  88/05/19  10:34:19  papowell
  39. X * Fixed open() calls to have a 0 parameter, ie: open(f, perms, 0), where needed
  40. X * 
  41. X * Revision 2.2  88/05/14  10:21:16  papowell
  42. X * Modified -X flag handling
  43. X * 
  44. X * Revision 2.1  88/05/09  10:09:44  papowell
  45. X * PLP: Released Version
  46. X * 
  47. X * Revision 1.4  88/03/25  15:01:04  papowell
  48. X * Debugged Version:
  49. X * 1. Added the PLP control file first transfer
  50. X * 2. Checks for MX during file transfers
  51. X * 3. Found and fixed a mysterious bug involving the SYSLOG facilities;
  52. X *     apparently they open files and then assume that they will stay
  53. X *     open.
  54. X * 4. Made sure that stdin, stdout, stderr was available at all times.
  55. X * 
  56. X * Revision 1.3  88/03/11  19:29:04  papowell
  57. X * Minor Changes, Updates
  58. X * 
  59. X * Revision 1.2  88/03/05  15:01:11  papowell
  60. X * Minor Corrections,  Lint Problems
  61. X * 
  62. X * Revision 1.1  88/03/01  11:09:01  papowell
  63. X * Initial revision
  64. X * 
  65. X ***************************************************************************
  66. X * void Print_open(): opens the Printer
  67. X * static int Print_of_fd(): makes an 'of' filter if needed
  68. X * void Print_close(): closes the Printer
  69. X * int Print_ready(): combines Print_open() and Print_of_fd()
  70. X * static int of_stop(): stops the 'of' filter
  71. X * int Print_string( str ): prints a string through 'of' or to Printer
  72. X * int Print_copy( fd ): copies a file through 'of' or to Printer
  73. X * int Print_filter( file, cmd ): makes a filter and copies file
  74. X * int Print_banner(): prints a banner through 'of' or to Printer
  75. X * Note: the above procedures which return values return JSUCC on success,
  76. X *   and JFAIL or JABORT on failure
  77. X ***************************************************************************/
  78. X
  79. X#ifndef lint
  80. static char id_str1[] =
  81. X    "$Header: print_support.c,v 3.1 88/06/18 09:35:18 papowell Exp $ PLP Copyright 1988 Patrick Powell";
  82. X#endif lint
  83. X
  84. X#include "lp.h"
  85. X
  86. X/***************************************************************************
  87. X * Print_open()
  88. X *     Open the Printer, and set the Print_fd variables
  89. X *     If the RW printcap flag is set, output is opened RW, otherwise
  90. X *     opened writeonly in append mode.
  91. X * 
  92. X *     If the Printer is a tty (i.e.- isatty returns non-zero),
  93. X *     then the baud rate is set.  The baud rate table is stolen from
  94. X *     the original LPD code, which stole it from STTY, etc.
  95. X * Side Effect:
  96. X *     sets the Print_fd variable to a non-zero value
  97. X *  terminates if Printer is unable to be opened
  98. X ****************************************************************************/
  99. struct bauds {
  100. X    char *string;
  101. X    int    baud;
  102. X    int    speed;
  103. X} bauds[] = {
  104. X    "110", 110,    B110,
  105. X    "134", 134,    B134,
  106. X    "150", 150,    B150,
  107. X    "300", 300,    B300,
  108. X    "600", 600,    B600,
  109. X    "1200", 1200,    B1200,
  110. X    "1800", 1800,    B1800,
  111. X    "2400", 2400,    B2400,
  112. X    "4800", 4800,    B4800,
  113. X    "9600", 9600,    B9600,
  114. X    "19200", 19200,    B19200,
  115. X    "38400", 38400,    B38400,
  116. X    (char *)0, 0,    0
  117. X};
  118. X
  119. static int of_pid;        /* OF process pid */
  120. static int of_fd;        /* pipe to OF process */
  121. static int of_running;    /* of filter running */
  122. static char filter_stop[] = "\031\001";    /* what to send filter */
  123. X
  124. Print_open()
  125. X{
  126. X    int err;
  127. X
  128. X    /*
  129. X     * check to see if it is open
  130. X     */
  131. X    if( Print_fd ){
  132. X        return;
  133. X    }
  134. X    if( LP == 0 || *LP == 0 ){
  135. X        fatal( XLOG_INFO, "Missing LP value for local Printer");
  136. X    }
  137. X    setstatus("waiting for %s to become ready since %s (offline?)",
  138. X        Printer, Time_str());
  139. X    Print_fd = open(LP, RW ? ( O_RDWR|O_APPEND ) : ( O_WRONLY|O_APPEND ), 0);
  140. X    if( Print_fd < 0 ){
  141. X        err = errno;
  142. X        setstatus("Print_open: '%s' open(%s) failed, %s",Printer,LP,
  143. X            Errormsg(err));
  144. X        errno = err;
  145. X        logerr_die( XLOG_INFO, "Print_open: cannot open %s", LP);
  146. X    } else if( Print_fd == 0 ){
  147. X        fatal( XLOG_INFO, "Print_open: cannot happen- Print_fd == 0");
  148. X    }
  149. X    /*
  150. X     * if it is a tty, set the baud rates and control information
  151. X     */
  152. X    if (isatty(Print_fd)){
  153. X        Do_stty(Print_fd);
  154. X    }
  155. X    if(Debug>3)log(XLOG_DEBUG,"Print_open: %s is fd %d", LP, Print_fd );
  156. X}
  157. X
  158. X/*
  159. X * Start up an output filter, if needed.
  160. X */
  161. Print_of_fd()
  162. X{
  163. X    int p[2];
  164. X    char *cmd;
  165. X
  166. X    if( OF == 0 || *OF == 0 || of_pid ){
  167. X        return;
  168. X    }
  169. X    /*
  170. X     * set OF command line
  171. X     */
  172. X    cmd = Setup_filter('o',OF);
  173. X    if( cmd == 0 || *cmd == 0 ){
  174. X        fatal(XLOG_INFO, "bad OF entry");
  175. X    }
  176. X    if(Debug>2)log( XLOG_DEBUG, "starting OF, '%s'", cmd);
  177. X    /*
  178. X     * create pipe and fork
  179. X     */
  180. X    if( pipe(p) < 0 ){
  181. X        logerr_die( XLOG_NOTICE, "Print_of_of: pipe failed" );
  182. X    }
  183. X    if( p[0] < 3 || p[1] < 3 ){
  184. X        fatal( XLOG_INFO, "Print_of_fd: IMPOSSIBLE- pipe fd %d %d", p[0], p[1]);
  185. X    }
  186. X    if ((of_pid = fork()) == 0) {    /* child */
  187. X        if( dup2(p[0], 0) < 0        /* pipe is std in */
  188. X         || dup2(Print_fd, 1) < 0 ){        /* Printer is std out */
  189. X            logerr_die( XLOG_NOTICE, "Print_of_fd: dup2 failed" );
  190. X        }
  191. X        if(Debug>3)log( XLOG_DEBUG, "Print_of_fd: forked %d OF: %s",
  192. X            getpid(), cmd );
  193. X        if( geteuid() == 0 && setreuid( Daemon_uid, Daemon_uid ) < 0 ){
  194. X            logerr_die( XLOG_NOTICE, "Print_of_fd: setreuid failed" );
  195. X        }
  196. X        mexecv( cmd );
  197. X        logerr_die( XLOG_NOTICE,"Print_of_fd: execv failed %s", cmd);
  198. X    } else if( of_pid < 0 ){
  199. X        logerr_die( XLOG_NOTICE, "Print_of_fd: fork failed" );
  200. X    }
  201. X    (void)close(p[0]);        /* close input side */
  202. X    of_fd = p[1];
  203. X    of_running = of_pid;
  204. X    if(Debug>3)log(XLOG_DEBUG,"started OF process %d, fd %d", of_pid, of_fd);
  205. X}
  206. X
  207. X/***************************************************************************
  208. X * Print_close()
  209. X * 1. Close the pipes and outputs.
  210. X * 2. Signal the of process that it is to do something.
  211. X *    Note that there is a Reapchild() call that will collect the
  212. X *    children;  this will make sure that there is a minimal number of
  213. X *    outstanding processes active.
  214. X ***************************************************************************/
  215. X
  216. void
  217. Print_close()
  218. X{
  219. X    if( of_fd ){
  220. X        (void)close(of_fd);
  221. X        of_fd = 0;
  222. X    }
  223. X    if( Print_fd ){
  224. X        (void)close(Print_fd);    /* close Printer */
  225. X        Print_fd = 0;
  226. X    }
  227. X    /*
  228. X     * when you kill the printer, make sure that you do it neatly
  229. X     */
  230. X    if( of_pid ){
  231. X        (void)kill(of_pid, SIGCONT);
  232. X    }
  233. X    of_pid = 0;
  234. X}
  235. X
  236. X/***************************************************************************
  237. X * Print_ready()
  238. X * 1. open the Printer if neccessary
  239. X * 2. start up the output filter
  240. X * 3. if the filter has been stopped, start it
  241. X * Return: JSUCC if started, JFAIL if not
  242. X ***************************************************************************/
  243. Print_ready()
  244. X{
  245. X    /*
  246. X     * open the Printer
  247. X     */
  248. X    Print_open();
  249. X    Print_of_fd();
  250. X    if( of_pid && of_running == 0 ){
  251. X        if (kill(of_pid, SIGCONT) < 0) {
  252. X            logerr( XLOG_INFO,"cannot restart output filter");
  253. X            Print_close();
  254. X            return( JFAIL );
  255. X        }
  256. X        of_running = of_pid;
  257. X    }
  258. X    return( JSUCC );
  259. X}
  260. X
  261. X/***************************************************************************
  262. X * of_stop()
  263. X * stop the output filter if neccessary
  264. X * 1. open and create the filter
  265. X * 2. flush output
  266. X * 3. kill(SIGSTOP) it
  267. X * Return: JSUCC if stopped, JFAIL if not
  268. X ***************************************************************************/
  269. X
  270. int
  271. of_stop()
  272. X{
  273. X    union wait statb;
  274. X    int pid;
  275. X
  276. X    Print_open();
  277. X    Print_of_fd();
  278. X    /*
  279. X     * stop the OF filter
  280. X     */
  281. X    if( of_pid && of_running ){
  282. X        if(Debug>3)log( XLOG_DEBUG, "stopping output filter" );
  283. X        if( write( of_fd, filter_stop, strlen(filter_stop))
  284. X            != strlen(filter_stop) ){
  285. X            logerr( XLOG_NOTICE,"of_stop: cannot write to OF");
  286. X            Print_close();
  287. X            return( JFAIL );
  288. X        }
  289. X        /*
  290. X         * wait until OF blocks
  291. X         */
  292. X        if(Debug>3)log( XLOG_DEBUG, "of_stop: waiting for OF %d", of_pid );
  293. X        while ((pid = wait3(&statb,WUNTRACED,(struct rusage *)0)) != -1
  294. X            && pid != of_pid) ;
  295. X        if( pid < 0 || statb.w_stopval != WSTOPPED ){
  296. X            logerr( XLOG_INFO, "of_stop: OF %d died (%s)", of_pid,
  297. X                Decode_status( &statb ) );
  298. X            Print_close();
  299. X            return( JFAIL );
  300. X        }
  301. X        if(Debug>3)log( XLOG_DEBUG, "of_stop: output filter stopped" );
  302. X        of_running = 0;
  303. X    }
  304. X    return( JSUCC );
  305. X}
  306. X
  307. X/***************************************************************************
  308. X * Print_string( char *str )
  309. X * print a string through a filter 
  310. X * 1. Enable the line Printer
  311. X * 2. get the filter or device fd;
  312. X * 3. put out the string
  313. X * 4. if unsuccessful, close the Printer
  314. X * Return: JSUCC if successful, JFAIL otherwise
  315. X ***************************************************************************/
  316. int
  317. Print_string( str )
  318. X    char *str;
  319. X{
  320. X    int f;
  321. X    int l;
  322. X
  323. X    if( Print_ready() != JSUCC ){
  324. X        return( JFAIL );
  325. X    }
  326. X    if( of_fd ){
  327. X        f = of_fd;
  328. X    } else {
  329. X        f = Print_fd;
  330. X    }
  331. X    l = strlen( str );
  332. X    if( write( f, str, l ) != l ){
  333. X        logerr( XLOG_INFO, "Print_string: write error");
  334. X        Print_close();
  335. X        return( JFAIL );
  336. X    }
  337. X    return( JSUCC );
  338. X}
  339. X
  340. X
  341. X/***************************************************************************
  342. X * Print_copy( int fd )
  343. X * copy a file through a filter
  344. X * 1. ready the Printer
  345. X * 2. copy the file to the appropriate output device
  346. X * 3. if an error, close the Printer
  347. X ***************************************************************************/
  348. int
  349. Print_copy( fd )
  350. X    int fd;
  351. X{
  352. X    int f;
  353. X    long cnt;
  354. X    char buf[BUFSIZ];
  355. X    int in;            /* bytes read */
  356. X    int out;        /* bytes written out */
  357. X
  358. X    cnt = 0;
  359. X    if( Print_ready() != JSUCC ){
  360. X        return( JFAIL );
  361. X    }
  362. X    if( of_fd ){
  363. X        f = of_fd;
  364. X    } else {
  365. X        f = Print_fd;
  366. X    }
  367. X    while( (in = read( fd, buf, sizeof(buf) )) > 0 ){
  368. X        out = write( f, buf, in );
  369. X        if( in != out ){
  370. X            logerr( XLOG_INFO, "Print_copy: write error");
  371. X            Print_close();
  372. X            return( JFAIL );
  373. X        }
  374. X        cnt = cnt + out;
  375. X    }
  376. X    /*
  377. X     * completed the reading
  378. X     */
  379. X    if( in < 0 ){
  380. X        logerr( XLOG_INFO, "Print_copy: read error");
  381. X        Print_close();
  382. X        return( JFAIL );
  383. X    }
  384. X    if(Debug>3)log(XLOG_DEBUG,"Print_copy: printed %d bytes", cnt);
  385. X    return( JSUCC );
  386. X}
  387. X
  388. X/***************************************************************************
  389. X *Print_filter( int fd, char *cmd )
  390. X *  spawn a subprocess to do the printing
  391. X * 1. stop the Printer
  392. X * 2. fork a process
  393. X * 3. wait for process to complete
  394. X * 4. restart the process
  395. X * Return: JSUCC if successful, JFAIL otherwise
  396. X ***************************************************************************/
  397. int
  398. Print_filter( file, cmd )
  399. X    int file;
  400. X    char *cmd;
  401. X{
  402. X    int succ;            /* success code */
  403. X    int filter_pid;        /* filter process */
  404. X    int pid;            /* daughter pid */
  405. X    union wait status;    /* daughter status */
  406. X    int err;            /* saved value of errno */
  407. X    
  408. X    /*
  409. X     * stop the Printer
  410. X     */
  411. X    succ = of_stop();
  412. X    if( succ != JSUCC ){
  413. X        return( succ );
  414. X    }
  415. X    /*
  416. X     * fork a process,  and connect file to fd 0, Printer to fd 1.
  417. X     */
  418. X    if ((filter_pid = fork()) == 0) {    /* daughter */
  419. X        /*
  420. X         * dup input file to standard in and Printer to stdout
  421. X         */
  422. X        if( dup2(file, 0)<0 || dup2(Print_fd, 1)<0 ){
  423. X            logerr_die(XLOG_NOTICE,"Print_filter: dup2 failed filter %s",cmd);
  424. X        }
  425. X        mexecv(cmd);
  426. X        logerr_die( XLOG_NOTICE,"Print_filter: cannot execv %s", cmd);
  427. X    } else if( filter_pid < 0 ){
  428. X        logerr( XLOG_NOTICE, "Print_filter: fork failed" );
  429. X        Print_close();
  430. X        return( JFAIL );
  431. X    }
  432. X    /*
  433. X     *    Wait for filter to complete 
  434. X     */
  435. X    if(Debug>2)log(XLOG_DEBUG,"Print_filter: waiting for pid %d",filter_pid);
  436. X    while ((pid = wait(&status)) > 0 && pid != filter_pid){
  437. X        if(Debug>3)log( XLOG_DEBUG, "Print_filter:caught %d (%s)",
  438. X            pid, Decode_status(&status) );
  439. X    }
  440. X    err = errno;
  441. X    if(Debug>2)log( XLOG_DEBUG, "Print_filter: filter %d finished (%s)",
  442. X        pid,Decode_status(&status));
  443. X    errno = err;
  444. X    /*
  445. X     * Check to see how filter terminated
  446. X     */
  447. X    if( pid < 0 || !WIFEXITED(status)
  448. X        || (unsigned)status.w_retcode > 1 ){
  449. X        /*
  450. X         * died for bad reasons, don't run this again
  451. X         */
  452. X        log(XLOG_INFO,"Print_filter:Filter '%s' Malfunction (%s)",
  453. X            cmd, Decode_status(&status));
  454. X        Print_close();
  455. X        return( JABORT );
  456. X    } else if (status.w_retcode != 0){
  457. X        /*
  458. X         * try again
  459. X         */
  460. X        log( XLOG_INFO, "Print_filter:Filter '%s' Retry wanted", cmd );
  461. X        Print_close();
  462. X        return(JFAIL);
  463. X    }
  464. X    return(JSUCC);
  465. X}
  466. X
  467. X/*
  468. X * Print_banner()
  469. X * 1. get the Printer ready
  470. X * 2. call the banner() routine with the correct parameter
  471. X */
  472. Print_banner()
  473. X{
  474. X    int f;
  475. X
  476. X    if(Debug>3)log(XLOG_DEBUG,"Print_banner: printing banner");
  477. X    if( Print_ready() != JSUCC ){
  478. X        return( JFAIL );
  479. X    }
  480. X    if( of_fd ){
  481. X        f = of_fd;
  482. X    } else {
  483. X        f = Print_fd;
  484. X    }
  485. X    if( banner(f) != JSUCC ){
  486. X        if(Debug>3)log(XLOG_DEBUG,"Print_banner: banner failed");
  487. X        Print_close();
  488. X        return( JFAIL );
  489. X    }
  490. X    return( JSUCC );
  491. X}
  492. X
  493. X/*
  494. X * Fri Feb 26 08:44:53 CST 1988 Patrick Powell
  495. X * set terminal modes
  496. X * This code was based on a public domain version of public domain version
  497. X * of stty. I suppose that I could have created if from scratermctrlh,
  498. X * but I have seen the same table appearing
  499. X * in many "public domain" display terminal modes programs.
  500. X */
  501. X
  502. struct tchars termctrl;
  503. struct ltchars linectrl;
  504. struct sgttyb mode;
  505. struct
  506. X{
  507. X    char    *string;
  508. X    int    set;
  509. X    int    reset;
  510. X    int    lset;
  511. X    int    lreset;
  512. X} modes[] = {
  513. X    "bs0",        BS0, BS1, 0, 0,
  514. X    "bs1",        BS1, BS1, 0, 0,
  515. X    "cbreak",    CBREAK, 0, 0, 0,
  516. X    "-cbreak",    0, CBREAK, 0, 0,
  517. X    "cooked",    0, RAW, 0, 0,
  518. X    "cr0",        CR0, CR3, 0, 0,
  519. X    "cr1",        CR1, CR3, 0, 0,
  520. X    "cr2",        CR2, CR3, 0, 0,
  521. X    "cr3",        CR3, CR3, 0, 0,
  522. X    "decctlq",    0, 0, LDECCTQ, 0,
  523. X    "-decctlq",    0, 0, 0, LDECCTQ,
  524. X    "echo",        ECHO, 0, 0, 0,
  525. X    "-echo",    0, ECHO, 0, 0,
  526. X    "even",        EVENP, 0, 0, 0,
  527. X    "-even",    0, EVENP, 0, 0,
  528. X    "ff0",        FF0, FF1, 0, 0,
  529. X    "ff1",        FF1, FF1, 0, 0,
  530. X    "lcase",    LCASE, 0, 0, 0,
  531. X    "-lcase",    0, LCASE, 0, 0,
  532. X    "litout",    0, 0, LLITOUT, 0,
  533. X    "-litout",    0, 0, 0, LLITOUT,
  534. X    "nl",        0, CRMOD, 0, 0,
  535. X    "-nl",        CRMOD, 0, 0, 0,
  536. X    "nl0",        NL0, NL3, 0, 0,
  537. X    "nl1",        NL1, NL3, 0, 0,
  538. X    "nl2",        NL2, NL3, 0, 0,
  539. X    "nl3",        NL3, NL3, 0, 0,
  540. X    "noflsh",    0, 0, LNOFLSH, 0,
  541. X    "-noflsh",    0, 0, 0, LNOFLSH,
  542. X    "nohang",    0, 0, LNOHANG, 0,
  543. X    "-nohang",    0, 0, 0, LNOHANG,
  544. X    "odd",        ODDP, 0, 0, 0,
  545. X    "-odd",        0, ODDP, 0, 0,
  546. X    "raw",        RAW, 0, 0, 0,
  547. X    "-raw",        0, RAW, 0, 0,
  548. X    "tab0",        TAB0, XTABS, 0, 0,
  549. X    "tab1",        TAB1, XTABS, 0, 0,
  550. X    "tab2",        TAB2, XTABS, 0, 0,
  551. X    "tabs",        0, XTABS, 0, 0,
  552. X    "-tabs",    XTABS, 0, 0, 0,
  553. X    "tandem",    TANDEM, 0, 0, 0,
  554. X    "-tandem",    0, TANDEM, 0, 0,
  555. X    "tilde",    0, 0, LTILDE, 0,
  556. X    "-tilde",    0, 0, 0, LTILDE,
  557. X    "tn300",    CR1, ALLDELAY, 0, 0,
  558. X    "tty33",    CR1, ALLDELAY, 0, 0,
  559. X    "tty37",    FF1+CR2+TAB1+NL1, ALLDELAY, 0, 0,
  560. X    "vt05",        NL2, ALLDELAY, 0, 0,
  561. X    0,
  562. X};
  563. X
  564. X
  565. struct    special {
  566. X    char    *name;
  567. X    char    *cp;
  568. X    char    def;
  569. X} special[] = {
  570. X    "stop",        &termctrl.t_stopc,        CSTOP,
  571. X    "start",    &termctrl.t_startc,        CSTART,
  572. X    0
  573. X};
  574. X
  575. Do_stty( fd )
  576. X    int fd;
  577. X{
  578. X    int i;
  579. X    int    localmode;
  580. X    int    linedisc;
  581. X    char buf[BUFSIZ], *bp, *ep, *arg;
  582. X
  583. X    if( ioctl(fd, TIOCGETP, &mode) < 0
  584. X     || ioctl(fd, TIOCGETC, &termctrl) < 0
  585. X     || ioctl(fd, TIOCLGET, &localmode) < 0
  586. X     || ioctl(fd, TIOCGLTC, &linectrl) < 0 ){
  587. X        logerr_die( XLOG_INFO,"cannot get tty parameters");
  588. X    }
  589. X    if(Debug>3)log(XLOG_DEBUG,"stty: before mode 0x%x, lmode 0x%x, speed 0x%x",
  590. X            mode.sg_flags, localmode, mode.sg_ispeed );
  591. X    if( BR ){
  592. X      for(i=0; bauds[i].baud && BR != bauds[i].baud; i++);
  593. X      if( i == 0){
  594. X          fatal(XLOG_INFO,"illegal baud rate %d", BR);
  595. X      }
  596. X      mode.sg_ispeed = mode.sg_ospeed = bauds[i].speed;
  597. X    }
  598. X    mode.sg_flags &= ~FC;
  599. X    mode.sg_flags |= FS;
  600. X    localmode &= ~XC;
  601. X    localmode |= XS;
  602. X
  603. X    if( TY && *TY ){
  604. X        (void)strcpy(buf, TY);
  605. X        ep = buf;
  606. X    } else {
  607. X        ep = 0;
  608. X    }
  609. X    while( ep && *ep ){
  610. X        for( ; *ep && isspace(*ep) ; ++ ep );
  611. X        for( arg = ep; *ep && !isspace(*ep) ; ++ ep );
  612. X        if( *ep ){
  613. X            *ep = 0;
  614. X            ++ep;
  615. X        }
  616. X        for(i=0; modes[i].string && strcmp(modes[i].string,arg); i++);
  617. X        if(modes[i].string) {
  618. X            if(Debug>4)log(XLOG_DEBUG,
  619. X                "stty: modes %s, mc 0x%x ms 0x%x lc 0x%x ls 0x%x",
  620. X                modes[i].string, modes[i].reset, modes[i].set,
  621. X                modes[i].lreset, modes[i].lset );
  622. X            mode.sg_flags &= ~modes[i].reset;
  623. X            mode.sg_flags |= modes[i].set;
  624. X            localmode &= ~modes[i].lreset;
  625. X            localmode |= modes[i].lset;
  626. X            continue;
  627. X        }
  628. X        for (i = 0; special[i].name && strcmp(special[i].name,arg); i++);
  629. X        if( special[i].name ){
  630. X            for( ; *ep && isspace(*ep) ; ++ ep );
  631. X            for( bp = ep; *ep && !isspace(*ep) ; ++ ep );
  632. X            if( *ep ){
  633. X                *ep = 0;
  634. X                ++ep;
  635. X            }
  636. X            if( *bp == 0 ){
  637. X                fatal( XLOG_INFO, "stty: missing parameter for %s", arg );
  638. X            }
  639. X            if (bp[0] == '^'){
  640. X                if( bp[1] == '?' ){
  641. X                    *special[i].cp = 0177;
  642. X                } else {
  643. X                    *special[i].cp = 037 & bp[1];
  644. X                }
  645. X            } else {
  646. X                *special[i].cp = bp[0];
  647. X            }
  648. X            if(Debug>4)log(XLOG_DEBUG,"stty: special %s %s", arg, bp );
  649. X            continue;
  650. X        }
  651. X        for(i=0; bauds[i].string && strcmp(bauds[i].string,arg); i++);
  652. X        if(bauds[i].string) {
  653. X            if(Debug>4)log(XLOG_DEBUG,"stty: speed %s", arg );
  654. X            mode.sg_ispeed = mode.sg_ospeed = bauds[i].speed;
  655. X            continue;
  656. X        }
  657. X        if (!strcmp("new", arg)){
  658. X            if(Debug>4)log(XLOG_DEBUG,"stty: ldisc %s", arg );
  659. X            linedisc = NTTYDISC;
  660. X            if (ioctl(fd, TIOCSETD, &linedisc)<0)
  661. X                logerr_die(XLOG_INFO,"stty: TIOCSETD ioctl failed");
  662. X            continue;
  663. X        }
  664. X        if (!strcmp("old",arg)){
  665. X            if(Debug>4)log(XLOG_DEBUG,"stty: ldisc %s", arg );
  666. X            linedisc = 0;
  667. X            if (ioctl(fd, TIOCSETD, &linedisc)<0)
  668. X                logerr_die(XLOG_INFO,"stty: TIOCSETD ioctl failed");
  669. X            continue;
  670. X        }
  671. X        fatal(XLOG_INFO,"unknown mode: %s\n", arg);
  672. X    }
  673. X    if(Debug>3)log(XLOG_DEBUG,"stty: after mode 0x%x, lmode 0x%x, speed 0x%x",
  674. X            mode.sg_flags, localmode, mode.sg_ispeed );
  675. X    if( ioctl(fd, TIOCSETN, &mode) < 0
  676. X        || ioctl(fd, TIOCSETC, &termctrl) < 0
  677. X        || ioctl(fd, TIOCSLTC, &linectrl) < 0
  678. X        || ioctl(fd, TIOCLSET, &localmode) < 0 ){
  679. X        logerr_die( XLOG_NOTICE,"cannot set tty parameters");
  680. X    }
  681. X}
  682. END_OF_FILE
  683. if test 17575 -ne `wc -c <'src/print_support.c'`; then
  684.     echo shar: \"'src/print_support.c'\" unpacked with wrong size!
  685. fi
  686. # end of 'src/print_support.c'
  687. fi
  688. if test -f 'src/recvfiles.c' -a "${1}" != "-c" ; then 
  689.   echo shar: Will not clobber existing file \"'src/recvfiles.c'\"
  690. else
  691. echo shar: Extracting \"'src/recvfiles.c'\" \(18372 characters\)
  692. sed "s/^X//" >'src/recvfiles.c' <<'END_OF_FILE'
  693. X/***************************************************************************
  694. X * U. Minnesota LPD Software * Copyright 1987, 1988, Patrick Powell
  695. X ***************************************************************************
  696. X * MODULE: recvfiles.c
  697. X * Receive files from a remote site
  698. X ***************************************************************************
  699. X * Revision History: Created Sat Jan 16 07:10:12 CST 1988
  700. X * $Log:    recvfiles.c,v $
  701. X * Revision 3.1  88/06/18  09:35:25  papowell
  702. X * Version 3.0- Distributed Sat Jun 18 1988
  703. X * 
  704. X * Revision 2.4  88/05/21  10:28:14  papowell
  705. X * Minor editing
  706. X * 
  707. X * Revision 2.3  88/05/14  10:18:01  papowell
  708. X * Use long format for job file names;
  709. X * Added 'fd', no forward flag;
  710. X * Control file has to have hostname and origination agree.
  711. X * 
  712. X * Revision 2.2  88/05/11  09:52:55  papowell
  713. X * Remote printer file transfer error fixed.
  714. X * 
  715. X * Revision 2.1  88/05/09  10:09:55  papowell
  716. X * PLP: Released Version
  717. X * 
  718. X * Revision 1.5  88/04/28  09:52:40  papowell
  719. X * added casts to shut up lint
  720. X * 
  721. X * Revision 1.4  88/04/26  15:53:39  papowell
  722. X * Fixed up a horribly silly bug in the add_files and File_name
  723. X * routines;  sigh.  Would you believe an L (l) and a one (1) got mixed
  724. X * up?
  725. X * 
  726. X * Revision 1.3  88/03/25  15:01:17  papowell
  727. X * Debugged Version:
  728. X * 1. Added the PLP control file first transfer
  729. X * 2. Checks for MX during file transfers
  730. X * 3. Found and fixed a mysterious bug involving the SYSLOG facilities;
  731. X *     apparently they open files and then assume that they will stay
  732. X *     open.
  733. X * 4. Made sure that stdin, stdout, stderr was available at all times.
  734. X * 
  735. X * Revision 1.2  88/03/05  15:01:07  papowell
  736. X * Minor Corrections,  Lint Problems
  737. X * 
  738. X * Revision 1.1  88/03/01  11:09:06  papowell
  739. X * Initial revision
  740. X * 
  741. X ***************************************************************************/
  742. X#ifndef lint
  743. static char id_str1[] =
  744. X    "$Header: recvfiles.c,v 3.1 88/06/18 09:35:25 papowell Exp $ PLP Copyright 1988 Patrick Powell";
  745. X#endif lint
  746. X
  747. X#include "lp.h"
  748. X
  749. X/***************************************************************************
  750. X * This module implements the file transfer protocol at the receiving
  751. X * site. For each job:
  752. X * 1.  The data files are transferred.
  753. X * 2.  The control files are transferred.
  754. X *     If the transfer is unsuccessful,  all job files are removed.
  755. X * 
  756. X * Individual files are transferred using the following protocol.
  757. X * 
  758. X * 1.  The sending site sends a line with the size and name of the file,
  759. X *     and a flag indicating if it is a data or control file.
  760. X * 2.  The receiving site will acknowledge reception.
  761. X * 3.  The remote site will send the file.
  762. X * 4.  The receiving site will acknowledge reception.
  763. X * 
  764. X * The transfer protocol is implemented by a simple FSM:
  765. X * INIT:  no files transferred
  766. X * DATA:  data file transferred
  767. X * CONTROL: control file transferred
  768. X * 
  769. X * A list of all files associated with the job is maintained,
  770. X * and if any errors result,  the list of files will be deleted.
  771. X * 
  772. X ***************************************************************************/
  773. X
  774. X/***************************************************************************
  775. X * recvfiles()
  776. X *
  777. X * Gets a job from the remote end.
  778. X * 
  779. X * The old Berkeley protocol was to send data files and then the control
  780. X * file.  The PLP protocol will send the control file first, then the data
  781. X * files, followed by the name of the control file.
  782. X * 
  783. X * If there is an error during transfer, all the jobs associated with the
  784. X * file are removed.
  785. X * 
  786. X * In order to be compatible with the Berkeley LPD, old Berkeley format is
  787. X * also supported.
  788. X ***************************************************************************/
  789. recvfiles()
  790. X{
  791. X    int i;                    /* ACME Integers */
  792. X    int succ;                /* success flag */
  793. X    int flag;                /* file kind */
  794. X    long size;                /* file size */
  795. X    char fname[CFNAMELEN+1];    /* file fname */
  796. X    char cfname[CFNAMELEN+1];    /* file fname */
  797. X    char tfname[CFNAMELEN+1];    /* file fname */
  798. X    int fd;                    /* file descriptor */
  799. X    FILE *cfp;                /* FILE descriptor */
  800. X    int state;                /* state: IDLE, BDATA, BCNTRL, PCNTRL, PDATA */
  801. X    long jobsize;            /* job size */
  802. X#define IDLE    0    /* nothing doing */
  803. X#define BDATA    1    /* transferring Berkeley data file */
  804. X#define BCNTRL    2    /* transferring Berkeley control file */
  805. X#define PCNTRL    3    /* transferring PLP control file */
  806. X#define PDATA    4    /* transferring PLP data file */
  807. X#define PLAST    5    /* last file has been transferred */
  808. X
  809. X    /*
  810. X     * get the printcap entry
  811. X     */
  812. X    if( Get_pc_entry(Printer, Status_pc_vars, Status_pc_len ) == 0){
  813. X        log( XLOG_INFO, "revcfiles: trying to start non-existent Printer" );
  814. X    }
  815. X    if( SD == 0 || *SD == 0 ){
  816. X        /*
  817. X         * no spooling directory, not a Printer
  818. X         */
  819. X        if(Debug>0)log(XLOG_DEBUG, "revcfiles: not a Printer");
  820. X        return;
  821. X    }
  822. X    /* chdir to spool directory */
  823. X    if (chdir(SD) < 0) {
  824. X        logerr_die( XLOG_NOTICE,"revcfiles: cannot chdir to %s", SD);
  825. X    }
  826. X    if(Debug>3)log(XLOG_DEBUG,"recvfiles: setting up log");
  827. X    Setuplog( LF, 1 );
  828. X    if(Debug>3)log(XLOG_DEBUG,"recvfiles: sending confirm");
  829. X    if( send_ack(0) != JSUCC ){
  830. X        if(Debug>3)log(XLOG_DEBUG,"recvfiles: confirm failed");
  831. X        goto error;
  832. X    }
  833. X
  834. X    /*
  835. X     * set up the file transfers
  836. X     */
  837. X    state = IDLE;
  838. X    while( (succ = get_file_xfer(&flag, &size, fname )) == JSUCC && flag ){
  839. X        if(Debug>3)log(XLOG_DEBUG,"recvfiles: state %d, flag %d, file %s",
  840. X            state,flag,fname);
  841. X        switch( state ){
  842. X        case IDLE:
  843. X            cfp = NULL;
  844. X            Rec_cnt = 0;
  845. X            (void)strcpy( cfname, fname );
  846. X            jobsize = 0;
  847. X            for( i = 0; i < 26; ++i ){
  848. X                CFparm[i][0] = 0;
  849. X            }
  850. X            switch( flag ){
  851. X            case CNAME:
  852. X                state = PCNTRL; break;
  853. X            case DFILE:
  854. X                state = BDATA;    break;
  855. X            default:
  856. X                goto protocol;
  857. X            }
  858. X            break;
  859. X        case BDATA:
  860. X            switch( flag ){
  861. X            case DFILE:
  862. X                break;
  863. X            case CFILE:
  864. X                state = BCNTRL;
  865. X                break;
  866. X            default:
  867. X                goto protocol;
  868. X            }
  869. X            break;
  870. X        case PCNTRL:
  871. X            switch( flag ){
  872. X            case DFILE:
  873. X                state = PDATA;    break;
  874. X            default:
  875. X                goto protocol;
  876. X            }
  877. X            break;
  878. X        case PDATA:
  879. X            switch( flag ){
  880. X            case DFILE:
  881. X                break;
  882. X            case CEND:
  883. X                state = PLAST;
  884. X                break;
  885. X            default:
  886. X                goto protocol;
  887. X            }
  888. X            break;
  889. X        default:
  890. X            goto protocol;
  891. X        }
  892. X        /*
  893. X         * trying to send a file with a different sequence number?
  894. X         */
  895. X        if( Job_match( cfname, fname ) == 0 ){
  896. X            log( XLOG_INFO, "recvfiles: file with bad format %s", fname );
  897. X            succ = JFAIL;
  898. X            goto error;
  899. X        }
  900. X        switch( state ){
  901. X        case PDATA:
  902. X            /*
  903. X             * add names to list
  904. X             */
  905. X            if( Find_name( fname ) < 0 ){
  906. X                log( XLOG_INFO,
  907. X                    "recvfiles: data file not in job '%s'", fname );
  908. X                succ = JFAIL;
  909. X                goto error;
  910. X            }
  911. X            break;
  912. X        case BCNTRL:
  913. X        case PCNTRL:
  914. X            (void)strcpy(tfname, fname );
  915. X            fname[0] = 't';
  916. X            break;
  917. X        }
  918. X        /*
  919. X         * add the file name to the temporary list
  920. X         */
  921. X        if( (i = add_recfiles( fname )) < 0 ){
  922. X            log( XLOG_INFO, "recvfiles: too many files (%s)", fname );
  923. X            succ = JFAIL;
  924. X            goto error;
  925. X        }
  926. X        /*
  927. X         * check to see that file size does not exceed the total
  928. X         */
  929. X        Parms[i].num = 1;
  930. X        Parms[i].size = ((size+1023)/1024);
  931. X        jobsize = jobsize + Parms[i].size;
  932. X        if( MX && jobsize > MX ){
  933. X            log( XLOG_INFO, "recvfiles: file (%s) exceeds MX",fname, MX);
  934. X            succ = JFAIL;
  935. X            goto error;
  936. X        }
  937. X        /*
  938. X         * check to see if we have opened the file already
  939. X         */
  940. X        if( state != PLAST ){
  941. X            /*
  942. X             * we lock the file
  943. X             */
  944. X            fd = Exlockcf( fname );
  945. X            if( fd < 0 ){
  946. X                /*
  947. X                 * The file is locked.  This can only happen if some other
  948. X                 * process  got hold of the file.  We either have several
  949. X                 * processes transferring files or horrible collision course.
  950. X                 * DONT remove already transferred files.
  951. X                 */
  952. X                logerr(XLOG_NOTICE,"recvfiles: %s IMPOSSIBLE collision %s",
  953. X                    fname,From);
  954. X                exit(1);
  955. X            }
  956. X            succ = get_file( size, fd, fname );
  957. X            if( succ != JSUCC ){
  958. X                goto error;
  959. X            }
  960. X        }
  961. X        /*
  962. X         * open a FILE for the control file, and check the entries in it.
  963. X         * If we have just got the file in PLP, just scan for entries.
  964. X         * Otherwise check to see that all are present.
  965. X         */
  966. X        switch( state ){
  967. X        case BCNTRL:
  968. X        case PCNTRL:
  969. X            if( (cfp = fdopen( fd, "r" ) ) < 0 ){
  970. X                logerr_die( XLOG_INFO,"recvfiles: fdopen failed" );
  971. X            }
  972. X            if( Validate_cf( state == PCNTRL, cfp, fname ) == 0 ){
  973. X                goto error;
  974. X            }
  975. X            break;
  976. X        case PLAST:
  977. X            if( Validate_cf( 0, cfp, fname ) == 0 ){
  978. X                goto error;
  979. X            }
  980. X            break;
  981. X        }
  982. X        switch( state ){
  983. X        case PLAST:
  984. X        case BCNTRL:
  985. X            Rename_cf( fname );
  986. X            Rec_cnt = 0;
  987. X            (void)fclose(cfp);
  988. X            state = IDLE;
  989. X            break;
  990. X        case PCNTRL:
  991. X            break;
  992. X        default:
  993. X            (void)close( fd );
  994. X            break;
  995. X        }
  996. X        /*
  997. X         * We can confirm transfer to the other end
  998. X         */
  999. X        if( send_ack( 0 ) != JSUCC ){
  1000. X            goto error;
  1001. X        }
  1002. X    }
  1003. X    if( succ == JSUCC && flag == 0 && state == IDLE ){
  1004. X        /*
  1005. X         * finished! start up Printer
  1006. X         */
  1007. X        if(Debug>3)log(XLOG_DEBUG,"recvfiles: done, starting Printer");
  1008. X        Link_close();
  1009. X        Startprinter();
  1010. X        return;
  1011. X    }
  1012. X    /*
  1013. X     * Error conditions
  1014. X     * 1. remove files
  1015. X     * 2. reply with error status to remote end
  1016. X     */
  1017. protocol:
  1018. X    log(XLOG_INFO,
  1019. X    "recvfiles: protocol violation, state %d, flag %d, file %s",
  1020. X        state, flag, fname );
  1021. error:
  1022. X    rm_recfiles();
  1023. X    (void)send_ack(1);
  1024. X    Startprinter();
  1025. X    return;
  1026. X}
  1027. X
  1028. X/***************************************************************************
  1029. X * add_recfiles(char * Name)
  1030. X * add a file Name to the received files
  1031. X ***************************************************************************/
  1032. X
  1033. add_recfiles( filename )
  1034. X    char *filename;
  1035. X{
  1036. X    int i;
  1037. X
  1038. X    if(Debug>4)log(XLOG_DEBUG,"add_recfiles: %s", filename );
  1039. X    /*
  1040. X     * add a control file name to the parameter list entries
  1041. X     * if there is nothing in the list, clobber the entry.
  1042. X     */
  1043. X    if( Rec_cnt ==  0 ){
  1044. X        Parmcount = 0;
  1045. X    }
  1046. X    if( (i = Add_name( filename )) < 0 ){
  1047. X        return( -1 );
  1048. X    }
  1049. X    Rec_cnt = Parmcount;
  1050. X    return( i );
  1051. X}
  1052. X
  1053. X/***************************************************************************
  1054. X * rm_recfiles()
  1055. X * remove the files that are in the receive list;
  1056. X ***************************************************************************/
  1057. X
  1058. rm_recfiles()
  1059. X{
  1060. X    int i;        /* ACME Integer, Inc. */
  1061. X
  1062. X    if(Debug>4)log(XLOG_DEBUG,"rm_recfiles: removing files" );
  1063. X    for( i = 0; i < Rec_cnt; ++i ){
  1064. X        if(Debug>4)log(XLOG_DEBUG,"rm_recfiles: %s", Parms[i].filename );
  1065. X        (void)unlink_daemon( Parms[i].filename );
  1066. X    }
  1067. X    Rec_cnt = 0;
  1068. X}
  1069. X
  1070. X/***************************************************************************
  1071. X * get_file_xfer(int *flag; long *size; char *name )
  1072. X * 1. read a line from the far end
  1073. X * 2. the line has the format <flag><size> <name>\n
  1074. X *      "%c%d %s\n" format
  1075. X * 3. extract the information from the line
  1076. X * 4. acknowledge the information
  1077. X ***************************************************************************/
  1078. get_file_xfer( flag, size, name )
  1079. X    int *flag;
  1080. X    long *size;
  1081. X    char *name;
  1082. X{
  1083. X    char buf[BUFSIZ];        /* buffer for reading */
  1084. X    int i;                    /* ACME Integers, Inc. */
  1085. X    char *cp;                /* ACME Pointers, Inc. */
  1086. X
  1087. X    /*
  1088. X     * read a line from the remote end
  1089. X     * use Bomb-proof Read (bpread), which reads up to the first \n
  1090. X     */
  1091. X    if(Debug>3)log(XLOG_DEBUG,"get_file_xfer: starting", buf );
  1092. X    if( (i = bpread(1, buf, sizeof(buf)) ) < 0 ){
  1093. X        logerr(XLOG_INFO, "get_file_xfer: read error from remote");
  1094. X        *flag = 0;
  1095. X        goto error;
  1096. X    } else if( i == 0 ){
  1097. X        if(Debug>3)log(XLOG_DEBUG,"get_file_xfer: end of input");
  1098. X        *flag = 0;
  1099. X        return( JSUCC );
  1100. X    }
  1101. X    /*
  1102. X     * UGLY UGLY UGLY:
  1103. X     * what I wanted to do is:
  1104. X     *    if( sscanf( buf, "%c%d %s", flag, size, name ) != 3 )...
  1105. X     * but the guilty-of-incestuous-rape sscanf is not portable across
  1106. X     * several implementations.
  1107. X     */
  1108. X    if(Debug>3)log(XLOG_DEBUG,"get_file_xfer: %d'%s'", buf[0], &buf[1]);
  1109. X    /*
  1110. X     * pull off the flag information
  1111. X     */
  1112. X    i = buf[0];
  1113. X    if( i != DFILE && i != CFILE && i != CNAME && i != CEND){
  1114. X        log(XLOG_INFO, "get_file_xfer: bad first char (%d)", i);
  1115. X        goto error;
  1116. X    }
  1117. X    *flag = i;
  1118. X    /*
  1119. X     * now pull off the size information
  1120. X     */
  1121. X    *size = 0;
  1122. X    for( cp = &buf[1]; (i = *cp) && isdigit( i ); ++cp ){
  1123. X        *size = 10*(*size) + (i - '0');
  1124. X    }
  1125. X    if( *cp != ' '){
  1126. X        log(XLOG_INFO, "get_file_xfer: no space separator (%d)", *cp);
  1127. X        goto error;
  1128. X    }
  1129. X    while( *cp == ' ' ) ++cp;
  1130. X    if( Job_match( cp, cp ) == 0 ){
  1131. X        log(XLOG_INFO, "get_file_xfer: bad job name '%s'", cp);
  1132. X        goto error;
  1133. X    }
  1134. X    /*
  1135. X     * must be a data or control file only
  1136. X     */
  1137. X    (void)strcpy( name, cp );
  1138. X    /*
  1139. X     * send a confirmation
  1140. X     */
  1141. X    if( send_ack( 0 ) != JSUCC ){
  1142. X        goto error;
  1143. X    }
  1144. X    if(Debug>3)log(XLOG_DEBUG,"get_file_xfer: flag %d, size %d, name '%s'",
  1145. X        *flag, *size, name );
  1146. X    return( JSUCC );
  1147. X    /*
  1148. X     * error, give up
  1149. X     */
  1150. error:
  1151. X    Link_close();
  1152. X    return( JFAIL );
  1153. X}
  1154. X
  1155. X/***************************************************************************
  1156. X * get_file(long size; int fd; char *name)
  1157. X * 1. copy size bytes from fd 1 to fd
  1158. X * 2. the next byte read should be 0; if not, then you have error
  1159. X ***************************************************************************/
  1160. get_file( size, fd, name )
  1161. X    long size;
  1162. X    int fd;
  1163. X    char *name;
  1164. X{
  1165. X    char buf[BUFSIZ];        /* buffer for reading */
  1166. X    long cnt;                /* number of bytes */
  1167. X    int i;                    /* ACME Integers, Inc. */
  1168. X
  1169. X    /*
  1170. X     * we simply copy the file from the remote end
  1171. X     */
  1172. X    if(Debug>3)log(XLOG_DEBUG,"get_file: get %d (%s) from %s",size,name,From);
  1173. X    cnt = size;
  1174. X    while( cnt > 0 ){
  1175. X        if( cnt > sizeof(buf) ){
  1176. X            i = sizeof(buf);
  1177. X        } else {
  1178. X            i = cnt;
  1179. X        }
  1180. X        i = read(1, buf, i);
  1181. X        if( i < 0 ){
  1182. X            logerr(XLOG_INFO, "get_file: read from %s failed", From );
  1183. X            goto error;
  1184. X        }
  1185. X        if( i == 0 ){
  1186. X            log(XLOG_INFO,"get_file: read 0 bytes from %s, assume dead",From);
  1187. X            goto error;
  1188. X        }
  1189. X        if( write( fd, buf, i ) != i ){
  1190. X            logerr(XLOG_INFO, "write to %s failed", name );
  1191. X            goto error;
  1192. X        }
  1193. X        cnt = cnt - i;
  1194. X    }
  1195. X    if(Debug>3)log(XLOG_DEBUG,"get_file: success %d (%s) from %s",
  1196. X        size,name,From);
  1197. X    i = read(1, buf, 1);
  1198. X    if( i < 0 ){
  1199. X        logerr(XLOG_INFO, "get_file: end from %s failed", From );
  1200. X        goto error;
  1201. X    }
  1202. X    if( i == 0 ){
  1203. X        log(XLOG_INFO, "get_file: end, 0 bytes from %s, assume dead", From );
  1204. X        goto error;
  1205. X    }
  1206. X    if( buf[0] != 0 ){
  1207. X        log(XLOG_INFO, "get_file: bad end confirm, %d from %s",buf[0],From);
  1208. X        goto error;
  1209. X    }
  1210. X    if(Debug>3)log(XLOG_DEBUG,"get_file: read %s from %s", name, From );
  1211. X    return( JSUCC );
  1212. error:
  1213. X    Link_close();
  1214. X    return( JFAIL );
  1215. X}
  1216. X
  1217. X/***************************************************************************
  1218. X * send_ack( int c )
  1219. X * acknowledge by sending back single char c
  1220. X ***************************************************************************/
  1221. send_ack( c )
  1222. X    int c;
  1223. X{
  1224. X    char buf[1];
  1225. X
  1226. X    buf[0] = c;
  1227. X    if( write( 1, buf, 1 ) != 1 ){
  1228. X        logerr(XLOG_INFO,"send_ack: %d to %s failed", c, From );
  1229. X        return( JFAIL );
  1230. X    }
  1231. X    if(Debug>3)log(XLOG_DEBUG,"send_ack: %d to %s succeeded", c, From );
  1232. X    return( JSUCC );
  1233. X}
  1234. X
  1235. X/***************************************************************************
  1236. X * Validate_cf( scan, fp, fname )
  1237. X * Check to ensure that the files contained in this control file
  1238. X * were actually sent as part of the control file.
  1239. X * 1. fseek to the start of the file
  1240. X * 2. read the file, looking data file entries
  1241. X * 3. Check that the names of the data files are consistent with the
  1242. X *    name of the control file
  1243. X * 4. Check that the file was sent
  1244. X ***************************************************************************/
  1245. Validate_cf( scan, fp, fname )
  1246. X    int scan;
  1247. X    FILE *fp;
  1248. X    char *fname;
  1249. X{
  1250. X    char buf[BUFSIZ];    /* Buffer, Inc. */
  1251. X    int c, l;            /* AMCE Aluminum Siding and Integers, Inc. */
  1252. X    char *bp;            /* Buffer */
  1253. X    long size;            /* total job size */
  1254. X    int perms;            /* permissions */
  1255. X    int name_len;        /* length of hostname to check */
  1256. X
  1257. X    if(Debug>6){
  1258. X        (void)fprintf( stderr,"Validate_cf: files %d", Parmcount );
  1259. X        for( c = 0; c < Parmcount; ++c ){
  1260. X            (void)fprintf(stderr,", %d '%s'(%d)",c,
  1261. X                Parms[c].filename,Parms[c].num);
  1262. X        }
  1263. X        (void)fprintf( stderr, "\n" );
  1264. X    }
  1265. X    size = 0;
  1266. X    if( fseek( fp, 0L, 0 ) < 0 ){
  1267. X        logerr_die( XLOG_INFO, "Validate_cf: fseek failed '%s'", fname );
  1268. X    }
  1269. X    while( fgets( buf, sizeof(buf), fp ) ){
  1270. X        l = strlen( buf );
  1271. X        if( l > MAXPARMLEN ){
  1272. X            log( XLOG_INFO, "Validate_cf: '%s' line too long '%s'",fname,buf);
  1273. X            return( 0 );
  1274. X        }
  1275. X        if( buf[l-1] != '\n' ){
  1276. X            log( XLOG_INFO, "Validate_cf: '%s', missing \\n", fname );
  1277. X            return( 0 );
  1278. X        }
  1279. X        buf[l-1] = 0;
  1280. X        c = *buf;
  1281. X        bp = buf+1;
  1282. X        if( !isascii(c) || !isalnum(c)){
  1283. X            log( XLOG_INFO, "Validate_cf: file %s, bad line'%s'",fname,bp);
  1284. X            return( 0 );
  1285. X        }
  1286. X        /*
  1287. X         * Check to see that data file information is OK
  1288. X         */
  1289. X        if( isupper(c) && c != 'L' && c != 'U' ){
  1290. X            (void)strcpy( CFparm[c-'A'], bp );
  1291. X        }
  1292. X        if( islower(c) || c == 'U' ){
  1293. X            /*
  1294. X             * check to see that the file is in the list
  1295. X             */
  1296. X            if( Job_match( fname, bp ) == 0 ){
  1297. X                log( XLOG_INFO,"Validate_cf: file %s, bad data file '%s'",
  1298. X                    fname,bp);
  1299. X                return( 0 );
  1300. X            }
  1301. X            /*
  1302. X             * if we are scanning, just enter name in list, otherwise
  1303. X             * check to see that file is in the Parms[] list and that the
  1304. X             * total job size is within limits
  1305. X             */
  1306. X            if( scan ){
  1307. X                if( Add_name( bp ) < 0 ){
  1308. X                    log( XLOG_INFO,"Validate_cf: too many files in job %s (%s)",
  1309. X                        fname,bp);
  1310. X                    return( 0 );
  1311. X                }
  1312. X            } else if( (l = Find_name( bp )) < 0 ){
  1313. X                log(XLOG_INFO,
  1314. X                    "Validate_cf: file %s, data file '%s' not in list",
  1315. X                    fname,bp);
  1316. X                return( 0 );
  1317. X            } else if( Parms[l].num == 0 ){
  1318. X                log( XLOG_INFO,
  1319. X                    "Validate_cf: file %s, data file '%s' not transferred",
  1320. X                    fname,bp);
  1321. X                return( 0 );
  1322. X            } else if( islower( c ) ){
  1323. X                size = size + Parms[l].size;
  1324. X                if( MX && size > MX ){
  1325. X                    log( XLOG_INFO,"Validate_cf: job %s too large", fname);
  1326. X                    return( 0 );
  1327. X                }
  1328. X            }
  1329. X        }
  1330. X    }
  1331. X    /*
  1332. X     * check to see if the remote submitter has valid authorizations
  1333. X     */
  1334. X    if( LOGNAME[0] == 0 ){
  1335. X        log( XLOG_INFO,"Validate_cf: job %s missing username", fname);
  1336. X        return( 0 );
  1337. X    }
  1338. X    /*
  1339. X     * check for long or short name
  1340. X     */
  1341. X    if( LH ){
  1342. X        name_len = strlen( From );
  1343. X    } else {
  1344. X        name_len = strlen( &fname[STARTFR] );
  1345. X    }
  1346. X    if( strncmp( FROMHOST, &fname[STARTFR], name_len ) ){
  1347. X        log( XLOG_INFO,"Validate_cf: bad filename '%s' FROMHOST '%s'",
  1348. X            fname, FROMHOST);
  1349. X        return( 0 );
  1350. X    }
  1351. X    /*
  1352. X     * check to see if you will accept forwarded files
  1353. X     * if FD is set, then no forwarded files allowed
  1354. X     */
  1355. X    if( FD && strcmp( FROMHOST, From ) ){
  1356. X        log( XLOG_INFO,"Validate_cf: forwarded job '%s' FROMHOST '%s'",
  1357. X            fname, FROMHOST);
  1358. X        return( 0 );
  1359. X    }
  1360. X    perms = 'R';
  1361. X    if((Permfile && *Permfile &&
  1362. X            !Checkperm(Permfile,FROMHOST,LOGNAME,First_name,&perms,(int *)0,0))
  1363. X       ||(XU && *XU &&
  1364. X            !Checkperm(XU,FROMHOST,LOGNAME,First_name,&perms,(int *)0,0 ) )){
  1365. X        log(XLOG_INFO, "Validate_cf: %s@%s cannot use '%s'",
  1366. X            LOGNAME, FROMHOST, First_name );
  1367. X            return( 0 );
  1368. X    }
  1369. X    return( 1 );
  1370. X}
  1371. END_OF_FILE
  1372. if test 18372 -ne `wc -c <'src/recvfiles.c'`; then
  1373.     echo shar: \"'src/recvfiles.c'\" unpacked with wrong size!
  1374. fi
  1375. # end of 'src/recvfiles.c'
  1376. fi
  1377. echo shar: End of archive 13 \(of 16\).
  1378. cp /dev/null ark13isdone
  1379. MISSING=""
  1380. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ; do
  1381.     if test ! -f ark${I}isdone ; then
  1382.     MISSING="${MISSING} ${I}"
  1383.     fi
  1384. done
  1385. if test "${MISSING}" = "" ; then
  1386.     echo You have unpacked all 16 archives.
  1387.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1388. else
  1389.     echo You still need to unpack the following archives:
  1390.     echo "        " ${MISSING}
  1391. fi
  1392. ##  End of shell archive.
  1393. exit 0
  1394.  
  1395.