home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume30 / sendopr / part01 / sendoprd.c < prev    next >
C/C++ Source or Header  |  1992-06-20  |  7KB  |  311 lines

  1. /* 
  2.  * $Author: brianb $
  3.  * $Date: 1992/03/31 20:26:52 $ 
  4.  * $Id: sendoprd.c,v 1.4 1992/03/31 20:26:52 brianb Exp $
  5.  * $Source: /usr/src/usr.local/utilities/sendopr/RCS/sendoprd.c,v $
  6.  *
  7.  * Written by Hyman Wong -- August 1, 1991
  8.  * Spooling routines by Reg Quinton.
  9.  *
  10.  * This program will copy messages  coming from stdin  to temporary files
  11.  * on disk.   Once all the input  has been spooled  to  disk, the program
  12.  * will try to  create a "busy"  lock by  opening  a  file on disk called
  13.  * ".busy".  If  the file already exists, which  means  there  is another
  14.  * copy of the daemon running, OPEN  will cause an  error and the program
  15.  * will exit.  If there is no .busy file, the current program is the only
  16.  * copy running and it  will then create  the busy  lock.  It  will  then
  17.  * change  directory to  the  spool area  and xmessage  each  file to the
  18.  * operator's terminal one at  a time and  wait for the operator to click
  19.  * the   "okay" button before  displaying  the   next message.  When  all
  20.  * messages  have been xmessaged, the  program will remove the .busy file
  21.  * and exit.
  22.  */
  23.  
  24. #include    <stdio.h>
  25. #include    <sysexits.h>
  26. #include    <syslog.h>
  27. #include    <signal.h>
  28. #include    <sys/ioctl.h>
  29. #include    <sys/file.h>
  30.  
  31. #include     "sendoprd.h"
  32.  
  33. /* some global variables */
  34.  
  35. char    *display=DISPLAY;
  36. char    *title=TITLE;
  37. char    *name=NAME;
  38. int    debug=0;
  39.  
  40. /* copy one file to another */
  41.  
  42. int copy(input,output)
  43. FILE    *input,*output;
  44. {    
  45.     int    c;
  46.  
  47.     while ((c=getc(input)) != EOF) fputc(c,output);
  48.     fclose(input);    fclose(output);
  49. }
  50.  
  51. /* take care of a file, display it to the operator */
  52.  
  53. show(text)
  54. char    *text;
  55. {
  56.     FILE    *input;
  57.     int    pid,r;
  58.  
  59.     if (debug) fprintf(stderr,"Displaying %s\n",text);
  60.  
  61.     /* gotta have that file */
  62.  
  63.     if (!(input=fopen(text,"r"))) return(0);
  64.  
  65.         /*      report fork problem if encountered    */
  66.  
  67.         if ((pid=fork()) == -1)
  68.         {       syslog(LOG_CRIT,"Cannot fork");
  69.                 return(0);
  70.         }
  71.  
  72.         /*      parent waits until *all* children have died    */
  73.  
  74.         if (pid)
  75.         {       fclose(input);
  76.         if (debug) fprintf(stderr,"Parent waiting for children\n");
  77.                 for (pid=wait(&r); pid != -1; pid=wait(&r));
  78.         if (debug) fprintf(stderr,"All children have terminated\n");
  79.                 return(1);
  80.         }
  81.  
  82.         /*      child closes all files and dups file to stdin    */
  83.  
  84.         close(0);       dup(fileno(input));     fclose(input);
  85.  
  86.         /*      child does an exec      */
  87.  
  88.     if (debug) fprintf(stderr,"Child execs %s\n",XMESSAGE);
  89.         execl(XMESSAGE,XMESSAGE,"-display",display,
  90.             "-title",title,"-name",name,"-",0);
  91.         syslog(LOG_CRIT,"Cannot exec %s",XMESSAGE);
  92.         exit(127);      /*      exec failed     */
  93. }
  94.     
  95. /* given a file, rename it into the spool. Return a success code */
  96.  
  97. int    spool(file)
  98. char    *file;
  99. {
  100.     char    name[BUFSIZ];
  101.     int    q,tail,head;
  102.  
  103.     if ((q=open(SPLRC,O_RDWR | O_CREAT,0644)) < 0)
  104.     {    syslog(LOG_CRIT,"spool \"%s\" cannot open",SPLRC);
  105.         return(0);
  106.     };
  107.  
  108.     flock(q,LOCK_EX);    lseek(q,0,L_SET);
  109.  
  110.     if ((read(q,&tail,sizeof(int)) != sizeof(int)) ||
  111.         (read(q,&head,sizeof(int)) != sizeof(int))) tail=head=0;
  112.  
  113.     sprintf(name,"./%d",tail);
  114.     if (rename(file,name) != 0)
  115.     {    
  116.         flock(q,LOCK_UN);    close(q);
  117.         return(0);
  118.     }
  119.  
  120.     if (debug) fprintf(stderr,"Spooled as number %d\n",tail);
  121.  
  122.     lseek(q,0,L_SET);    tail++;
  123.     write(q,&tail,sizeof(int));
  124.     write(q,&head,sizeof(int));
  125.  
  126.     flock(q,LOCK_UN);    close(q);
  127.  
  128.     return(1);
  129. }
  130.  
  131. /*    take care of the queue, return a success code    */
  132.  
  133. int    unspool()
  134. {
  135.     char    name[BUFSIZ];
  136.     int    q,tail,head;
  137.  
  138.     if ((q=open(SPLRC,O_RDWR | O_CREAT, 0664)) < 0)
  139.     {
  140.         syslog(LOG_CRIT,"unspool \"%s\" cannot open\n",SPLRC);
  141.         return(0);
  142.     }
  143.  
  144.     if (debug) fprintf(stderr,"Unspooling\n");
  145.     while (1)
  146.     {    flock(q,LOCK_EX);    lseek(q,0,L_SET);
  147.  
  148.         if ((read(q,&tail,sizeof(int)) != sizeof(int)) ||
  149.             (read(q,&head,sizeof(int)) != sizeof(int)))
  150.         {
  151.             lseek(q,0,L_SET);    tail=head=0;
  152.             write(q,&tail,sizeof(int));
  153.             write(q,&head,sizeof(int));
  154.         }
  155.  
  156.         if (tail == head)
  157.         {    flock(q,LOCK_UN);    close(q);
  158.             return(1);
  159.         };
  160.  
  161.         /* ok got the head name, release the queue manager */
  162.  
  163.         flock(q,LOCK_UN);
  164.  
  165.         /* now do it, display the file */
  166.  
  167.         if (debug) fprintf(stderr,"Will display %d\n",head);
  168.         sprintf(name,"./%d",head);
  169.         if (!show(name)) return(0);
  170.         unlink(name);
  171.     
  172.         /* now advance the queue */
  173.  
  174.         flock(q,LOCK_EX);    lseek(q,0,L_SET);
  175.  
  176.         if ((read(q,&tail,sizeof(int)) != sizeof(int)) ||
  177.             (read(q,&head,sizeof(int)) != sizeof(int)))
  178.         {
  179.             lseek(q,0,L_SET);    tail=head=0;
  180.             write(q,&tail,sizeof(int));
  181.             write(q,&head,sizeof(int));
  182.         }
  183.  
  184.         if (tail == head)
  185.         {    flock(q,LOCK_UN);    close(q);
  186.             return(1);
  187.         };
  188.  
  189.         lseek(q,0,L_SET);    head++;
  190.  
  191.         write(q,&tail,sizeof(int));
  192.         write(q,&head,sizeof(int));
  193.         flock(q,LOCK_UN);
  194.     }
  195. }
  196.  
  197. /* see Unix World Tutorial, Dec. 88 */
  198.  
  199. void    detach()
  200. {
  201.     int    i;
  202.  
  203.     /* let parent go quitely */
  204.  
  205.     if (fork()) exit(0);
  206.     
  207.     /* change process group */
  208.  
  209.         setpgrp(0,getpid());
  210.  
  211.         /* get rid of controlling tty */
  212.  
  213.         if ((i=open("/dev/tty",O_RDWR)) >= 0)
  214.         {
  215.             ioctl(i,TIOCNOTTY,0);
  216.                 close(i);
  217.         }
  218.  
  219.         /*  ignore key-board signals */
  220.  
  221.         signal(SIGHUP,SIG_IGN);
  222.         signal(SIGINT,SIG_IGN);
  223.         signal(SIGQUIT,SIG_IGN);
  224.         signal(SIGTERM,SIG_IGN);
  225.         signal(SIGTSTP,SIG_IGN);
  226.  
  227.         /* close all open files */
  228.  
  229.         for (i=0; i < 3; close(i++));
  230. }
  231.     
  232. /* main program starts here */
  233.  
  234. char    *USAGE="Usage: sendoprd [-d display] [-t title] [-n name]\n";
  235.  
  236. main(argc, argv)
  237. int    argc;
  238. char    *argv[];
  239. {
  240.     int    lockf,c;
  241. extern    int    optind;
  242. extern     char    *optarg;
  243.     char    *tmpfile="./tmp.XXXXXX";
  244.     FILE    *output;
  245.  
  246.     /* Some day, I'll put this into inetd ... */
  247.  
  248.     while ((c=getopt(argc,argv,"xd:t:n:")) != EOF)
  249.         switch (c)
  250.         {
  251.         case 'x':    debug++;
  252.                 break;
  253.  
  254.         case 'd':    display=optarg;
  255.                 break;
  256.  
  257.         case 't':    title=optarg;
  258.                 break;
  259.  
  260.         case 'n':    name=optarg;
  261.                 break;
  262.  
  263.         default:    fprintf(stderr,USAGE);
  264.                 exit(EX_USAGE);
  265.         }
  266.     
  267.     /* we're going to gripe to syslog */
  268.  
  269.     openlog("sendopr",LOG_PID,LOG_DAEMON);
  270.  
  271.     /* go to the spool area */
  272.  
  273.     if (chdir(SPOOL) != 0) 
  274.     {    syslog(LOG_CRIT,"Cannot chdir to %s\n",SPOOL);
  275.         if (debug) fprintf(stderr,"Cannot chdir to %s\n",SPOOL);
  276.         exit(EX_OSFILE);
  277.     }
  278.  
  279.     umask(UMASK);
  280.  
  281.     /* copy the input to a file whose name is given by spool */
  282.  
  283.     mktemp(tmpfile);    
  284.  
  285.     if (debug) fprintf(stderr,"Creating tmpfile %s\n",tmpfile);
  286.  
  287.     if (!(output=fopen(tmpfile,"w")))
  288.     {    syslog(LOG_CRIT,"can't create tempfile\n");
  289.         exit(EX_OSFILE);
  290.     }
  291.  
  292.     copy(stdin,output);    spool(tmpfile);
  293.  
  294.     /* try to create the busy lock */
  295.  
  296.     if ((lockf=open(BUSYLOCK,O_WRONLY|O_CREAT, 644)) < 0)
  297.         exit(EX_OSFILE);
  298.     if (flock(lockf, LOCK_EX|LOCK_NB) >= 0)
  299.     {
  300.         if (debug) fprintf(stderr,"Busy lock created, will unspool\n");
  301.         else detach();
  302.         unspool();
  303.         flock(lockf, LOCK_UN);
  304.         close(lockf);
  305.         unlink(BUSYLOCK);
  306.     }
  307.  
  308.     exit(0);
  309. }
  310.  
  311.