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