home *** CD-ROM | disk | FTP | other *** search
/ Network Support Encyclopedia 96-1 / novell-nsepro-1996-1-cd2.iso / download / netware / lw42n2.exe / BWPRINT.C < prev    next >
C/C++ Source or Header  |  1994-12-09  |  24KB  |  919 lines

  1. #define VERSION  "3.2"
  2. /*
  3.     BWNFSD is an RPC daemon used in conjunction with BWNFS (a client NFS
  4. for DOS based PCs. BWNFSD provides Authentication, Print Spooling,
  5. DOS 3.1 Locking, DOS 3.1 Sharing, GID name mapping, UID name mapping services
  6. for BWNFS and associated applications on the PC. BWNFSD is being used also
  7. by Macintosh NFS clients.
  8.  
  9.     The BWNFSD code is originally copyright Beame & Whiteside Software Ltd.
  10. and now is released to the Public Domain. The intent is that all server vendors
  11. included a version of BWNFSD with their operating system. BWNFSD can run
  12. simultanteously with PCNFSD, but provides more features.
  13.  
  14.     Please send modifications to:
  15.  
  16.         Beame & Whiteside Software, Inc.
  17.         706 Hillsborough St.
  18.         Raleigh, North Carolina
  19.         USA 27603-1655
  20.         +1 (919) 831-8989
  21.         support@bws.com
  22.  
  23.     Please modify by including "ifdefs" for your particular operating
  24. system, with appropriate modifications to the "makefile".
  25.  
  26. BWPRINT.C provides the print spool services for BWNFS. This is where most
  27. modification needs to be done as it is coded mainly for BSD systems, not
  28. System V.
  29.  
  30. MODIFICATION HISTORY
  31. --------------------
  32. 27/06/92 fjw  Made default_print readable by breaking out #defined sections
  33. 01/08/92 fjw  Merged in SVR4 code from Frank Glass (gatech!holos0!fsg)
  34. 31/08/92 cfb  Added code for queueing.  It's a little ugly :-)
  35. 31/08/92 fjw  Mucked about cleaning the ifdefs up and making queues right
  36. 31/08/92 fjw  Thanks to David Marceau for help with some obscure SCO bits
  37. 08/10/92 fjw  Fixed problem with forking processes failing
  38. 09/10/92 fjw  Added HPUX 8.07 support
  39. 09/02/94 fjw  Changed most of the manifest constant names to assist customisation
  40. 09/02/94 fjw  Rewrote many routines; made the printing customisable
  41. 29/04/94 fjw  Added AIX PIOBE command to print string; thanks to MAERSK Travel
  42. 23/08/94 cpz  Fixed undefined SIGCLD problem; added P,Q_CMDS_BSDI; Carl Zwanzig
  43.  
  44. */
  45.  
  46. #include <stdio.h>
  47. #include <sys/types.h>
  48. #include <errno.h>
  49. #include <ctype.h>
  50. #include <sys/stat.h>
  51. #include <signal.h>
  52. #include <string.h>
  53. #include <sys/time.h>
  54.  
  55. char *my_strdup();
  56. char *find_host();
  57. extern int debugmode;
  58.  
  59. #ifdef INT_SIG
  60. #define Void int
  61. #define Return return(0)
  62. #else
  63. #define Void void
  64. #define Return return
  65. #endif
  66.  
  67. #ifdef P_CMDS_SYSV32
  68. # ifdef P_TITLE_LOWERT
  69. #  define PRINT_COMMAND "/usr/bin/lp -d%queuename% -c -t%title% -s%debug%"
  70. # else
  71. #  define PRINT_COMMAND "/usr/bin/lp -d%queuename% -c -T%title% -s%debug%"
  72. # endif
  73. #endif
  74.  
  75. #ifdef P_CMDS_AIX
  76. # ifdef P_CMDS_AIX_ENSCRIPT
  77.   Error Only one of P_CMDS_AIX, P_CMDS_AIX_PIOBE and P_CMDS_AIX_ENSCRIPT may be defined
  78. # endif
  79. # ifdef P_CMDS_AIX_PIOBE
  80.   Error Only one of P_CMDS_AIX, P_CMDS_AIX_PIOBE and P_CMDS_AIX_ENSCRIPT may be defined
  81. # endif
  82. # define PRINT_COMMAND "/bin/enq -P%queuename% -r%remove% -c -T%title%"
  83. #endif
  84.  
  85. #ifdef P_CMDS_AIX_PIOBE
  86. # ifdef P_CMDS_AIX_ENSCRIPT
  87.   Error Only one of P_CMDS_AIX, P_CMDS_AIX_PIOBE and P_CMDS_AIX_ENSCRIPT may be defined
  88. # endif
  89. # ifdef P_CMDS_AIX
  90.   Error Only one of P_CMDS_AIX, P_CMDS_AIX_PIOBE and P_CMDS_AIX_ENSCRIPT may be defined
  91. # endif
  92. # define PRINT_COMMAND "/bin/enq -P%queuename% -o-dp -r%remove% -c -T%title%"
  93. #endif
  94.  
  95. #ifdef P_CMDS_AIX_ENSCRIPT
  96. # ifdef P_CMDS_AIX_ENSCRIPT
  97.   Error Only one of P_CMDS_AIX, P_CMDS_AIX_PIOBE and P_CMDS_AIX_ENSCRIPT may be defined
  98. # endif
  99. # ifdef P_CMDS_AIX
  100.   Error Only one of P_CMDS_AIX, P_CMDS_AIX_PIOBE and P_CMDS_AIX_ENSCRIPT may be defined
  101. # endif
  102. # define PRINT_COMMAND "/usr/bin/enscript -d%queuename% -q -t%title%"
  103. #endif
  104.  
  105. #ifdef P_CMDS_BSD
  106. # ifdef P_TITLE_LOWERT
  107. #  define PRINT_COMMAND "/usr/ucb/lpr -P %queuename% -r%remove% -t %title%"
  108. # else
  109. #  define PRINT_COMMAND "/usr/ucb/lpr -P %queuename% -r%remove% -T %title%"
  110. # endif
  111. #endif
  112.  
  113. #ifdef P_CMDS_BSDI
  114. # ifdef P_TITLE_LOWERT
  115. #  define PRINT_COMMAND "/usr/bin/lpr -P %queuename% -r%remove% -t %title%"
  116. # else
  117. #  define PRINT_COMMAND "/usr/bin/lpr -P %queuename% -r%remove% -T %title%"
  118. # endif
  119. #endif
  120.  
  121. #ifdef P_CMDS_SVR4
  122. # define PRINT_COMMAND "/usr/bin/lp -d %queuename% -c -s%debug% -t %title%"
  123. #endif
  124.  
  125. #ifdef Q_CMDS_BSD
  126. #   define LP_STATUS "/usr/ucb/lpq -P%s"
  127. #   define LP_REMOVE "/usr/ucb/lprm -P%s %d", printers[theprinter].queuename
  128. #   define LP_REMSUCCESS "dequeued"
  129. #endif
  130. #ifdef Q_CMDS_AIX
  131. #   define LP_STATUS "/bin/enq -q -P %s"
  132. #   define LP_REMOVE "/bin/enq -P %s -x%d", printers[theprinter].queuename
  133. #   define LP_REMFAILURE "enq"
  134. #endif
  135. #ifdef Q_CMDS_BSDI
  136. #   define LP_STATUS "/usr/bin/lpq -P%s"
  137. #   define LP_REMOVE "/usr/bin/lprm -P%s %d", printers[theprinter].queuename
  138. #   define LP_REMSUCCESS "dequeued"
  139. #endif
  140. #ifdef Q_CMDS_SVR4
  141. #   define LP_STATUS "/usr/bin/lpstat -p%s"
  142. #   define LP_REMOVE "/usr/bin/cancel %d"
  143. #   define LP_REMSUCCESS "cancelled"
  144. #endif
  145. #ifdef Q_CMDS_SCO
  146. #   define LP_STATUS "/usr/bin/lpstat -p%s -u"
  147. #   define LP_REMOVE "/usr/bin/cancel %s-%d", printers[theprinter].queuename
  148. #   define LP_REMSUCCESS "cancelled"
  149. #endif
  150.  
  151. #define PARSE_UNKNOWN   0
  152. #define PARSE_BSD       1
  153. #define PARSE_BWLPDOS   2
  154. #define PARSE_AIX       3
  155. #define PARSE_SCO       4
  156.  
  157. #define  WN_SUCCESS             0x00
  158. #define  WN_NET_ERROR           0x02
  159. #define  WN_ACCESS_DENIED       0x07
  160. #define  WN_JOB_NOT_FOUND       0x41
  161. #define  WN_BAD_QUEUE           0x43
  162. #define  WN_ALREADY_LOCKED      0x46
  163.  
  164. int
  165. my_fork(file)
  166. char *file;
  167. {
  168. int counter=0, pid;
  169.  
  170.     srand((int)time(NULL));
  171.     while (((pid=fork()) == -1) && (counter++ < 10)) {
  172.         if (debugmode) {
  173.             fprintf(stdout,"bwnfsd: [my_fork] had to sleep for %s\n",file);
  174.             fflush(stdout);
  175.         }
  176.         sleep(rand()%10);
  177.     }
  178.     if ((pid == -1) && debugmode)
  179.         fprintf(stdout,"bwnfsd: [my_fork] gave up on %s\n",file);
  180.  
  181.     return(pid);
  182. }
  183.  
  184. char *master_args[20], p_printer_format[5], p_title_format[5], p_debug_string[5];
  185. char print_command[255];
  186. int printer_removes_files=0;
  187.  
  188. char *
  189. get_token(start)
  190.     char *start;
  191. {
  192. static char *rememb;
  193. char *p;
  194.  
  195.     if (start != NULL)
  196.         rememb = start;
  197.     if (rememb == NULL)
  198.         return(NULL);
  199.     p = rememb;
  200.     while (*p && isspace(*p))
  201.         p++;
  202.     if (*p == '\0') {
  203.         rememb = NULL;
  204.         return(NULL);
  205.     }
  206.     rememb = p;
  207.     while (*rememb && !isspace(*rememb))
  208.         rememb++;
  209.     if (*rememb)
  210.         *rememb++ = '\0';
  211.     else
  212.         rememb = NULL;
  213.     return(p);
  214. }
  215.  
  216. int
  217. determine_print_command()
  218. {
  219. char *p, *p1;
  220. int i;
  221.  
  222.     strcpy(print_command, PRINT_COMMAND);
  223.     p = get_token(print_command);
  224.     if (!p) {
  225. /* error - no command in line */
  226.         return(0);
  227.     }
  228.     p1 = p + strlen(p) - 1;
  229.     while ((p1 > p) && (*p1 != '/'))
  230.         p1--;
  231.     if (p1 > p)
  232.         p1++;
  233.     i = 0;
  234.     master_args[i++] = p;
  235.     master_args[i++] = p1;
  236.     while ((p=get_token(NULL)) != NULL) {
  237.         if ((p1=strchr(p,'%')) != NULL) {
  238.             if (my_strnicmp(p1, "%queuename%", 11) == 0) {
  239.                 *(p1+1) = 's';
  240.                 *(p1+2) = '\0';
  241.                 strcpy(p_printer_format, p);
  242.                 master_args[i++] = p_printer_format;
  243.             } else if (my_strnicmp(p1, "%title%", 7) == 0) {
  244.                 *(p1+1) = 's';
  245.                 *(p1+2) = '\0';
  246.                 strcpy(p_title_format, p);
  247.                 master_args[i++] = p_title_format;
  248.             } else if (my_strnicmp(p1, "%debug%", 7) == 0) {
  249.                 *p1 = '\0';
  250.                 strcpy(p_debug_string, p);
  251.                 master_args[i++] = p_debug_string;
  252.             } else if (my_strnicmp(p1, "%remove%", 8) == 0) {
  253.                 *p1 = '\0';
  254.                 printer_removes_files = 1;
  255.                 master_args[i++] = p;
  256.             } else
  257.                 master_args[i++] = p;
  258.         } else
  259.             master_args[i++] = p;
  260.     }
  261.     master_args[i] = NULL;
  262.     if (debugmode) {
  263.         fprintf(stdout, "bwnfsd: [determine_print_command] Print command is:\nbwnfsd:        ");
  264.         for (i=0; master_args[i]; i++)
  265.             if (i != 1)
  266.                 fprintf(stdout, "%s ", master_args[i]);
  267.         fprintf(stdout, "\nbwnfsd: [determine_print_command] and does%sremove print files\n",
  268.              printer_removes_files?" ":" not ");
  269.     }
  270.     return(1);
  271. }
  272.  
  273. void
  274. default_print(file, printer, jobname)
  275. char *file, *printer, *jobname;
  276. {
  277. char *args[20], argprinter[50], argtitle[50];
  278. int mast, loc, wait_pid, pid;
  279.  
  280.     if (debugmode)
  281.         fprintf(stdout, "bwnfsd: [default_print] called\n");
  282.  
  283.     for (mast=0,loc=0; master_args[mast]; mast++,loc++) {
  284.         if (master_args[mast] == p_printer_format) {
  285. /* if no space, p_printer_format is "-d%s"
  286.    if space, p_printer_format is "%s" and the previous master_args was "-d"
  287.  */
  288.             sprintf(argprinter, p_printer_format, printer);
  289.             args[loc] = argprinter;
  290.         } else if (master_args[mast] == p_title_format) {
  291. /* if no space, p_title_format is "-t%s"
  292.    if space, p_title_format is "%s" and the previous master_args was "-t"
  293.  */
  294.             if (jobname) {
  295.                 sprintf(argtitle, p_title_format, jobname);
  296.                 args[loc] = argtitle;
  297.             } else {
  298.                 loc--;
  299.                 if (*p_title_format != '-')
  300.                     loc--;
  301.             }
  302.         } else if (master_args[mast] == p_debug_string) {
  303.             if (debugmode)
  304.                 args[loc] = p_debug_string;
  305.             else
  306.                 loc--;
  307.         } else
  308.             args[loc] = master_args[mast];
  309.     }
  310.     args[loc++] = file;
  311.     args[loc++] = NULL;
  312.  
  313.     chmod(file, 0777);
  314. #ifdef SIGCLD
  315.     signal(SIGCLD, SIG_IGN);
  316. #endif
  317. #ifdef SIGCHILD
  318.     signal(SIGCHILD, SIG_IGN);
  319. #endif
  320.     if (debugmode) {
  321.         fprintf(stdout, "bwnfsd: [default_print] execv(%s,\"", args[0]);
  322.         for (loc=0; args[loc]; loc++)
  323.             if (loc != 1)
  324.                 fprintf(stdout, "%s ", args[loc]);
  325.         fprintf(stdout, "\")\n");
  326.         fflush(stdout);
  327.     }
  328.     if (printer_removes_files) {
  329.         execv(args[0], &args[1]);
  330.  
  331. /*
  332.  * If we get here, it means that the print failed. We unlink the
  333.  * printfile to prevent lots of queued files. This may not be appropriate
  334.  * in your environment or for debugging purposes.
  335.  */
  336.  
  337.         if (debugmode)
  338.             fprintf(stdout, "bwnfsd: [default_print] print failed, unlinking %s\n", file);
  339.     } else {
  340.         if ((pid=my_fork(file)) == 0) {
  341.             execv(args[0],&args[1]);
  342.             if (debugmode)
  343.                 fprintf(stdout, "bwnfsd: [default_print] execv failed\n");
  344.             exit(1);
  345.         }
  346.         if (debugmode)
  347.             fprintf(stdout, "bwnfsd: [default_print] calling wait for pid %d\n", pid);
  348.         while (((wait_pid=wait(NULL)) != pid) && (wait_pid != -1))
  349.             ;
  350.  
  351. /*
  352.  * When we get here, we are waiting for the child process just created
  353.  * to complete (one way or the other) and let us know so that we can remove
  354.  * the spool file.  We have to wait, because there is no way that we can
  355.  * know when the print program has finished with the printfile.  We have the
  356.  * print program copy the file since it is possible for a PC user to reboot
  357.  * their machine and print again; this will result in a file with the same
  358.  * name being created over top of the file *we* are printing.  The copy
  359.  * option will result in the original file printed and the second lost.
  360.  * Failing to specify the copy option will result in a file being printed
  361.  * which is likely part of the first document and then an lp error (since the
  362.  * file went away, or was truncated).  This is a small window of vulnerability.
  363.  */
  364.  
  365.         if (debugmode)
  366.             fprintf(stdout, "bwnfsd: [default_print] unlinking print-file %s\n", file);
  367.     }
  368.     (void) unlink(file);
  369. }
  370.  
  371. void
  372. print_it(file, printer, jobname)
  373. char *file, *printer, *jobname;
  374. {
  375. struct printies {
  376.     char *name;
  377.     void (*routine)();
  378. };
  379.  
  380. static  struct printies print_list[] = {
  381.     "lp", default_print,
  382. /*
  383.  *      "your printer", your_printer_routine,
  384.  */
  385. };
  386.  
  387. #define PRINT_COUNT sizeof(print_list)/sizeof(struct printies)
  388.  
  389. int     i,tmp;
  390. struct stat buf;
  391.  
  392.     if (debugmode) {
  393.         fprintf(stdout, "bwnfsd: [print_it] called\n");
  394.         fprintf(stdout, "bwnfsd: Filename = %s\n", file);
  395.         fprintf(stdout, "bwnfsd: Jobname = %s\n", jobname);
  396.         fprintf(stdout, "bwnfsd: Printer = %s\n", printer);
  397.     }
  398.     if (stat(file,&buf) == 0) {
  399.         setgid(buf.st_gid);
  400.         setuid(buf.st_uid);
  401.     }
  402.  
  403.     for (i=0; i<PRINT_COUNT; i++)
  404.         if (strcmp(printer,print_list[i].name) == 0) {
  405.             if (debugmode)
  406.                 fprintf(stdout, "bwnfsd: [print_it] using %s\n", printer);
  407.                       (*print_list[i].routine)(file,printer,jobname);
  408.             return;
  409.         }
  410.     if (debugmode)
  411.         fprintf(stdout, "bwnfsd: [print_it] using default_print\n");
  412.     default_print(file, printer, jobname);
  413. }
  414.  
  415. #define WNPRQ_ACTIVE    0
  416. #define WNPRQ_PAUSE     1
  417. #define WNPRQ_ERROR     2
  418. #define WNPRQ_PENDING   3
  419. #define WNPRQ_PROBLEM   4
  420.  
  421. #define WNPRJ_QS_QUEUED 0
  422. #define WNPRJ_QS_PAUSE  1
  423. #define WNPRJ_QS_SPOOLING 2
  424. #define WNPRJ_QS_PRINTING 3
  425.  
  426. #define WNPRJ_DS_COMPLETE       0x8
  427. #define WNPRJ_DS_INTERV         0x10
  428. #define WNPRJ_DS_ERROR          0x20
  429. #define WNPRJ_DS_DESTOFFLIN     0x40
  430. #define WNPRJ_DS_DESTPAUSED     0x80
  431. #define WNPRJ_DS_NOTIFY         0x100
  432. #define WNPRJ_DS_DESTNOPAPER    0x200
  433. #define WNPRJ_DS_DESTFORMCHG    0x400
  434. #define WNPRJ_DS_DESTCRTCHG     0x800
  435. #define WNPRJ_DS_DESTPENCHG     0x1000
  436.  
  437. struct queueentry {
  438.     int jobid;
  439.     char *username;
  440.     char *params;
  441.     int queueposition;
  442.     int jobstatus;
  443.     unsigned long timesubmitted;
  444.     unsigned long size;
  445.     int copies;
  446.     char *jobcomment;
  447.     struct queueentry *next;
  448. };
  449.  
  450. struct printertype {
  451.     char *queuename;
  452.     char *queuecomment;
  453.     int queuestatus;
  454.     int numphysicalprinters;
  455.     unsigned long lasttime;
  456.     struct queueentry *head;
  457. };
  458.  
  459. extern struct printertype printers[];
  460.  
  461. void
  462. free_printer(theprinter)
  463.     int theprinter;
  464. {
  465. struct queueentry *p1, *p2;
  466.  
  467.     p1 = printers[theprinter].head;
  468.     while (p1) {
  469.         p2 = p1->next;
  470.         if (p1->username)
  471.             free(p1->username);
  472.         if (p1->params)
  473.             free(p1->params);
  474.         if (p1->jobcomment)
  475.             free(p1->jobcomment);
  476.         free(p1);
  477.         p1 = p2;
  478.     }
  479.     printers[theprinter].head = NULL;
  480. }
  481.  
  482. int no_response=0;
  483. int child_pid;
  484. FILE *thepipe;
  485. #ifndef USE_ALARM
  486. struct itimerval timer;
  487. #endif
  488.  
  489. static Void
  490. cancel_pipe(unused)
  491.     int unused;
  492. {
  493.     no_response = 1;
  494.     fclose(thepipe);
  495.     kill(child_pid, SIGKILL);
  496.     Return;
  497. }
  498.  
  499. void
  500. start_pipe_timer(n)
  501.     int n;
  502. {
  503.     signal(SIGALRM, cancel_pipe);
  504. #ifndef USE_ALARM
  505.     timer.it_interval.tv_usec = 0;
  506.     timer.it_interval.tv_sec = 0;
  507.     timer.it_value.tv_usec = 0;
  508.     timer.it_value.tv_sec = n;
  509.     setitimer(ITIMER_REAL, &timer, NULL);
  510. #else
  511.     alarm(n);
  512. #endif
  513.     no_response = 0;
  514. }
  515.  
  516. void
  517. stop_pipe_timer()
  518. {
  519. #ifndef USE_ALARM
  520.     timer.it_interval.tv_usec = 0;
  521.     timer.it_interval.tv_sec = 0;
  522.     timer.it_value.tv_usec = 0;
  523.     timer.it_value.tv_sec = 0;
  524.     setitimer(ITIMER_REAL, &timer, NULL);
  525. #else
  526.     alarm(0);
  527. #endif
  528.     signal(SIGALRM, SIG_IGN);
  529. }
  530.  
  531. FILE *
  532. my_popen(thecmd, timeout)
  533.     char *thecmd;
  534.     int timeout;
  535. {
  536. int fds[2], parent_fd, child_fd, pid, i;
  537.  
  538.     if (pipe(fds) < 0)
  539.         return(NULL);
  540.     parent_fd = fds[0];
  541.     child_fd = fds[1];
  542.     if ((pid=fork()) == 0) {
  543.         for (i=0; i<10; i++)
  544.             if (i != child_fd)
  545.                 close(i);
  546.         if (child_fd != 1) {
  547.             dup2(child_fd, 1);
  548.             close(child_fd);
  549.         }
  550.         dup2(1, 2);
  551.         execl("/bin/sh", "sh", "-c", thecmd, NULL);
  552.         exit(-1);
  553.     }
  554.     if (pid == -1) {
  555.         close(parent_fd);
  556.         close(child_fd);
  557.         return(NULL);
  558.     }
  559.     child_pid = pid;
  560.     close(child_fd);
  561.     start_pipe_timer(timeout);
  562.     thepipe = fdopen(parent_fd, "r");
  563.     return(thepipe);
  564. }
  565.  
  566. void
  567. my_pclose(fd)
  568.     FILE *fd;
  569. {
  570. int pid;
  571.  
  572.     stop_pipe_timer();
  573.     fclose(fd);
  574.     if (child_pid == -1)
  575.         return;
  576.     while (((pid=wait(NULL)) != child_pid) && (pid != -1))
  577.         ;
  578.     return;
  579. }
  580.  
  581. char *
  582. my_strstr(str1, str2)
  583.     char *str1, *str2;
  584. {
  585. char *a, *b, *c, *d;
  586. int len1=strlen(str1), len2=strlen(str2);
  587.  
  588.     if (len2 > len1)
  589.         return(NULL);
  590.     d = str1+(len1-len2)+1;
  591.     a = str1;
  592.     while (a < d) {
  593.         if (*a == *str2) {
  594.             b = a;
  595.             c = str2;
  596.             while (*c && (*b == *c)) {
  597.                 b++;
  598.                 c++;
  599.             }
  600.             if (*c == 0)
  601.                 return(a);
  602.         }
  603.         a++;
  604.     }
  605.     return(NULL);
  606. }
  607.  
  608. void
  609. add_entries(theprinter)
  610.     int theprinter;
  611. {
  612. char buffer[1024], *m, *n;
  613. FILE *p;
  614. int systype=PARSE_UNKNOWN, dropx=0, jobposition, j;
  615. struct queueentry *qe, **head= &printers[theprinter].head;
  616. unsigned long ip;
  617.  
  618.     free_printer(theprinter);
  619.     if (debugmode)
  620.         fprintf(stdout, "bwnfsd: [add_entries] called on %s\n", printers[theprinter].queuename);
  621.     printers[theprinter].queuestatus = WNPRQ_ACTIVE;
  622.     sprintf(buffer, LP_STATUS, printers[theprinter].queuename);
  623.     if ((p=my_popen(buffer, 10)) == NULL)
  624.         return;
  625.     while (fgets(buffer, sizeof(buffer)-1, p) != NULL) {
  626.         if (dropx > 0) {
  627.             dropx--;
  628.             continue;
  629.         }
  630.         if ((j=strlen(buffer)) == 0)
  631.             continue;
  632.         m = &buffer[j-1];
  633.         memset(m+1, 0, sizeof(buffer)-j-1);
  634.         if (*m == '\n')
  635.             *m-- = '\0';
  636.         while ((m>=buffer) && isspace(*m))
  637.             *m-- = '\0';
  638.         if (m < buffer)
  639.             continue;
  640.         if ((my_strnicmp(buffer,"Warning",7) != 0) && ((m=strchr(buffer,':')) != NULL)) {
  641.             for (n=buffer; n<m; n++)
  642.                 if (isspace(*n))
  643.                     break;
  644.             if (n >= m)
  645.                 memcpy(buffer, m+2, strlen(m+2)+1);
  646.         }
  647.         if (my_strnicmp(buffer,"Warning",7) == 0) {
  648.             systype = PARSE_BSD;
  649.             if ((my_strstr(buffer,"no daemon") != NULL) && (printers[theprinter].queuestatus == WNPRQ_ACTIVE))
  650.                 printers[theprinter].queuestatus = WNPRQ_PROBLEM;
  651.             if (my_strstr(buffer,"down") != NULL)
  652.                 printers[theprinter].queuestatus = WNPRQ_PAUSE;
  653.             continue;
  654.         }
  655.         if (my_strnicmp(buffer, "Rank ", 5) == 0) {
  656.             systype = PARSE_BSD;
  657.             continue;
  658.         }
  659.         if (strncmp(buffer, "*** Printer ", 12) == 0) {
  660.             systype = PARSE_BWLPDOS;
  661.             printers[theprinter].queuestatus = WNPRQ_PROBLEM;
  662.             dropx = 2;
  663.             jobposition = 1;
  664.             continue;
  665.         }
  666.         if (strncmp(buffer, "*** Exceeded ", 13) == 0) {
  667.             systype = PARSE_BWLPDOS;
  668.             printers[theprinter].queuestatus = WNPRQ_PROBLEM;
  669.             dropx = 2;
  670.             jobposition = 1;
  671.             continue;
  672.         }
  673.         if (strncmp(buffer, "   Job Id      Username", 23) == 0) {
  674.             systype = PARSE_BWLPDOS;
  675.             dropx = 1;
  676.             jobposition = 1;
  677.             continue;
  678.         }
  679.         if (strncmp(buffer, "Queue   Dev   Status   ", 23) == 0) {
  680.             systype = PARSE_AIX;
  681.             dropx = 1;
  682.             continue;
  683.         }
  684.         if (strncmp(buffer, "printer ", 7) == 0) {
  685.             systype = PARSE_SCO;
  686.             jobposition = 1;
  687.             if (my_strstr(buffer,"disabled") != NULL)
  688.                 printers[theprinter].queuestatus = WNPRQ_PAUSE;
  689.             continue;
  690.         }
  691.         switch (systype) {
  692.         case PARSE_UNKNOWN:
  693.             continue;
  694.             break;
  695.         case PARSE_AIX:
  696.             if (strncmp(&buffer[14],"DOWN",4) == 0) {
  697.                 printers[theprinter].queuestatus = WNPRQ_PROBLEM;
  698.                 continue;
  699.             }
  700.             if (buffer[24] == '\0')
  701.                 continue;
  702.             if ((qe=(struct queueentry *) malloc(sizeof(struct queueentry))) == NULL)
  703.                 continue;
  704.             qe->jobid = atoi(&buffer[24]);
  705.             for (m= &buffer[48]; !isspace(*m); )
  706.                 m++;
  707.             *m = '\0';
  708.             qe->username = my_strdup(&buffer[48]);
  709.             qe->queueposition = atoi(&buffer[76]);
  710.             for (m= &buffer[28]; !isspace(*m); )
  711.                 m++;
  712.             *m = '\0';
  713.             qe->params = my_strdup(&buffer[28]);
  714.             qe->size = atol(&buffer[67])*1024;
  715.             qe->copies = atoi(&buffer[73]);
  716.             if ((printers[theprinter].queuestatus == WNPRQ_ACTIVE) && (qe->queueposition == 1))
  717.                 qe->jobstatus = WNPRJ_QS_PRINTING;
  718.             else
  719.                 qe->jobstatus = WNPRJ_QS_QUEUED;
  720.             m = &buffer[28];
  721.             if ((n=strrchr(m, '/')) == NULL)
  722.                 n = m;
  723.             else
  724.                 n++;
  725.             if ((sscanf(n,"%lx",&ip) != 1) || (ip < 0x01000000L))
  726.                 qe->jobcomment = my_strdup("-");
  727.             else {
  728.                 sprintf(buffer,"queued from PC \"%s\"",find_host(ip));
  729.                 qe->jobcomment = my_strdup(buffer);
  730.             }
  731.             qe->timesubmitted = time(NULL);
  732.             qe->next = NULL;
  733.             *head = qe;
  734.             head = &qe->next;
  735.             break;
  736.         case PARSE_BWLPDOS:
  737.             if ((qe=(struct queueentry *) malloc(sizeof(struct queueentry))) == NULL)
  738.                 continue;
  739.             buffer[6] = '\0';
  740.             qe->jobid = atoi(buffer);
  741.             for (m= &buffer[16]; !isspace(*m); )
  742.                 m++;
  743.             *m = '\0';
  744.             qe->username = my_strdup(&buffer[16]);
  745.             qe->queueposition = jobposition++;
  746.             for (m= &buffer[31]; !isspace(*m); )
  747.                 m++;
  748.             *m++ = '\0';
  749.             qe->size = atol(&buffer[31]);
  750.             if ((*m == '\0') || (*m == ' '))
  751.                 qe->params = my_strdup("-");
  752.             else
  753.                 qe->params = my_strdup(m);
  754.             qe->timesubmitted = time(NULL);
  755.             qe->copies = -1;
  756.             if ((printers[theprinter].queuestatus == WNPRQ_ACTIVE) && (qe->queueposition == 1))
  757.                 qe->jobstatus = WNPRJ_QS_PRINTING;
  758.             else
  759.                 qe->jobstatus = WNPRJ_QS_QUEUED;
  760.             qe->jobcomment = my_strdup("-");
  761.             qe->next = NULL;
  762.             *head = qe;
  763.             head = &qe->next;
  764.             break;
  765.         case PARSE_BSD:
  766.             m = &buffer[strlen(buffer)-1];
  767.             while (isspace(*m) && (m>buffer))
  768.                 m--;
  769.             while (!isspace(*m) && (m>buffer))
  770.                 m--;
  771.             *m = '\0';
  772.             while (!isspace(*m) && (m>buffer))
  773.                 m--;
  774.             if (m <= buffer)
  775.                 continue;
  776.             if ((qe=(struct queueentry *) malloc(sizeof(struct queueentry))) == NULL)
  777.                 continue;
  778.             qe->size = atol(m);
  779.             while (isspace(*m) && (m>buffer))
  780.                 *m-- = '\0';
  781.             m = buffer;
  782.             while (isspace(*m) || isdigit(*m))
  783.                 m++;
  784.             while (!isspace(*m))
  785.                 m++;
  786.             *m++ = '\0';
  787.             qe->queueposition = atoi(buffer);
  788.             if ((printers[theprinter].queuestatus == WNPRQ_ACTIVE) && (qe->queueposition == 1))
  789.                 qe->jobstatus = WNPRJ_QS_PRINTING;
  790.             else
  791.                 qe->jobstatus = WNPRJ_QS_QUEUED;
  792.             while (isspace(*m))
  793.                 m++;
  794.             n = m;
  795.             while (!isspace(*m))
  796.                 m++;
  797.             *m++ = '\0';
  798.             qe->username = my_strdup(n);
  799.             while (isspace(*m))
  800.                 m++;
  801.             n = m;
  802.             while (!isspace(*m))
  803.                 m++;
  804.             *m++ = '\0';
  805.             qe->jobid = atoi(n);
  806.             while (isspace(*m))
  807.                 m++;
  808.             qe->params = my_strdup(m);
  809.             qe->timesubmitted = time(NULL);
  810.             qe->copies = -1;
  811.             if ((n=strrchr(m, '/')) == NULL)
  812.                 n = m;
  813.             else
  814.                 n++;
  815.             if ((sscanf(n,"%lx",&ip) != 1) || (ip < 0x01000000L))
  816.                 qe->jobcomment = my_strdup("-");
  817.             else {
  818.                 sprintf(buffer,"queued from PC \"%s\"",find_host(ip));
  819.                 qe->jobcomment = my_strdup(buffer);
  820.             }
  821.             qe->next = NULL;
  822.             *head = qe;
  823.             head = &qe->next;
  824.             break;
  825.  
  826.         case PARSE_SCO:
  827.             if (isspace(buffer[0]))
  828.                 continue;
  829.             m = strchr(buffer,'-');
  830.             if (m == NULL)
  831.                 continue;
  832.             *m++ = '\0';
  833.             if (strcmp(buffer,printers[theprinter].queuename) != 0)
  834.                 continue;
  835.             if ((qe=(struct queueentry *) malloc(sizeof(struct queueentry))) == NULL)
  836.                 continue;
  837.             qe->jobid = atoi(m);
  838.             for (; !isspace(*m); )
  839.                 m++;
  840.             for (; isspace(*m); )
  841.                 m++;
  842.             n = m;
  843.             for (; !isspace(*m); )
  844.                 m++;
  845.             *m++ = '\0';
  846.             qe->username = my_strdup(n);
  847.             qe->queueposition = jobposition++;
  848.             for (; isspace(*m); )
  849.                 m++;
  850.             qe->size = atol(m);
  851.             for (; !isspace(*m); )
  852.                 m++;
  853.             for (; isspace(*m); )
  854.                 m++;
  855.             qe->params = my_strdup(m);
  856.             qe->timesubmitted = time(NULL);
  857.             qe->copies = -1;
  858.             if (my_strstr(m," on") != NULL)
  859.                 qe->jobstatus = WNPRJ_QS_PRINTING;
  860.             else
  861.                 qe->jobstatus = WNPRJ_QS_QUEUED;
  862.             qe->jobcomment = my_strdup("-");
  863.             qe->next = NULL;
  864.             *head = qe;
  865.             head = &qe->next;
  866.             break;
  867.         }
  868.     }
  869.     printers[theprinter].lasttime = time(NULL);
  870.     my_pclose(p);
  871. }
  872.  
  873. int
  874. cancel_printjob(theprinter, username, jobid)
  875.     int theprinter, jobid;
  876.     char *username;
  877. {
  878. struct queueentry *qe=printers[theprinter].head;
  879. char buffer[1024];
  880. FILE *p;
  881.  
  882.     while (qe) {
  883.         if (qe->jobid == jobid) {
  884.             if (strcmp(qe->username, username) != 0)
  885.                 return(WN_ACCESS_DENIED);
  886.             else
  887.                 break;
  888.         }
  889.         qe = qe->next;
  890.     }
  891.     if (qe == NULL)
  892.         return(WN_JOB_NOT_FOUND);
  893.     sprintf(buffer, LP_REMOVE, jobid);
  894.     if ((p=my_popen(buffer, 10)) == NULL)
  895.         return(WN_NET_ERROR);
  896.     while (fgets(buffer, sizeof(buffer)-1, p) != NULL) {
  897.         if (buffer[strlen(buffer)-1] == '\n')
  898.             buffer[strlen(buffer)-1] = '\0';
  899. #ifdef LP_REMSUCCESS
  900.         if (my_strstr(buffer, LP_REMSUCCESS) != NULL) {
  901.             my_pclose(p);
  902.             return(WN_SUCCESS);
  903.         }
  904. #else
  905.         if (my_strstr(buffer, LP_REMFAILURE) != NULL) {
  906.             my_pclose(p);
  907.             return(WN_JOB_NOT_FOUND);
  908.         }
  909.  
  910. #endif
  911.     }
  912.     my_pclose(p);
  913. #ifdef LP_REMSUCCESS
  914.     return(WN_JOB_NOT_FOUND);
  915. #else
  916.     return(WN_SUCCESS);
  917. #endif
  918. }
  919.