home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume23 / mlpd / printer.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-01-08  |  9.6 KB  |  374 lines

  1. /*
  2.  * Copyright (c) 1990 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms are permitted
  6.  * provided that the above copyright notice and this paragraph are
  7.  * duplicated in all such forms and that any documentation,
  8.  * advertising materials, and other materials related to such
  9.  * distribution and use acknowledge that the software was developed
  10.  * by the University of California, Riverside. 
  11.  *
  12.  * NOTE : That's Riverside.  Not Berkeley, not Santa Cruz, not even
  13.  *        Irvine.  Riverside.  Ri - ver - side.
  14.  *
  15.  * The name of the University may not be used to endorse or promote 
  16.  * products derived from this software without specific prior written
  17.  * permission.
  18.  *
  19.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  20.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  21.  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  22.  * 
  23.  * MLPD -- Multiple Line Printer Daemon (Version 1.3)
  24.  * SCCS keywords: @(#)printer.c    1.3 12/1/90
  25.  */
  26.  
  27. #include "config.h"
  28.  
  29. /*
  30. // check_base_printer() -- Check the main printer queue.
  31. //
  32. // This function will go through the main printer queue and see
  33. // whether or not there are any files to print out.  If there are,
  34. // notify the main program the number of files to print out.  We
  35. // mainly want to see that there are files to print, so that all
  36. // of the other printer queues can be checked.
  37. */
  38.  
  39. int check_base_printer()
  40. {
  41. #ifdef  SUN
  42.     struct dirent *d; 
  43. #else
  44.     struct direct *d;
  45. #endif
  46.     DIR *dirpointer; 
  47.     int nitems;
  48.  
  49.     /*
  50.     // First we open up the spooling directory for the main
  51.     // spooler.  Queueing should be allowed on this printer,
  52.     // but printing should be turned off.  We open up the
  53.     // directory to read the files in them.
  54.     */
  55.     (void)debug("Checking base printer spooling directory...\n");
  56.     if ((dirpointer = opendir(LP_SPOOL_DIRECTORY)) == NULL)
  57.     {
  58.         debug("Couldn't open directory.\n");
  59.         return -1;
  60.     }
  61.     nitems = 0;
  62.     /*
  63.     // Now, while we have the chance, let's check out the files
  64.     // in the directory and see whether something is printing or
  65.     // not (if nothing is printing, there won't be any files in
  66.     // the directory.  lpd will delete them off.)
  67.     */
  68.     while ((d = readdir(dirpointer)) != NULL)
  69.     {
  70.         debug("Checking files in directory.\n");
  71.         /*
  72.         // See if the file has a df* extension.
  73.         // This is the type of file that we want to use to 
  74.         // print out.
  75.         */
  76.         if (!strncmp(d->d_name, "cf", 2))
  77.         {
  78.             debug("Incrementing file count.\n");
  79.             ++nitems;
  80.         }
  81.     }
  82.     /*
  83.     // Now close off the directory, and get back to main().
  84.     */
  85.     (void)closedir(dirpointer);
  86.     return (nitems);
  87. }
  88.  
  89. /*
  90. // check_prs() -- Check each printer queue.
  91. //
  92. // This function will go through the each printer queue and see
  93. // whether or not there are any files to print out.  If there are,
  94. // notify the main program the printer is busy, otherwise tell the
  95. // main program that we would like a print job sent to us.  All of
  96. // the printer queues are checked through this machine.
  97. */
  98.  
  99. int check_prs(printers, cnt)
  100. printerstruct *printers;
  101. int cnt;
  102. {
  103. #ifdef  SUN
  104.     struct dirent *d; 
  105. #else
  106.     struct direct *d;
  107. #endif
  108.     DIR *dirpointer; 
  109.     int nitems;
  110.  
  111.     /*
  112.     // Try and create a char[] for the directory where 
  113.     // the printer is located.  
  114.     */
  115.     /*
  116.     // First we open up the spooling directory for our new
  117.     // spooler.  Printing should be allowed on this printer,
  118.     // but queueing should be turned off.  We open up the
  119.     // directory to read the files in them.
  120.     */
  121.     if ((dirpointer = opendir(printers->directory[cnt])) == NULL)
  122.     {
  123.         bomb("check_prs:opendir");
  124.         return -1;
  125.     }
  126.     nitems = 0;
  127.     /*
  128.     // Now, while we have the chance, let's check out the files
  129.     // in the directory and see whether something is printing or
  130.     // not.  If something is printing, then we don't want to send
  131.     // a job to this printer.  If nothing is printing, we want
  132.     // to ship out a job to the printer ASAP.
  133.     */
  134.     while ((d = readdir(dirpointer)) != NULL)
  135.     {
  136.         if (!strncmp(d->d_name, "cf", 2))
  137.         {
  138.             ++nitems;
  139.         }
  140.     }
  141.     /*
  142.     // Close off the directory pointer.
  143.     */
  144.     (void)closedir(dirpointer);
  145.     /*
  146.     // Return the number of files that are printing.
  147.     */
  148.     return(nitems);
  149. }
  150.  
  151. /*
  152. // print_file() -- Print out a file in the spool directory.
  153. //
  154. // First, we try to find a file in the directory where we have
  155. // specified that we are going to print from.  If we do, then we
  156. // take the job from one printer area to another, and "kick-start"
  157. // the new printer into printing out the jobs (We should have to
  158. // send a signal to lpd to get this job running.)
  159. */
  160.  
  161. int print_file(p, cnt)
  162. printerstruct *p;
  163. int cnt;
  164. {
  165. #ifdef  SUN
  166.     struct dirent *d; 
  167. #else
  168.     struct direct *d;
  169. #endif
  170.     DIR *dirpointer; 
  171.     int nitems;
  172.  
  173.     /*
  174.     // Open up the spooling directory.
  175.     */ 
  176.     (void)debug("Yes, I can now print out a file!\n");
  177.     if ((dirpointer = opendir(LP_SPOOL_DIRECTORY)) == NULL)
  178.     {
  179.         return -1;
  180.     }
  181.     nitems = 0;
  182.     /*
  183.     // Try to find some number of files to print out on the 
  184.     // printer.  If we find a file, we send that file to the new
  185.     // directory, and send a signal to the lpd program and 
  186.     // return back to the main program.  If we do not get any
  187.     // file from the directory, something must be messed up, so
  188.     // we need to return our exit status to the main program.
  189.     // While we are at it, we should pass along the control file 
  190.     // that goes with the data file, so that the printer can get 
  191.     // the proper information for the banner page, accounting, etc.
  192.     */
  193.     while (((d = readdir(dirpointer)) != NULL) && (nitems == 0))
  194.     {
  195.         /*
  196.         // Check to see that the file we want to print
  197.         // is a data file type in the directory.
  198.         */
  199.         if (!strncmp(d->d_name, "cf", 2))
  200.         {
  201.             /*
  202.             // Move the files.
  203.             */
  204.             (void)debug("I am now attempting to move the files.\n");
  205.             move_files(d->d_name, p, cnt);
  206.             /*
  207.             // Send off the signal to the lpd program.
  208.             // We never use the return value, though.
  209.             */
  210.             (void)debug("Starting up the printer.\n");
  211.             (void)send_lpd_signal(p->name[cnt]);
  212.             ++nitems;
  213.         }
  214.     }
  215.     /*
  216.     // Close off the directory.
  217.     */
  218.     (void)closedir(dirpointer);
  219.     if (nitems == 0)
  220.     {
  221.         bomb("readdir");
  222.     }
  223.     return(0);
  224. }
  225.  
  226. /*
  227. // move_files() -- move the files from one spooling directory to another.
  228. //
  229. // This function will move all of the files associated with a print job
  230. // to a new spooling directory.
  231. //
  232. // Arguments: char *cffile -- the name of the control file.
  233. //            printerstruct *p -- the printers structure.
  234. //            int cnt -- the index into printerstruct specifying the printer
  235. //                       directory to move the files to.
  236. */
  237. move_files(cffile, p, cnt)
  238. char *cffile;
  239. printerstruct *p;
  240. int cnt;
  241. {
  242.     char tmpbuf1[1024],tmpbuf2[1024],xbuf[1024],data[1024];
  243.     FILE *fp, *fopen();
  244.  
  245.     xbuf[0] = '\0'; data[0] = '\0';
  246.     (void)sprintf(xbuf, "%s/%s", LP_SPOOL_DIRECTORY, cffile);
  247.     (void)debug("Opening and reading control file");
  248.     if ((fp = fopen(xbuf, "r")) == NULL)
  249.     {
  250.         (void)debug("Bombing on fopen().\n");
  251.         bomb("move_files:fopen");
  252.     }
  253.     data[0] = '\0';
  254.     while (fgets(data, 1024, fp) > 0)
  255.     {
  256.         if (data[0] == 'f')
  257.         {
  258.             /* 
  259.             // Must be a file that we want...Move it.
  260.             */
  261.             (void)debug("Moving data file.\n");
  262.             tmpbuf1[0] = '\0'; tmpbuf2[0] = '\0';
  263.             data[strlen(data)-1] = '\0';
  264.             (void)sprintf(tmpbuf1,"%s/%s",LP_SPOOL_DIRECTORY,&data[1]);
  265.             (void)sprintf(tmpbuf2,"%s/%s",p->directory[cnt],&data[1]);
  266.             if (rename(tmpbuf1, tmpbuf2) != 0)
  267.             {
  268.                 bomb("move_files:fgets:rename");
  269.             }
  270.         }
  271.         data[0] = '\0';
  272.     }
  273.     (void)fclose(fp);
  274.     tmpbuf1[0] = '\0'; tmpbuf2[0] = '\0';
  275.     (void)sprintf(tmpbuf1, "%s/%s", LP_SPOOL_DIRECTORY,cffile);
  276.     (void)sprintf(tmpbuf2, "%s/%s", p->directory[cnt],cffile);
  277.     (void)debug("Moving control file.\n");
  278.     if (rename(tmpbuf1, tmpbuf2) != 0)
  279.     {
  280.         bomb("move_files:rename");
  281.     }
  282. }
  283.  
  284. /*
  285. // restart_all_printers() -- send a signal to restart all printers.
  286. //
  287. // We want to restart all printers when we first start up so that we can
  288. // clear jobs from those queues.  This will be run every 30 seconds.
  289. //
  290. // Arguments: int nop -- The total number of printers.
  291. //            printerstruct *printers -- the printers structure.
  292. */
  293.  
  294. int restart_all_printers(nop, printers)
  295. int nop;
  296. printerstruct *printers;
  297. {
  298.     int clt;
  299.  
  300.     for (clt = 0; clt < nop; ++clt)
  301.     {
  302.         (void)send_lpd_signal(printers->name[clt]);
  303.     }
  304. }
  305.  
  306. /*
  307. // send_lpd_signal() -- Send a signal to lpd to start printing from a printer.
  308. //
  309. // This function will create a socket, try and connect using that socket to
  310. // the default socket for the printer, and then if a connection can be made,
  311. // the printer is sent a control code to print out all files for a specific
  312. // printer.  If this returns a \0, then everything was okay.
  313. //
  314. // Arguments : char *printer; (Name of the printer to use)
  315. */
  316.  
  317. int send_lpd_signal(printer)
  318. char *printer;
  319. {
  320.     struct sockaddr_un server;
  321.     register int s, n;
  322.     char buf[1024];
  323.  
  324.     s = socket(AF_UNIX, SOCK_STREAM, 0);
  325.     if (s < 0) 
  326.     {
  327.         if (errno == EMFILE)
  328.         {
  329.             bomb("send_lpd_signal:socket:EMFILE");
  330.         }
  331.         else if (errno == ENFILE)
  332.         {
  333.             bomb("send_lpd_signal:socket:ENFILE");
  334.         }
  335.         else if (errno == ENOBUFS)
  336.         {
  337.             bomb("send_lpd_signal:socket:ENOBUFS");
  338.         }
  339.         bomb("send_lpd_signal:socket:dont_know");
  340.     }
  341.     server.sun_family = AF_UNIX;
  342. #ifndef lint
  343.     (void)strcpy((char *)server.sun_path, (char *)"/dev/printer");
  344. #endif
  345.     if ((int)connect(s, (struct sockaddr *)&server, (int)strlen(server.sun_path) + 2) < 0) 
  346.     {
  347.         bomb("connect");
  348.         (void) close(s);
  349.         return(0);
  350.     }
  351.     (void) sprintf(buf, "\1%s\n", printer);
  352.     n = strlen(buf);
  353.     if (write(s, buf, n) != n) 
  354.     {
  355.         bomb("write");
  356.         (void) close(s);
  357.         return(0);
  358.     }
  359.     if (read(s, buf, 1) == 1) 
  360.     {
  361.         if (buf[0] == '\0') 
  362.         {
  363.             (void)close(s);
  364.             return(1);
  365.         }
  366.         (void)putchar(buf[0]);
  367.     }
  368.     while ((n = read(s, buf, sizeof(buf))) > 0)
  369.         (void)fwrite(buf, 1, n, stdout);
  370.     (void)close(s);
  371.     (void)debug("Signal has been sent to the printer %s.\n");
  372.     return(0);
  373. }
  374.