moss@ptsfa.UUCP (01/20/88)
Comp.sources.misc: Volume 2, Issue 14 Submitted-By: <moss@ptsfa.UUCP> Archive-Name: psmon [The only BSD porting needed should be termio-relative stuff. ++bsa] Here's a submission for a simple monitor program for Postscript error messages. It was written for SYS5 line printer spooling, and writes printer-detected error messages into a status file, along with the user's name and lp job id number. Ken Keirnan ------------------------------cut 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: # Makefile # README # ps.monitor.c # This archive created by Ken Keirnan, Mon Jan 18 09:04:19 1988 export PATH; PATH=/bin:$PATH if test -f 'Makefile' then echo shar: will not over-write existing file "'Makefile'" else cat << \SHAR_EOF > 'Makefile' CFLAGS = -O -s # Uncomment the CLIB line if you have SYS5 shared libraries # CLIB = -lc_s all: ps.monitor ps.monitor: ps.monitor.c cc $(CFLAGS) -o ps.monitor ps.monitor.c $(CLIB) install: all mv ps.monitor /usr/lib/ps.monitor chown lp /usr/lib/ps.monitor chgrp sys /usr/lib/ps.monitor chmod 4755 /usr/lib/ps.monitor SHAR_EOF chmod +x 'Makefile' fi # end of overwriting check if test -f 'README' then echo shar: will not over-write existing file "'README'" else cat << \SHAR_EOF > 'README' Ps.monitor is a program to monitor and log input from a tty line connected to a PostScript printer. It creates a log file "/usr/spool/lp/ps.error" and a lock file "/usr/spool/lp/PS_LOCK" to prevent multiple instances of the program. Ps.monitor will clean up the lock file and stop on a SIGTERM. When ps.monitor starts, it move an existing "ps.error" file to "Ops.error", and writes the date and time as the first line in the new "ps.error" file. To make the program just type "make". To make the program and install in /usr/lib type "make install". The program is kept in /usr/lib/ps.monitor, and is called with two arguments, the baud rate of the tty port, and the ttyxx name (without the "/dev/") as in: /usr/lib/ps.monitor 9600 tty22 In the system startup files or wherever the lineprinter startup is called (such as /etc/rc or /etc/rc2.d, etc.), the following lines should be added: rm -f /usr/spool/lp/PS_LOCK /usr/lib/ps.monitor <baud> <ttyxx> where <baud> is baud rate of the tty device and <ttyxx> is the tty name in the "/dev" directory. Also, if the printer driver or interface is a shell procedure, a line similar to the following could be used to keep track of the user, job id and time in the "ps.error" file: echo "<$JOB>, <$USER>, `/bin/date`" >> /usr/spool/lp/ps.error The location of the lock file and the error log can be changed by modifying the defines for LOCK, PSERR and OPSERR near the beginning of the program, and the directory containing the program can be changed in the Makefile. Precautions: The program was intended for SYS5 line printer spooling systems, and may require modifications for use on other flavors of Unices..... Ken Keirnan Pacific [*] Bell Minicomputer Operations Support Staff San Ramon, CA. 94583 (415) 823-3911 {ames,pyramid,sun}!pacbell!pt06a!kk1 or {ames,pyramid,sun}!ptsfa!pt06a!kk1 SHAR_EOF chmod +x 'README' fi # end of overwriting check if test -f 'ps.monitor.c' then echo shar: will not over-write existing file "'ps.monitor.c'" else cat << \SHAR_EOF > 'ps.monitor.c' /* * ps.monitor - log output from PostScript printer * * This program will monitor a tty port for error/diagnostic messages * from a PostScript printer, and log them in /usr/spool/lp/ps.error. * The program runs as a daemon (places itself in the background and * ignores most interrupts), and will stop cleanly on SIGTERM. A lock * file (/usr/spool/lp/PS_LOCK) is created to prevent multiple instances * of the program, and the lock may have to be removed manually if the * program is stopped with other than SIGTERM. * * To compile: cc -O -s -o /usr/lib/ps.monitor ps.monitor.c * chown lp /usr/lib/ps.monitor * chmod 4755 /usr/lib/ps.monitor * * Usage: /usr/lib/ps.monitor <baud> <ttyxx> */ #include <fcntl.h> #include <signal.h> #include <stdio.h> #include <termio.h> #include <time.h> #define LOCK "/usr/spool/lp/PS_LOCK" #define PSERR "/usr/spool/lp/ps.error" #define OPSERR "/usr/spool/lp/Ops.error" #define FPR (void)fprintf void exit(); void spinoff(); int unlock(); main(argc, argv) int argc; char **argv; { register FILE *ofp; register i, psfd; char lbuf[512]; char dbuf[64]; long t, time(); (void)umask(0); if (argc != 3) { FPR(stderr, "Usage: ps.monitor <baud> <ttyxx>\n"); exit(1); } if (access(LOCK, 0) == 0) { FPR(stderr, "ps.monitor: already active\n"); FPR(stderr, " (%s already exists)\n", LOCK); exit(0); } i = getspeed(atoi(argv[1])); (void)sprintf(dbuf, "/dev/%s", argv[2]); if ((psfd = open(dbuf, O_RDONLY)) == -1) { FPR(stderr, "ps.monitor: can't open %s\n", dbuf); exit(1); } if (settty(psfd, i) == -1) { FPR(stderr, "ps.monitor: ioctl failed on %s\n", dbuf); exit(1); } if (link(PSERR, OPSERR) != -1) (void)unlink(PSERR); if ((ofp = fopen(PSERR, "a")) == NULL) { FPR(stderr, "ps.monitor: can't create error log %s\n", PSERR); exit(1); } spinoff(); /* * Ignore common signals */ (void)signal(SIGHUP, SIG_IGN); (void)signal(SIGQUIT, SIG_IGN); (void)signal(SIGINT, SIG_IGN); (void)signal(SIGPIPE, SIG_IGN); (void)signal(SIGALRM, SIG_IGN); (void)signal(SIGTERM, unlock); t = time((long *)0); FPR(ofp, "Created: %s", ctime(&t)); (void)fflush(ofp); while ((i = read(psfd, lbuf, 512)) >= 0) if (i) { (void)fwrite(lbuf, 1, i, ofp); (void)fflush(ofp); } return(0); } getspeed(n) int n; { switch (n) { case 300: return(B300); case 1200: return(B1200); case 2400: return(B2400); case 4800: return(B4800); case 9600: return(B9600); case 19200: return(B19200); } return(B9600); /* default for no match 9600 baud */ } /* * settty() - set tty modes (if output connected to a tty). */ settty(fd, speed) int fd, speed; { struct termio termbuff; if (ioctl(fd, TCGETA, &termbuff) == -1) return(-1); /* * Enable Canonical, XON / XOFF flow control, and set baud. */ termbuff.c_lflag = ICANON; termbuff.c_iflag = IXON | IXOFF; termbuff.c_cflag = speed | CS8 | CREAD; termbuff.c_oflag = 0; (void)ioctl(fd, TCSETAW, &termbuff); return(0); } void spinoff() { register FILE *fp; register i; /* * Create a child process */ if ((i = fork()) == -1) { FPR(stderr, "ps.monitor: can't fork()\n"); exit(1); } /* * The parent dies leaving the child inherited by pid 1 */ if (i) { if ((fp = fopen(LOCK, "w")) == NULL) { FPR(stderr, "ps.monitor: can't create lock %s\n", LOCK); (void)kill(i, SIGKILL); } FPR(fp, "%d\n", i); (void)fclose(fp); exit(0); } } unlock() { (void)unlink(LOCK); exit(0); } SHAR_EOF chmod +x 'ps.monitor.c' fi # end of overwriting check # End of shell archive exit 0