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

  1. Subject:  v16i029:  Public lineprinter spooler package, Part16/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 29
  8. Archive-name: plp/part16
  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 16 (of 16)."
  17. # Contents:  src/control_ops.c
  18. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  19. if test -f 'src/control_ops.c' -a "${1}" != "-c" ; then 
  20.   echo shar: Will not clobber existing file \"'src/control_ops.c'\"
  21. else
  22. echo shar: Extracting \"'src/control_ops.c'\" \(28050 characters\)
  23. sed "s/^X//" >'src/control_ops.c' <<'END_OF_FILE'
  24. X/***************************************************************************
  25. X * U. Minnesota LPD Software * Copyright 1987, 1988, Patrick Powell
  26. X ***************************************************************************
  27. X * MODULE: Control_ops.c
  28. X ***************************************************************************
  29. X * Revision History: Created Mon Jan 18 07:48:12 CST 1988
  30. X * $Log:    control_ops.c,v $
  31. X * Revision 3.2  88/06/24  17:55:14  papowell
  32. X * MODS for VAX 4.3BSD UNIX
  33. X * 
  34. X * Revision 3.1  88/06/18  09:34:02  papowell
  35. X * Version 3.0- Distributed Sat Jun 18 1988
  36. X * 
  37. X * Revision 2.2  88/05/14  10:21:23  papowell
  38. X * Modified -X flag handling
  39. X * 
  40. X * Revision 2.1  88/05/09  10:07:50  papowell
  41. X * PLP: Released Version
  42. X * 
  43. X * Revision 1.9  88/04/28  11:02:11  papowell
  44. X * removed unused variables,  shuts up lint
  45. X * 
  46. X * Revision 1.8  88/04/27  17:59:14  papowell
  47. X * Added debugging statements to C_lpq, C_lprm
  48. X * 
  49. X * Revision 1.7  88/04/07  12:31:32  papowell
  50. X * 
  51. X * Revision 1.6  88/04/06  12:12:24  papowell
  52. X * Minor updates, changes in error message formats.
  53. X * Elimination of the AF_UNIX connections, use AF_INET only.
  54. X * Better error messages.
  55. X * 
  56. X * Revision 1.5  88/03/25  14:59:13  papowell
  57. X * Debugged Version:
  58. X * 1. Added the PLP control file first transfer
  59. X * 2. Checks for MX during file transfers
  60. X * 3. Found and fixed a mysterious bug involving the SYSLOG facilities;
  61. X *     apparently they open files and then assume that they will stay
  62. X *     open.
  63. X * 4. Made sure that stdin, stdout, stderr was available at all times.
  64. X * 
  65. X * Revision 1.4  88/03/12  10:03:38  papowell
  66. X * *** empty log message ***
  67. X * 
  68. X * Revision 1.3  88/03/11  19:29:57  papowell
  69. X * Minor Changes, Updates
  70. X * 
  71. X * Revision 1.2  88/03/05  15:01:56  papowell
  72. X * Minor Corrections,  Lint Problems
  73. X * 
  74. X * Revision 1.1  88/03/01  11:08:19  papowell
  75. X * Initial revision
  76. X * 
  77. X ***************************************************************************/
  78. X#ifndef lint
  79. static char id_str1[] =
  80. X    "$Header: control_ops.c,v 3.2 88/06/24 17:55:14 papowell Exp $ PLP Copyright 1988 Patrick Powell";
  81. X#endif lint
  82. X
  83. X#include "lp.h"
  84. X
  85. X/***************************************************************************
  86. X * Control_ops()
  87. X *  1. get the printcap entries
  88. X *  2. check for permissions
  89. X *  3. determine the function to be carried out
  90. X *  4. carry out the function
  91. X ***************************************************************************/
  92. static int op_init;        /* flag for operation initialization */
  93. X
  94. X
  95. X/*
  96. X * dispatch is a data structure that contains the names and flagss
  97. X * of control commands.
  98. X */
  99. struct dispatch{
  100. X    char *name;
  101. X    int distinct;
  102. X    int (*routine)();
  103. X    int flags;
  104. X    char *summary;
  105. X};
  106. X
  107. int C_bad(), C_help(), C_abort(), C_clean(), C_disable(),
  108. X    C_enable(), C_exit(), C_kill(), C_restart(), C_lpq(), C_lprm(),
  109. X    C_start(), C_status(), C_stop(), C_topq(), C_remote(), C_lpd();
  110. X
  111. X#define NEED_OPT        1    /* we check for other options */
  112. X#define ALL_ALLOWED        2    /* check for all */
  113. X#define NEED_PRIV        4    /* privileged operation */
  114. X#define ALL_DEF            8    /* if no parameter, all is default */
  115. X#define NO_PR_LIST        0x10    /* printer list */
  116. X#define REMOTE_OP        0x20    /* remote allowed */
  117. X#define SERVER_OP        0x40    /* server allowed */
  118. X#define ON_REMOTE            0x80    /* not if you have RM and NW */
  119. X#define IS_OPT(x) ((x)&NEED_OPT)
  120. X#define IS_ALL(x) ((x)&ALL_ALLOWED)
  121. X#define IS_PRIV(x) ((x)&NEED_PRIV)
  122. X#define IS_ALL_DEF(x) ((x)&ALL_DEF)
  123. X#define IS_NO_PR_LIST(x) ((x)&NO_PR_LIST)
  124. X#define IS_REMOTE(x) ((x)&REMOTE_OP)
  125. X#define IS_SERVER(x) ((x)&SERVER_OP)
  126. X#define IS_ON_REMOTE(x) ((x)&ON_REMOTE)
  127. X
  128. static struct dispatch
  129. dispatch[] = {
  130. X{ "", 0, 0, 0, "not a command" },
  131. X{ "?", 1, C_help, 0, "? is same as 'help'" },
  132. X{ "abort", 1, C_abort,
  133. X    NEED_OPT | NEED_PRIV |ALL_ALLOWED |REMOTE_OP |SERVER_OP |ON_REMOTE,
  134. X    "abort ( all | Printer ): kill off server and disable printing" },
  135. X{ "clean", 1, C_clean, NEED_OPT | NEED_PRIV |ALL_ALLOWED |REMOTE_OP |ON_REMOTE,
  136. X    "clean ( all | Printer ): remove all crud from queue (dangerous!)"},
  137. X{ "disable", 1, C_disable, NEED_OPT | NEED_PRIV |ALL_ALLOWED |REMOTE_OP |ON_REMOTE,
  138. X    "disable ( all | Printer ): disable queueing"},
  139. X{ "enable", 2, C_enable, NEED_OPT | NEED_PRIV |ALL_ALLOWED |REMOTE_OP |ON_REMOTE,
  140. X    "enable ( all | Printer ): enable queuing"},
  141. X{ "exit", 2, C_exit, 0, "exit: terminate" },
  142. X{ "help", 1, C_help, 0 ,"help [all] [command]: print command summary"},
  143. X{ "kill", 1, C_kill,
  144. X    NEED_OPT | NEED_PRIV |ALL_ALLOWED |REMOTE_OP |SERVER_OP |ON_REMOTE,
  145. X    "kill ( all | Printer ): kill off server and then restart printing" },
  146. X{ "lpd", 3, C_lpd, 0,
  147. X    "lpd : check out lpd process"},
  148. X{ "lpq", 3, C_lpq, 0,
  149. X    "lpq ( parms ) : call lpq"},
  150. X{ "lprm", 3, C_lprm, 0,
  151. X    "lprm ( parms ) : call lpq"},
  152. X{ "quit", 1, C_exit, 0, "quit (same as exit): terminate" },
  153. X{ "remote", 3, C_remote, 0,
  154. X    "remote command: do the action on remote printer"},
  155. X{ "restart", 3, C_restart, NEED_OPT | ALL_ALLOWED |REMOTE_OP |SERVER_OP,
  156. X    "restart ( all | Printer ): start a server"},
  157. X{ "start", 4, C_start,
  158. X    NEED_OPT | NEED_PRIV |ALL_ALLOWED |REMOTE_OP |SERVER_OP |ON_REMOTE,
  159. X    "start ( all | Printer ): enable printing and start server"},
  160. X{ "status", 4, C_status, ALL_DEF |ALL_ALLOWED | NEED_OPT,
  161. X    "status [all] [Printer]: print status"},
  162. X{ "stop", 3, C_stop,
  163. X    NEED_OPT | NEED_PRIV |ALL_ALLOWED |REMOTE_OP |SERVER_OP |ON_REMOTE,
  164. X    "stop ( all | Printer ): disable further printing"},
  165. X{ "topq", 1, C_topq, NO_PR_LIST | NEED_OPT |REMOTE_OP | ON_REMOTE| NEED_PRIV,
  166. X    "topq Printer (Host | jobnumber)*: move job to top of queue"},
  167. X};
  168. int ncmds = sizeof(dispatch)/sizeof(struct dispatch);
  169. X
  170. X/***************************************************************************
  171. X * Control_ops()
  172. X * This routine is called with the parameters in the Parms[] array.
  173. X * It will check to see if the command is valid,  and if so, will
  174. X * do any other actions.
  175. X ***************************************************************************/
  176. int
  177. Control_ops()
  178. X{
  179. X    int command;        /* command we are going to do */
  180. X    char **list;        /* list of Printers */
  181. X    int i, all;            /* doing for all Printers */
  182. X
  183. X    /*
  184. X     * set the flagss needed
  185. X     */
  186. X    Is_local = ( strcmp( From, Host ) == 0 );
  187. X    Is_root  = ( strcmp( Person, "root" ) == 0);
  188. X    op_init = 0;
  189. X    command = 0;
  190. X    all = 0;
  191. X    /*
  192. X     * check to see that we have a valid command
  193. X     */
  194. X    if(Debug>4)Show_ops();
  195. X    if( Parmcount < 1 ){
  196. X        (void)fprintf( stdout, "no command\n" );
  197. X        return( 0 );
  198. X    }
  199. X    command = find_command( Parms[0].str );
  200. X    if( command == 0 ){
  201. X        (void)fprintf( stdout, "unknown command %s\n", Parms[0].str );
  202. X        return( 0 );
  203. X    }
  204. X    if(Debug>3)log(XLOG_DEBUG,"Control_ops: command %s, flags 0x%x, %s",
  205. X    dispatch[command].name,dispatch[command].flags,dispatch[command].summary);
  206. X    if( !Is_local && !IS_REMOTE(dispatch[command].flags) ){
  207. X        log(XLOG_INFO,"command %s cannot be done remotely", Parms[0].str);
  208. X        return( 0 );
  209. X    }
  210. X
  211. X    /*
  212. X     * call the appropriate routine
  213. X     */
  214. X    Shift_parms(1);
  215. X    /*
  216. X     * If no option processing just dispatch
  217. X     */
  218. X    if( !IS_OPT(dispatch[command].flags) ){
  219. X        return( (*dispatch[command].routine)(&dispatch[command]));
  220. X    }
  221. X    /*
  222. X     * if no options and IS_ALL is the default, set up the all flag
  223. X     */
  224. X    if( Parmcount == 0 ){
  225. X        if( IS_ALL_DEF(dispatch[command].flags) ){
  226. X            all = 1;
  227. X        } else {
  228. X            (void)fprintf( stdout, "no parameters, use: %s\n",
  229. X                dispatch[command].summary);
  230. X            return( 0 );
  231. X        }
  232. X    } else if( strcmp( Parms[0].str, "all" ) == 0 ){
  233. X        if( IS_ALL(dispatch[command].flags) ){
  234. X            all = 1;
  235. X        } else {
  236. X            (void)fprintf( stdout, "'all' not allowed, use: %s\n",
  237. X                dispatch[command].summary);
  238. X            return( 0 );
  239. X        }
  240. X    }
  241. X    /*
  242. X     * set up Printer from parameters
  243. X     */
  244. X    if( all ){
  245. X        if(Debug>2)log(XLOG_DEBUG,"'all' parameter" );
  246. X        for( list = All_printers(); *list; ++list ){
  247. X            Printer = *list;
  248. X            if( service( &dispatch[command] ) == 0 ){
  249. X                return( 0 );
  250. X            }
  251. X        }
  252. X    } else {
  253. X        for( i = 0; i < Parmcount; ++i ){
  254. X            Printer = Parms[0].str;
  255. X            Shift_parms(1);
  256. X            if( service( &dispatch[command] ) == 0 ){
  257. X                return( 0 );
  258. X            }
  259. X            if( IS_NO_PR_LIST(dispatch[command].flags) ){
  260. X                break;
  261. X            }
  262. X        }
  263. X    }
  264. X    return( 1 );
  265. X}
  266. X
  267. X/***************************************************************************
  268. X * service( struct dispatch *cmd );
  269. X * 1. check on the printcap entry
  270. X * 2. chdir to the spool directory
  271. X * 3. dispatch the particular routine
  272. X ***************************************************************************/
  273. X
  274. service( cmd )
  275. X    struct dispatch *cmd;
  276. X{
  277. X    char *st, *ps;
  278. X    int perms = 'C';    /* Permission Checking */
  279. X
  280. X    if(Debug>4)log(XLOG_DEBUG,"service: printer '%s', cmd '%s'",
  281. X        Printer, cmd->name );
  282. X    if(Get_pc_entry(Printer, Status_pc_vars, Status_pc_len) == 0){
  283. X        log(XLOG_INFO,"service: Printer %s does not have printcap entry", Printer);
  284. X        return( 0 );
  285. X    }
  286. X    if( RM && NW && IS_ON_REMOTE(cmd->flags) ){
  287. X        (void)fprintf( stdout,
  288. X    "remote printer and network file system, use \'remote %s %s\'\n",
  289. X        cmd->name, Printer );
  290. X        return( 0 );
  291. X    }
  292. X    /*
  293. X     * we may have a server specified
  294. X     */
  295. X    if( SS && *SS ){
  296. X        ps = PS;
  297. X        st = ST;
  298. X        if( Set_pc_entry(SS, Status_pc_vars, Status_pc_len) == 0){
  299. X            log(XLOG_INFO,"service: Server %s queue %s does not have printcap entry",
  300. X            Printer,SS);
  301. X            return( 0 );
  302. X        }
  303. X        PS = ps;
  304. X        ST = st;
  305. X        LO = Printer;
  306. X        SV = 0;
  307. X    }
  308. X    if( SD == 0 || *SD == 0 ){
  309. X        log( XLOG_INFO,"service: Printer %s does not have spool directory", Printer);
  310. X        return( 0 );
  311. X    }
  312. X    /* chdir to spool directory */
  313. X    if (chdir(SD) < 0) {
  314. X        logerr( XLOG_INFO,"service: cannot chdir to %s", SD);
  315. X        return( 0 );
  316. X    }
  317. X    /*
  318. X     * check on the privileges needed
  319. X     * You have to be local and root OR have C privs
  320. X     */
  321. X    if( IS_PRIV(cmd->flags) && !( Is_local && Is_root )
  322. X            && !( Permfile && *Permfile
  323. X              && Checkperm(Permfile,From,Person,First_name,&perms,(int *)0,0))){
  324. X        (void)fprintf(stdout,
  325. X            "You do not have Printer control perms on '%s'\n", Printer);
  326. X        return( 0 );
  327. X    }
  328. X    return( (*cmd->routine)(cmd));
  329. X}
  330. X
  331. X/***************************************************************************
  332. X * int find_command( char *str )
  333. X * look in the command table for a match.  The "distinct" entry is used
  334. X * to determine the numbers of characters for a match.
  335. X ***************************************************************************/
  336. X
  337. int
  338. find_command( str )
  339. X    char *str;
  340. X{
  341. X    int i;
  342. X
  343. X    for( i = 1; i < ncmds; ++ i ){
  344. X        if( strncmp( str, dispatch[i].name, dispatch[i].distinct ) == 0
  345. X            && strncmp( str, dispatch[i].name, strlen(str)) == 0 ){
  346. X            return( i );
  347. X        }
  348. X    }
  349. X    return( 0 );
  350. X}
  351. X
  352. X/***************************************************************************
  353. X * C_bad()
  354. X * Cannot decide what to do with the command
  355. X ***************************************************************************/
  356. int
  357. C_bad()
  358. X{
  359. X    (void)fprintf(stdout, "bad command %s\n", Parms[0].str );
  360. X    return( 1 );
  361. X}
  362. X/***************************************************************************
  363. X * C_help()
  364. X * Print a help message for each command listed,
  365. X * or a simple list of commands
  366. X ***************************************************************************/
  367. int
  368. C_help()
  369. X{
  370. X    int i, cmd;
  371. X
  372. X    if( Parmcount < 2 || strcmp( Parms[1].str, "all" ) == 0 ){
  373. X        for( i = 1; i < ncmds; ++i ){
  374. X            Print_sum( i );
  375. X        }
  376. X    } else {
  377. X        for( i = 1; i < Parmcount; ++i ){
  378. X            cmd = find_command( Parms[i].str );
  379. X            if( cmd > 0 ){
  380. X                Print_sum( cmd );
  381. X            } else {
  382. X                (void)fprintf(stdout, "not a command: %s", Parms[i].str );
  383. X            }
  384. X        }
  385. X    }
  386. X}
  387. X
  388. X/***************************************************************************
  389. X * Print_sum( cmd )
  390. X * prints the command summary line
  391. X ***************************************************************************/
  392. Print_sum( cmd )
  393. X{
  394. X    (void)fprintf(stdout, "%s\n", dispatch[cmd].summary );
  395. X}
  396. X
  397. X
  398. X/***************************************************************************
  399. X * C_exit()
  400. X * terminate gracefully
  401. X ***************************************************************************/
  402. C_exit()
  403. X{
  404. X    exit( 0 );
  405. X}
  406. X/***************************************************************************
  407. X * C_stop()
  408. X * Sets the DISABLE_PRINT perm bit in the lockfile perms
  409. X * Returns: 1 if successful, 0 if not;
  410. X ***************************************************************************/
  411. C_stop()
  412. X{
  413. X    int s;
  414. X
  415. X    if(Debug>4)log(XLOG_DEBUG,"C_stop: printer %s, lock '%s'", Printer, LO );
  416. X    (void)Checklockfile( LO, (int *)0,(char *)0,0,&LO_statb );
  417. X    if((s=chmod_daemon(LO,(int)(LO_statb.st_mode&0777) |DISABLE_PRINT)) < 0){
  418. X        logerr(XLOG_INFO,"cannot chmod lockfile %s", LO);
  419. X    } else {
  420. X        (void)fprintf(stdout,"%s: printing disabled\n", Printer);
  421. X    }
  422. X    return( s >= 0 );
  423. X}
  424. X/***************************************************************************
  425. X * C_start()
  426. X * 1. Clears the DISABLE_PRINT perm bit in the lockfile perms
  427. X * 2. Starts the Printer
  428. X * Returns: 1 if successful, 0 if not;
  429. X ***************************************************************************/
  430. C_start()
  431. X{
  432. X    int s;
  433. X
  434. X    if(Debug>4)log(XLOG_DEBUG,"C_start: printer %s, lock '%s'", Printer, LO );
  435. X    (void)Checklockfile( LO, (int *)0,(char *)0,0,&LO_statb );
  436. X    if((s=chmod_daemon(LO, (int)(LO_statb.st_mode & ENABLE_PRINT))) < 0){
  437. X        logerr(XLOG_INFO,"cannot chmod lockfile %s", LO);
  438. X    } else {
  439. X        (void)fprintf(stdout,"%s: printing enabled\n", Printer);
  440. X    }
  441. X    /*
  442. X     * start the server
  443. X     */
  444. X    if( s >= 0 ){
  445. X        s = C_restart();
  446. X    }
  447. X    return( s >= 0 );
  448. X}
  449. X/***************************************************************************
  450. X * C_disable()
  451. X * Sets the DISABLE_QUEUE perm bit in the lockfile perms
  452. X * Returns: 1 if successful, 0 if not;
  453. X ***************************************************************************/
  454. C_disable()
  455. X{
  456. X    int s;
  457. X
  458. X    if(Debug>4)log(XLOG_DEBUG,"C_disable: printer %s, lock '%s'", Printer, LO );
  459. X    (void)Checklockfile( LO, (int *)0,(char *)0,0,&LO_statb );
  460. X    if((s=chmod_daemon(LO,(int)(LO_statb.st_mode&0777) | DISABLE_QUEUE)) < 0){
  461. X        logerr(XLOG_INFO,"cannot chmod lockfile %s", LO);
  462. X    } else {
  463. X        (void)fprintf(stdout,"%s: queueing disabled\n", Printer);
  464. X    }
  465. X    return( s >= 0 );
  466. X}
  467. X/***************************************************************************
  468. X * C_enable()
  469. X * 1. Clears the DISABLE_QUEUE perm bit in the lockfile perms
  470. X * Returns: 1 if successful, 0 if not;
  471. X ***************************************************************************/
  472. C_enable()
  473. X{
  474. X    int s;
  475. X
  476. X    if(Debug>4)log(XLOG_DEBUG,"C_enable: printer %s, lock '%s'", Printer, LO );
  477. X    (void)Checklockfile( LO, (int *)0,(char *)0,0,&LO_statb );
  478. X    if((s=chmod_daemon(LO, (int)(LO_statb.st_mode & ENABLE_QUEUE))) < 0){
  479. X        logerr(XLOG_INFO,"cannot chmod lockfile %s", LO);
  480. X    } else {
  481. X        (void)fprintf(stdout,"%s: queueing enabled\n", Printer);
  482. X    }
  483. X    return( s >= 0 );
  484. X}
  485. X/***************************************************************************
  486. X * C_restart()
  487. X * 1. Attempts to fire up the server
  488. X * Returns: 1 if successful, 0 if not;
  489. X ***************************************************************************/
  490. C_restart()
  491. X{
  492. X    /*
  493. X     * start the server
  494. X     */
  495. X
  496. X    if(Debug>4)log(XLOG_DEBUG,"C_restart: printer %s, lock '%s'", Printer, LO );
  497. X    (void)Startserver();
  498. X    return( 1 );
  499. X}
  500. X
  501. X/*
  502. X * killserver(): kills the current server to stop printing
  503. X */
  504. static int
  505. killserver()
  506. X{
  507. X    int s;        /* Success of operation */
  508. X    int pid;    /* server PID */
  509. X    /*
  510. X     * Kill the current server to stop printing now.
  511. X     */
  512. X    s = 1;
  513. X    if( Checklockfile( LO, &pid, (char *)0, 0,&LO_statb )){
  514. X        if( kill(pid, SIGINT) < 0 ){
  515. X            (void)logerr(XLOG_INFO,"server (pid %d) not killed", pid);
  516. X            s = 0;
  517. X        } else {
  518. X            (void)fprintf(stdout,"%s: server (pid %d) killed\n",
  519. X                Printer, pid);
  520. X        }
  521. X    } else {
  522. X        (void)fprintf(stdout,"%s: no server present\n", Printer);
  523. X    }
  524. X    return(s);
  525. X}
  526. X/***************************************************************************
  527. X * C_abort()
  528. X * 1. Does C_stop()
  529. X * 2. kills off server if there is one
  530. X * Returns: 1 if successful, 0 if not;
  531. X ***************************************************************************/
  532. C_abort()
  533. X{
  534. X    int s;        /* Success of operation */
  535. X
  536. X    if(Debug>4)log(XLOG_DEBUG,"C_abort: printer %s, lock '%s'", Printer, LO );
  537. X    s = C_stop();
  538. X    if( s ){
  539. X        s = killserver();
  540. X    }
  541. X    return( s );
  542. X}
  543. X/***************************************************************************
  544. X * C_kill()
  545. X * 1. Does C_abort()
  546. X * 2. Does C_start()
  547. X * Returns: 1 if successful, 0 if not;
  548. X ***************************************************************************/
  549. C_kill()
  550. X{
  551. X    int s;        /* Success of operation */
  552. X
  553. X    if(Debug>4)log(XLOG_DEBUG,"C_kill: printer %s, lock '%s'", Printer, LO );
  554. X    s = C_abort();
  555. X    if( s ){
  556. X        s = C_start();
  557. X    }
  558. X    return( s );
  559. X}
  560. X
  561. X/***************************************************************************
  562. X * C_clean()
  563. X * 1. Removes all entries in the specified spool directory.
  564. X * Returns: 1 if successful, 0 if not;
  565. X ***************************************************************************/
  566. C_clean()
  567. X{
  568. X    int c;                /* ACME Integers, Inc. */
  569. X    DIR *dirp;
  570. X    struct direct *d;
  571. X
  572. X    if(Debug>4)log(XLOG_DEBUG,"C_clean: printer %s, lock '%s'", Printer, LO );
  573. X    if ((dirp = opendir(SD)) == NULL) {
  574. X        logerr(XLOG_INFO,"cannot examine spool directory %s");
  575. X        return( 0 );
  576. X    }
  577. X    while ((d = readdir(dirp)) != NULL) {
  578. X        c = d->d_name[0];
  579. X        if ((c == 'c' || c == 't' || c == 'd') && d->d_name[1]=='f') {
  580. X            if (unlink_daemon(d->d_name) < 0){
  581. X                (void)fprintf(stdout,"cannot remove %s\n", d->d_name);
  582. X            } else {
  583. X                (void)fprintf(stdout,"removed %s\n", d->d_name);
  584. X            }
  585. X        }
  586. X    }
  587. X    closedir(dirp);
  588. X    return( 1 );
  589. X}
  590. X/*
  591. X * Print the status of each queue listed or all the queues.
  592. X */
  593. static char *hdr_format =  "%-12.12s %-4s  %-10s %s\n";
  594. static char *data_format = "%-12.12s %4d  %-10s %s%s%s\n";
  595. C_status()
  596. X{
  597. X    int active, pid;            /* active server and its pid */
  598. X    char buf[BUFSIZ];            /* buffer */
  599. X    char *prstat, *actstat, *qstat, *rqstat;    /* Printer and queue status */
  600. X    char *st, *ps;
  601. X    char sbuf[BUFSIZ];            /* status buffer */
  602. X    char servers[BUFSIZ];
  603. X    char *sp, *ep, *sr;            /* ACME Pointers, Inc. */
  604. X
  605. X    if(Debug>3)log(XLOG_INFO,"C_status: printer %s", Printer);
  606. X    if(Get_pc_entry(Printer, Status_pc_vars, Status_pc_len) == 0){
  607. X        log(XLOG_INFO,"Printer %s does not have printcap entry", Printer);
  608. X        return( 0 );
  609. X    }
  610. X    /* we have a server here */
  611. X    if( SS && *SS ){
  612. X        ps = PS;
  613. X        st = ST;
  614. X        if( Set_pc_entry(SS, Status_pc_vars, Status_pc_len) == 0){
  615. X            log(XLOG_INFO,"Server %s queue %s does not have printcap entry",
  616. X                Printer,SS);
  617. X            return( 0 );
  618. X        }
  619. X        PS = ps;
  620. X        ST = st;
  621. X        LO = Printer;
  622. X        SV = 0;
  623. X    }
  624. X    if( SD == 0 || *SD == 0 ){
  625. X        log( XLOG_INFO,"Printer %s does not have spool directory", Printer);
  626. X        return( 0 );
  627. X    }
  628. X    /* chdir to spool directory */
  629. X    if (chdir(SD) < 0) {
  630. X        logerr( XLOG_INFO,"cannot chdir to %s", SD);
  631. X        return( 0 );
  632. X    }
  633. X    /*
  634. X     * start by getting active server information
  635. X     */
  636. X    buf[0] = 0;
  637. X    active = Checklockfile( LO, &pid, buf, sizeof( buf),&LO_statb);
  638. X
  639. X    /*
  640. X     * get numbers of jobs in queue
  641. X     */
  642. X
  643. X    Jobcount = Getq();
  644. X
  645. X    /*
  646. X     * now format the info appropriately
  647. X     */
  648. X    qstat = (LO_statb.st_mode & DISABLE_QUEUE) ? "disabled " : "enabled ";
  649. X    prstat = ( LO_statb.st_mode & DISABLE_PRINT) ? "disabled " : "enabled ";
  650. X    /*
  651. X     * get active server
  652. X     */
  653. X    if(Debug>4)log(XLOG_DEBUG,"C_status: active '%d', Jobcount '%d', '%s'",
  654. X        active, Jobcount, buf );
  655. X    if( SV == 0 || *SV == 0 ){
  656. X        if( Jobcount == 0 && active == 0 ){
  657. X            (void)sprintf( sbuf,"" );
  658. X        } else if( Jobcount == 0 && active ){
  659. X            (void)sprintf( sbuf,"(server %d)", pid, buf );
  660. X        } else if( Jobcount && active == 0 ){
  661. X            (void)sprintf( sbuf,"(no server)" );
  662. X        } else {
  663. X            (void)sprintf( sbuf,"(server %d, job %s)", pid, buf );
  664. X        }
  665. X        actstat = sbuf;
  666. X    } else {
  667. X        (void)strcpy( servers, SV );
  668. X        (void)sprintf( sbuf, hdr_format, "", "", "X", "" );
  669. X        if( (sp = index( sbuf, 'X' ) ) == 0 ){
  670. X            fatal(XLOG_INFO,"C_status: header format bad" );
  671. X        }
  672. X        *sp = 0;
  673. X        for( sp = servers; sp; sp = ep ){
  674. X            ep = index( sp, ',');
  675. X            if( ep ){
  676. X                *ep = 0;
  677. X                ep = ep + 1;
  678. X            }
  679. X            active = Checklockfile( sp, &pid,buf,sizeof(buf),&LO_statb );
  680. X            if( LO_statb.st_mode & DISABLE_PRINT){
  681. X                sr = "dis";
  682. X            } else {
  683. X                sr = "enb";
  684. X            }
  685. X            if( active == 0 ){
  686. X                (void)sprintf( sbuf+strlen(sbuf),"(%s: %s, no server)",sp, sr);
  687. X            } else {
  688. X            (void)sprintf( sbuf+strlen(sbuf),"(%s: %s, %d, job %s)",
  689. X                sp, sr, pid, buf );
  690. X            }
  691. X        }
  692. X        actstat = sbuf;
  693. X    }
  694. X    if( LO_statb.st_mode & FORCE_REQUE ){
  695. X            rqstat = ", reorder requested";
  696. X    } else {
  697. X            rqstat = "";
  698. X    }
  699. X    /* displays heading if not already displayed */
  700. X    if (!op_init) {
  701. X        (void)fprintf(stdout,hdr_format,
  702. X            SS ? "Server" : "Queue", "Jobs", "Queueing", "Printing" );
  703. X        op_init = 1;
  704. X    }
  705. X    /* prints the queue status */
  706. X    (void)fprintf(stdout,data_format, Printer, Jobcount, qstat,
  707. X            prstat,rqstat,actstat);
  708. X    /* prints the Printer status */
  709. X    printstatus();
  710. X    (void)fflush(stdout);
  711. X    return(1);
  712. X}
  713. X
  714. X/*
  715. X * Put the specified jobs at the top of Printer queue.
  716. X */
  717. C_topq()
  718. X{
  719. X    int i;                    /* ACME Integer, Inc. */
  720. X    int changed;            /* We changed the queue */
  721. X    char *cfname;            /* control file name */
  722. X
  723. X    (void)fprintf(stdout,"%s:\n", Printer);
  724. X
  725. X    /*
  726. X     * put the parameters in the list in the correct position
  727. X     */
  728. X    if( Parmcount == 0 ){
  729. X        if(Debug>4)log(XLOG_DEBUG,"C_topq: no parameters" );
  730. X        return( 0 );
  731. X    }
  732. X    if(Debug>4)log(XLOG_DEBUG,"C_topq: '%s'(%d)", Parms[0].str, Parms[0].num );
  733. X    /* get number of jobs in the queue */
  734. X    Jobcount = Getq();
  735. X    /*
  736. X     * go through the queue and find the jobs to be promoted
  737. X     */
  738. X    changed = 0;
  739. X    for( i = 0; i < Jobcount; ++i ){
  740. X        if(Match_entry( &Queue[i] )){
  741. X            /*
  742. X             * Reposition the job by setting its priority to high level
  743. X             * and then fix the control file
  744. X             */
  745. X            if(promote(Queue[i].q_name)) {
  746. X                changed++;
  747. X                Queue[i].q_name[0] = 0;
  748. X            }
  749. X        }
  750. X    }
  751. X    /*
  752. X     * Put the other high priority jobs lower
  753. X     */
  754. X    if( !changed ){
  755. X        return( 1 );
  756. X    }
  757. X    for( i = 0; i < Jobcount; i++) {
  758. X        cfname = Queue[i].q_name;
  759. X        if(*cfname && cfname[2] == 'A'){
  760. X            touch(cfname);
  761. X        }
  762. X    }
  763. X    (void)fprintf(stdout, "queue order changed\n");
  764. X    /*
  765. X     * Turn on the public execute bit of the lock file to
  766. X     * get lpd to rebuild the queue after the current job.
  767. X     */
  768. X    (void)Checklockfile( LO, (int *)0,(char *)0,0,&LO_statb );
  769. X    if( chmod_daemon(LO, (int)(LO_statb.st_mode & 0777) | FORCE_REQUE) < 0 ){
  770. X        logerr( XLOG_INFO, "cannot force requeue on lockfile %s", LO );
  771. X        return( 0 );
  772. X    }
  773. X    return( 1 );
  774. X} 
  775. X
  776. X/***************************************************************************
  777. X * promote( char *cfname )
  778. X * promote a file to the A priority, and head of the list.
  779. X ***************************************************************************/
  780. promote(cfname)
  781. X    char *cfname;
  782. X{
  783. X    char buf[BUFSIZ];
  784. X
  785. X    (void)strcpy( buf, cfname);
  786. X    buf[STARTPR] = 'A';
  787. X    if(Debug>0)log( XLOG_DEBUG, "renaming %s to %s", cfname, buf );
  788. X    if( strcmp( buf, cfname) && rename( cfname, buf ) < 0 ){
  789. X        logerr( XLOG_INFO,"cannot rename %s to %s", cfname, buf );
  790. X        return(0);
  791. X    }
  792. X    (void)fprintf( stdout, "promoting %s to %s\n", cfname, buf );
  793. X    return( 1 );
  794. X}
  795. X
  796. X
  797. X/* 
  798. X * Change the modification time of the file.
  799. X *    Returns boolean if successful.  
  800. X */
  801. touch(cfname)
  802. X    char *cfname;
  803. X{
  804. X    FILE *fp;
  805. X    int i;
  806. X
  807. X    if( (fp = Lockcf(cfname)) == NULL ){
  808. X        logerr(XLOG_INFO,"cannot open %s\n", cfname);
  809. X    } else if( (i = getc(fp)) == EOF ){
  810. X        logerr(XLOG_INFO,"cannot read %s\n", cfname);
  811. X    } else if(fseek(fp, 0L, 0) < 0 ){;
  812. X        /* set pointer back to top of file */
  813. X        logerr(XLOG_INFO,"cannot seek %s\n", cfname);
  814. X    } else if( putc( i, fp) == EOF ){
  815. X        logerr(XLOG_INFO,"cannot write %s\n", cfname);
  816. X    } else if( fflush( fp ) == EOF ){
  817. X        logerr(XLOG_INFO,"cannot flush %s\n", cfname);
  818. X    }
  819. X    if( fp != NULL ){
  820. X        (void)fclose(fp);
  821. X    }
  822. X}
  823. X
  824. X/*
  825. X * Show_ops()
  826. X * show the values of the local options
  827. X */
  828. X
  829. Show_ops()
  830. X{
  831. X    int i;
  832. X    (void)fprintf(stdout,"From: %s, Host %s, Person %s\n",From,Host,Person);
  833. X    (void)fprintf(stdout,"Is_local %d, Is_root %d\n", Is_local, Is_root );
  834. X    (void)fprintf(stdout,"Parmcount %d ", Parmcount );
  835. X    for( i = 0; i < Parmcount; ++i ){
  836. X        (void)fprintf(stdout, " '%s'(%d)", Parms[i].str, Parms[i].num );
  837. X    }
  838. X    (void)fprintf(stdout,"\n");
  839. X    (void)fflush(stdout);
  840. X}
  841. X
  842. X/***************************************************************************
  843. X * C_lpq()
  844. X * invoke Lpq with parameters.
  845. X * use the "system()" facility to do this.
  846. X ***************************************************************************/
  847. C_lpq()
  848. X{
  849. X    char buf[BUFSIZ];
  850. X    char *bp, *ep;            /* ACME Pointers, Inc. */
  851. X    int i;
  852. X
  853. X    ep = buf+sizeof(buf);
  854. X    bp = estrcp( buf, "lpq", ep );
  855. X    for( i = 0; i < Parmcount; ++i ){
  856. X        bp = estrcp( bp, " ", ep );
  857. X        bp = estrcp( bp, Parms[i].str, ep );
  858. X    }
  859. X    if(Debug>4)log(XLOG_DEBUG,"C_lpq: '%s'", buf );
  860. X    i = system( buf );
  861. X    if(Debug>4)log(XLOG_DEBUG,"C_lpq: status %d", i );
  862. X    return( i );
  863. X}
  864. X
  865. X/***************************************************************************
  866. X * C_lprm()
  867. X * invoke Lprm with parameters.
  868. X * use the "system()" facility to do this.
  869. X ***************************************************************************/
  870. C_lprm()
  871. X{
  872. X    char buf[BUFSIZ];
  873. X    char *bp, *ep;            /* ACME Pointers, Inc. */
  874. X    int i;
  875. X
  876. X    ep = buf+sizeof(buf);
  877. X    bp = estrcp( buf, "lprm", ep );
  878. X    for( i = 0; i < Parmcount; ++i ){
  879. X        bp = estrcp( bp, " ", ep );
  880. X        bp = estrcp( bp, Parms[i].str, ep );
  881. X    }
  882. X    if(Debug>4)log(XLOG_DEBUG,"C_lprm: '%s'", buf );
  883. X    i =  system( buf );
  884. X    if(Debug>4)log(XLOG_DEBUG,"C_lprm: status %d", i );
  885. X    return( i );
  886. X}
  887. X
  888. X/***************************************************************************
  889. X * C_remote()
  890. X * do the indicated command on the remote host
  891. X * command has the form: "remote op printer"
  892. X * 1. get the command and see if it can be done remotely
  893. X *    Parms[0] will be op, Parms[1] will be printer
  894. X * 2. check the printer and make sure that it is a remote printer
  895. X * 3. send the remote command to the far end, and get the information
  896. X *    sent back.
  897. X ***************************************************************************/
  898. X
  899. C_remote(cmd)
  900. X    struct dispatch *cmd;
  901. X{
  902. X    char **list;        /* list of printers */
  903. X    int i;                /* ACME Integers and Bearings, Inc. */
  904. X    int command;        /* command we are going to do */
  905. X
  906. X    if( Parmcount < 2 ){
  907. X        (void)fprintf( stdout, "no or missing command or parameters\n" );
  908. X        return( 0 );
  909. X    }
  910. X    command = find_command( Parms[0].str );
  911. X    if( command == 0 ){
  912. X        (void)fprintf( stdout, "unknown command %s\n", Parms[0].str );
  913. X        return( 0 );
  914. X    }
  915. X    if(Debug>3)log(XLOG_DEBUG,"C_remote: command %s, %d, %s",
  916. X    dispatch[command].name,dispatch[command].flags,dispatch[command].summary);
  917. X
  918. X    if( !IS_REMOTE(dispatch[command].flags) ){
  919. X        (void)fprintf( stdout, "command %s cannot be done remotely\n",
  920. X            Parms[0].str );
  921. X    }
  922. X
  923. X    /*
  924. X     * check on the printer
  925. X     */
  926. X    if( strcmp("all", Parms[0].str) == 0){
  927. X        if(Debug>2)log(XLOG_DEBUG,"'all' parameter" );
  928. X        for( list = All_printers(); *list; ++list ){
  929. X            Printer = *list;
  930. X            if( remote_cando(dispatch[command].flags) ){
  931. X                Remote_control(dispatch[command].name);
  932. X            }
  933. X        }
  934. X    } else {
  935. X        for( i = 1; i < Parmcount; ++i ){
  936. X            Printer = Parms[i].str;
  937. X            if( remote_cando(dispatch[command].flags) ){
  938. X                Remote_control(dispatch[command].name);
  939. X            }
  940. X        }
  941. X    }
  942. X    return( 1 );
  943. X}
  944. X
  945. X/***************************************************************************
  946. X * remote_cando()
  947. X * returns 0 if not able to do to remote site, 1 otherwise
  948. X *    
  949. X ***************************************************************************/
  950. remote_cando(flags)
  951. X{
  952. X    int perms = 'C';    /* Permission Checking */
  953. X
  954. X    if(Get_pc_entry(Printer, Status_pc_vars, Status_pc_len) == 0){
  955. X        log(XLOG_INFO,"Printer %s does not have printcap entry", Printer);
  956. X        return( 0 );
  957. X    }
  958. X    if( RM == 0 || RP == 0 ){
  959. X        if(Debug>5)log(XLOG_DEBUG,"%s not remote", Printer );
  960. X        return( 0 );
  961. X    }
  962. X    /*
  963. X     * check on the privileges needed
  964. X     * You have to be local and root OR have C privs
  965. X     */
  966. X    if( IS_PRIV(flags) && !( Is_local && Is_root )
  967. X        && !( Permfile && *Permfile
  968. X          && Checkperm(Permfile,From,Person,First_name,&perms,(int *)0,0))){
  969. X    (void)fprintf(stdout,
  970. X            "You do not have printer control perms on '%s'\n", Printer);
  971. X        return( 0 );
  972. X    }
  973. X    return( 1 );
  974. X}
  975. X
  976. X/***************************************************************************
  977. X * C_lpd()
  978. X * 1. Check to see if there is an active lpd server by checking the
  979. X *    lock file.
  980. X * 2. Check to see if the /dev/printer is available as well.
  981. X ***************************************************************************/
  982. X
  983. C_lpd()
  984. X{
  985. X    int f;
  986. X
  987. X    (void)Checklockfile(Masterlock, &f, (char *)0, 0, &LO_statb );
  988. X    if(f){
  989. X        (void)fprintf(stdout, "active LPD %d\n", f );
  990. X    } else {
  991. X        (void)fprintf( stdout, "LPD is not active\n" );
  992. X    }
  993. X    (void)fflush(stdout);
  994. X}
  995. END_OF_FILE
  996. if test 28050 -ne `wc -c <'src/control_ops.c'`; then
  997.     echo shar: \"'src/control_ops.c'\" unpacked with wrong size!
  998. fi
  999. # end of 'src/control_ops.c'
  1000. fi
  1001. echo shar: End of archive 16 \(of 16\).
  1002. cp /dev/null ark16isdone
  1003. MISSING=""
  1004. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ; do
  1005.     if test ! -f ark${I}isdone ; then
  1006.     MISSING="${MISSING} ${I}"
  1007.     fi
  1008. done
  1009. if test "${MISSING}" = "" ; then
  1010.     echo You have unpacked all 16 archives.
  1011.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1012. else
  1013.     echo You still need to unpack the following archives:
  1014.     echo "        " ${MISSING}
  1015. fi
  1016. ##  End of shell archive.
  1017. exit 0
  1018.  
  1019.