sewilco@mecc.UUCP (Scot E. Wilcoxon) (03/04/86)
This program executes a command on a specified tty port. I'd like to get it to work on a port which has a getty inactive on it, but haven't yet figured out how to do that easily. In the meantime it is being extremely useful for running reports at night (SMC seems to think that human intervention should be needed for all business reports). I do prefer mod.sources, but I'll start this program here since it is both small and of limited interest. Suggestions for improvements are welcome. Scot E. Wilcoxon Minn. Ed. Comp. Corp. quest!mecc!sewilco 45 03 N / 93 08 W (612)481-3507 {ihnp4,mgnetp}!dicome!mecc!sewilco -------------------------nibble here -------------------------------- #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create the files: # totty.c # This archive created: Mon Mar 3 16:37:36 1986 export PATH; PATH=/bin:$PATH if test -f 'totty.c' then echo shar: will not over-write existing file "'totty.c'" else cat << \SHAR_EOF > 'totty.c' /* totty.c - assign a process to an unused tty ** Author: Scot E. Wilcoxon, MECC (ihnp4!mecc!sewilco) 86/01/15 ** ** Format of Call: ** ** totty device-pathname command [args] ** ** device-pathname - pathname of device to assign to ** command - command to execute ** [args] - optional arguments to command ** */ /* This program causes a command to be executed under control * of a specified device (usually a tty port). * * Applications: * * Any program which requires use of /dev/tty. * To allow crontab entries for SMC BASIC, which requires /dev/tty * (and doesn't support standard in/out..sigh). * A program to shutdown when temperature or power (UPS) problem * occurs uses the Lisa mouse button, which requires /dev/tty. * * How it works: * * 1. Close standard in/out/error so as to not inherit them. * 2. Make an orphan process. * 3. Declare the orphan to be leader of the process group. * 4. Assign the desired device as standard in/out/error. * 5. Execute the desired command as an orphan which does not mind * the parent disappearing. * * Step 1 avoids the orphan from being considered part of the original * process group. * Step 2 isolates the new process from the previous process grouping. * Steps 3 and 4 are what define the tty group owner by meeting the * kernel's requirements when the orphan opens standard input. * Step 5 tries to keep things clean by having an orphan do the real work. * * System: * XENIX 3.0 (Priam) on Apple Lisa * * Bugs: * * Only works when called by a process which is not a member of a * tty group. These are identified by "?" in the TTY column of * "ps -ef". Known to work in /etc/rc and crontab. * * Does not work when the device has processes assigned to it, * specifically getty. Known to work on a tty port with getty * disabled. * * The device name must be a pathname. Should allow (or assume) * implied "/dev/" prefix. * * No formal man page. Author does not have XENIX Text Development * System, thus no nroff/troff. */ #define DAEMON /* if DAEMON, don't give up easily */ #include <sys/ioctl.h> #include <fcntl.h> #include <stdio.h> #include <signal.h> extern errno; #ifndef void typedef int void; /* XENIX 3.0 only has a system void */ #endif main(argc, argv) int argc; char **argv; { int forkvalue; /* value of fork */ if ( argc < 3 ) { printf("usage: %s tty_device command [args]\n",argv[0]); exit(1); } if ( fclose(stdin) ) perror("totty: stdin fclose"); if ( fclose(stdout) ) perror("totty: stdout fclose"); if ( fclose(stderr) ) perror("totty: stderr fclose"); if ( close(0) ) perror("totty: STDIN close"); if ( close(1) ) perror("totty: STDOUT close"); if ( close(2) ) perror("totty: STDERR close"); #ifdef DAEMON while ( (forkvalue=fork()) == -1 ) sleep(60); /* keep trying until forked */ #else if ( (forkvalue=fork()) == -1 ) exit(1); /* die if can't fork */ #endif if ( forkvalue != 0 ) exit(0); /* if parent, die. */ (void)setpgrp(); /* become process group leader */ if ( open(argv[1],O_RDONLY|O_NDELAY) < 0 ) perror("totty: stdin open"); if ( open(argv[1],O_WRONLY) < 0 ) perror("totty: stdout open"); if ( open(argv[1],O_WRONLY) < 0 ) perror("totty: stderr open"); if ( fopen(argv[1],"r") == NULL ) perror("totty: stdin open"); if ( fopen(argv[1],"w") == NULL ) perror("totty: stdout open"); if ( fopen(argv[1],"w") == NULL ) perror("totty: stderr open"); (void)signal(SIGHUP,SIG_IGN); /* have child ignore death of tty group leader */ #ifdef DAEMON while ( (forkvalue=fork()) == -1 ) sleep(60); /* keep trying until forked */ #else if ( (forkvalue=fork()) == -1 ) exit(1); /* die if can't fork */ #endif if ( forkvalue != 0 ) exit(0); /* if parent, die. */ (void)execvp( argv[2], &argv[2] ); /* execute desired command */ exit(1); } SHAR_EOF fi # end of overwriting check # End of shell archive exit 0 -- Scot E. Wilcoxon Minn. Ed. Comp. Corp. quest!mecc!sewilco 45 03 N / 93 15 W (612)481-3507 {ihnp4,mgnetp}!dicome!mecc!sewilco