home *** CD-ROM | disk | FTP | other *** search
- /*
- * $Author: brianb $
- * $Date: 1992/03/31 20:26:52 $
- * $Id: sendoprd.c,v 1.4 1992/03/31 20:26:52 brianb Exp $
- * $Source: /usr/src/usr.local/utilities/sendopr/RCS/sendoprd.c,v $
- *
- * Written by Hyman Wong -- August 1, 1991
- * Spooling routines by Reg Quinton.
- *
- * This program will copy messages coming from stdin to temporary files
- * on disk. Once all the input has been spooled to disk, the program
- * will try to create a "busy" lock by opening a file on disk called
- * ".busy". If the file already exists, which means there is another
- * copy of the daemon running, OPEN will cause an error and the program
- * will exit. If there is no .busy file, the current program is the only
- * copy running and it will then create the busy lock. It will then
- * change directory to the spool area and xmessage each file to the
- * operator's terminal one at a time and wait for the operator to click
- * the "okay" button before displaying the next message. When all
- * messages have been xmessaged, the program will remove the .busy file
- * and exit.
- */
-
- #include <stdio.h>
- #include <sysexits.h>
- #include <syslog.h>
- #include <signal.h>
- #include <sys/ioctl.h>
- #include <sys/file.h>
-
- #include "sendoprd.h"
-
- /* some global variables */
-
- char *display=DISPLAY;
- char *title=TITLE;
- char *name=NAME;
- int debug=0;
-
- /* copy one file to another */
-
- int copy(input,output)
- FILE *input,*output;
- {
- int c;
-
- while ((c=getc(input)) != EOF) fputc(c,output);
- fclose(input); fclose(output);
- }
-
- /* take care of a file, display it to the operator */
-
- show(text)
- char *text;
- {
- FILE *input;
- int pid,r;
-
- if (debug) fprintf(stderr,"Displaying %s\n",text);
-
- /* gotta have that file */
-
- if (!(input=fopen(text,"r"))) return(0);
-
- /* report fork problem if encountered */
-
- if ((pid=fork()) == -1)
- { syslog(LOG_CRIT,"Cannot fork");
- return(0);
- }
-
- /* parent waits until *all* children have died */
-
- if (pid)
- { fclose(input);
- if (debug) fprintf(stderr,"Parent waiting for children\n");
- for (pid=wait(&r); pid != -1; pid=wait(&r));
- if (debug) fprintf(stderr,"All children have terminated\n");
- return(1);
- }
-
- /* child closes all files and dups file to stdin */
-
- close(0); dup(fileno(input)); fclose(input);
-
- /* child does an exec */
-
- if (debug) fprintf(stderr,"Child execs %s\n",XMESSAGE);
- execl(XMESSAGE,XMESSAGE,"-display",display,
- "-title",title,"-name",name,"-",0);
- syslog(LOG_CRIT,"Cannot exec %s",XMESSAGE);
- exit(127); /* exec failed */
- }
-
- /* given a file, rename it into the spool. Return a success code */
-
- int spool(file)
- char *file;
- {
- char name[BUFSIZ];
- int q,tail,head;
-
- if ((q=open(SPLRC,O_RDWR | O_CREAT,0644)) < 0)
- { syslog(LOG_CRIT,"spool \"%s\" cannot open",SPLRC);
- return(0);
- };
-
- flock(q,LOCK_EX); lseek(q,0,L_SET);
-
- if ((read(q,&tail,sizeof(int)) != sizeof(int)) ||
- (read(q,&head,sizeof(int)) != sizeof(int))) tail=head=0;
-
- sprintf(name,"./%d",tail);
- if (rename(file,name) != 0)
- {
- flock(q,LOCK_UN); close(q);
- return(0);
- }
-
- if (debug) fprintf(stderr,"Spooled as number %d\n",tail);
-
- lseek(q,0,L_SET); tail++;
- write(q,&tail,sizeof(int));
- write(q,&head,sizeof(int));
-
- flock(q,LOCK_UN); close(q);
-
- return(1);
- }
-
- /* take care of the queue, return a success code */
-
- int unspool()
- {
- char name[BUFSIZ];
- int q,tail,head;
-
- if ((q=open(SPLRC,O_RDWR | O_CREAT, 0664)) < 0)
- {
- syslog(LOG_CRIT,"unspool \"%s\" cannot open\n",SPLRC);
- return(0);
- }
-
- if (debug) fprintf(stderr,"Unspooling\n");
- while (1)
- { flock(q,LOCK_EX); lseek(q,0,L_SET);
-
- if ((read(q,&tail,sizeof(int)) != sizeof(int)) ||
- (read(q,&head,sizeof(int)) != sizeof(int)))
- {
- lseek(q,0,L_SET); tail=head=0;
- write(q,&tail,sizeof(int));
- write(q,&head,sizeof(int));
- }
-
- if (tail == head)
- { flock(q,LOCK_UN); close(q);
- return(1);
- };
-
- /* ok got the head name, release the queue manager */
-
- flock(q,LOCK_UN);
-
- /* now do it, display the file */
-
- if (debug) fprintf(stderr,"Will display %d\n",head);
- sprintf(name,"./%d",head);
- if (!show(name)) return(0);
- unlink(name);
-
- /* now advance the queue */
-
- flock(q,LOCK_EX); lseek(q,0,L_SET);
-
- if ((read(q,&tail,sizeof(int)) != sizeof(int)) ||
- (read(q,&head,sizeof(int)) != sizeof(int)))
- {
- lseek(q,0,L_SET); tail=head=0;
- write(q,&tail,sizeof(int));
- write(q,&head,sizeof(int));
- }
-
- if (tail == head)
- { flock(q,LOCK_UN); close(q);
- return(1);
- };
-
- lseek(q,0,L_SET); head++;
-
- write(q,&tail,sizeof(int));
- write(q,&head,sizeof(int));
- flock(q,LOCK_UN);
- }
- }
-
- /* see Unix World Tutorial, Dec. 88 */
-
- void detach()
- {
- int i;
-
- /* let parent go quitely */
-
- if (fork()) exit(0);
-
- /* change process group */
-
- setpgrp(0,getpid());
-
- /* get rid of controlling tty */
-
- if ((i=open("/dev/tty",O_RDWR)) >= 0)
- {
- ioctl(i,TIOCNOTTY,0);
- close(i);
- }
-
- /* ignore key-board signals */
-
- signal(SIGHUP,SIG_IGN);
- signal(SIGINT,SIG_IGN);
- signal(SIGQUIT,SIG_IGN);
- signal(SIGTERM,SIG_IGN);
- signal(SIGTSTP,SIG_IGN);
-
- /* close all open files */
-
- for (i=0; i < 3; close(i++));
- }
-
- /* main program starts here */
-
- char *USAGE="Usage: sendoprd [-d display] [-t title] [-n name]\n";
-
- main(argc, argv)
- int argc;
- char *argv[];
- {
- int lockf,c;
- extern int optind;
- extern char *optarg;
- char *tmpfile="./tmp.XXXXXX";
- FILE *output;
-
- /* Some day, I'll put this into inetd ... */
-
- while ((c=getopt(argc,argv,"xd:t:n:")) != EOF)
- switch (c)
- {
- case 'x': debug++;
- break;
-
- case 'd': display=optarg;
- break;
-
- case 't': title=optarg;
- break;
-
- case 'n': name=optarg;
- break;
-
- default: fprintf(stderr,USAGE);
- exit(EX_USAGE);
- }
-
- /* we're going to gripe to syslog */
-
- openlog("sendopr",LOG_PID,LOG_DAEMON);
-
- /* go to the spool area */
-
- if (chdir(SPOOL) != 0)
- { syslog(LOG_CRIT,"Cannot chdir to %s\n",SPOOL);
- if (debug) fprintf(stderr,"Cannot chdir to %s\n",SPOOL);
- exit(EX_OSFILE);
- }
-
- umask(UMASK);
-
- /* copy the input to a file whose name is given by spool */
-
- mktemp(tmpfile);
-
- if (debug) fprintf(stderr,"Creating tmpfile %s\n",tmpfile);
-
- if (!(output=fopen(tmpfile,"w")))
- { syslog(LOG_CRIT,"can't create tempfile\n");
- exit(EX_OSFILE);
- }
-
- copy(stdin,output); spool(tmpfile);
-
- /* try to create the busy lock */
-
- if ((lockf=open(BUSYLOCK,O_WRONLY|O_CREAT, 644)) < 0)
- exit(EX_OSFILE);
- if (flock(lockf, LOCK_EX|LOCK_NB) >= 0)
- {
- if (debug) fprintf(stderr,"Busy lock created, will unspool\n");
- else detach();
- unspool();
- flock(lockf, LOCK_UN);
- close(lockf);
- unlink(BUSYLOCK);
- }
-
- exit(0);
- }
-
-