david@wiley.UUCP (David Hull) (02/22/90)
I've written a replacement for biff/comsat that works even when the mail spool directory is mounted over NFS and the mail is being delivered on another machine. It wakes up every minute and stats the user's mail file to decide whether he has received any new mail. The program should automatically die when the user logs out. I'd like it to receive a SIGHUP when its parent, the login shell, exits, but haven't been able to make it work. Aren't all the processes in the same process group as the login supposed to receive a SIGHUP when it exits? The program works now by calling getppid right before it stats the file. If the parent has exited, init has inherited the program and the ppid is 1. It works but seems inelegant. Does anybody have any help? -David --------------------------------------- David Hull TRW Inc. Redondo Beach, CA david%wiley.uucp@csvax.caltech.edu ...!{uunet,cit-vax}!wiley!david
bgg@yarra.oz.au (Benjamin G. Golding) (02/23/90)
In article <8948@wiley.UUCP> david@wiley.UUCP (David Hull) writes: > I've written a replacement for biff/comsat that works even when the > mail spool directory is mounted over NFS and the mail is being delivered > on another machine. It wakes up every minute and stats the user's mail > file to decide whether he has received any new mail. > > The program should automatically die when the user logs out. Why not reorganise the order of the programs? If you make your comsat replacement the login shell and have it fork and wait for an interactive shell to exit before your program exits. A timer could interrupt the wait() to tell it when to check for new mail. The wait() needs to be in a while loop so that it will resume if it was interrupted (on unixes without restartable system calls). It sounds simpler anyway. Ben.
tony@oha.UUCP (Tony Olekshy) (02/25/90)
In message <1416@yarra.oz.au>, bgg@yarra.oz.au (Benjamin G. Golding) writes: > > In article <8948@wiley.UUCP> david@wiley.UUCP (David Hull) writes: > > I've written a replacement for biff/comsat that works even when the > > mail spool directory is mounted over NFS and the mail is being delivered > > on another machine. It wakes up every minute and stats the user's mail > > file to decide whether he has received any new mail. > > > > The program should automatically die when the user logs out. > > Why not reorganise the order of the programs? Well, that's one way, or you could have the parent spawn both the shell and mail watcher and kill the living when either dies, or fiddle something with SIGHUP (I think), or have the child try to kill(parent_id, 0) once around each loop. However, the following will also work as long as the parent doesn't close the writing end of the pipe until it is exiting. You should clean it up to check all return codes, of course. Interested readers are referred to the pipe, read, and exit man pages: From pipe: Description fildes[0] is opened for reading and fildes[1] is opened for writing and the O_NDELAY flag is clear. The descriptors remain open across fork system calls... From read: When attempting to read from an empty pipe: If O_NDELAY is clear, the read will block until data is written to the file or the file is no longer open for writing. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ read will fail if one or more of the following are true: A signal was caught during the read system call. [EINTR] From exit: All of the file descriptors open in the calling process are closed. ---------------------------------------------------------------------------- #include <stdio.h> #include <signal.h> #include <errno.h> #define CHILD_CYCLE 2 /* Delay between child ops. */ childWork() { alarm(0); /* Put your mail watching code here. */ fprintf(stderr, "Child working!\n"); } main() { int pfd[2]; int pid; char byte; if (pipe(pfd) == -1) perror("pipe"); switch (pid = fork()) { case -1: perror("fork"); exit (1); case 0: /* Child */ close(pfd[1]); signal(SIGINT, SIG_IGN); fprintf(stderr, "Child %d running...\n", getpid()); while (1) { alarm(CHILD_CYCLE); signal(SIGALRM, childWork); errno = 0; read(pfd[0], &byte, 1); /* Blocks till write or sig. */ switch (errno) { case 0: /* Parent exit closed pipe. */ fprintf(stderr, "Child %d done.\n", getpid()); exit (0); case EINTR: /* Alarm rang through childWork. */ break; default: /* Hmmm? */ fprintf(stderr, "Child read errno %d.\n", errno); exit (1); } } /* NOTREACHED */ default: /* Parent */ break; } close(pfd[0]); fprintf(stderr, "Parent %d execing shell, ^D to stop...\n", getpid()); execl("/bin/sh", "sh", NULL); perror("exec"); exit (1); } -- Yours, etc., Tony Olekshy (...!alberta!oha!tony or tony@oha.UUCP).