sources-request@mirror.UUCP (12/10/86)
Submitted by: ihnp4!utzoo!hcr!hcrvx1!hugh Mod.sources: Volume 7, Issue 90 Archive-name: forktest I would like to submit the following program to mod.sources. I hope that the comments are sufficient explanation. I don't see that a manual is worthwhile. I have run this program under System V and Version 7. I have not tested it under BSD, but I know of no impediment. With this program, I have found bugs in a number of UNIX System V utilities. I am sure that BSD programs would be just as buggy, but I haven't tested them. Here are some examples: Programs that leave extra file descriptors open: sdb ! command mailx ~! command during message composition, and ! command (two extra) mail ! command rn ! or | command (5 extra!) cu ~! command (one extra: number 5) Programs that leave signals ignored: mailx ~! command (SIGINT!) rn ! and | commands (SIGEMT!?) I think that this list shows that it is easy to get fork(2) wrong. I hope programmers will use ForkTest to catch this type of bug early. Exercise for the reader: what can you scribble on with those extra file descriptors? Hugh Redelmeier (416) 922-1937 utzoo!hcr!hugh [ I wrote the Makefile and README. --r$ ] ----------CUT HERE---------- #! /bin/sh # This is a shell archive. Remove anything before this line, # then unpack it by saving it in a file and typing "sh file". # If all goes well, you will see the message "End of shell archive." # Contents: Makefile README forktest.c # Wrapped by rs@mirror on Wed Dec 10 13:44:46 1986 PATH=/bin:/usr/bin:/usr/ucb; export PATH echo shar: extracting "'Makefile'" '(52 characters)' if test -f 'Makefile' ; then echo shar: will not over-write existing file "'Makefile'" else sed 's/^X//' >Makefile <<'@//E*O*F Makefile//' X Xforktest: forktest.c X $(CC) $(CFLAGS) -o forktest X @//E*O*F Makefile// if test 52 -ne "`wc -c <'Makefile'`"; then echo shar: error transmitting "'Makefile'" '(should have been 52 characters)' fi fi # end of overwriting check echo shar: extracting "'README'" '(253 characters)' if test -f 'README' ; then echo shar: will not over-write existing file "'README'" else sed 's/^X//' >README <<'@//E*O*F README//' X X[ This program is designed to be called by programs that allow X shell escapes. It prints out the argc,argv parameters, and X lists the disposition of signals, alarm calls, etc. The fun X part is when it lists the open file descriptors... -r$ ] @//E*O*F README// if test 253 -ne "`wc -c <'README'`"; then echo shar: error transmitting "'README'" '(should have been 253 characters)' fi fi # end of overwriting check echo shar: extracting "'forktest.c'" '(3059 characters)' if test -f 'forktest.c' ; then echo shar: will not over-write existing file "'forktest.c'" else sed 's/^X//' >forktest.c <<'@//E*O*F forktest.c//' X/* Fork Test: display args, open files, signals, etc. X * X * Simple as this program is, it has found bugs in the X * way a number of programs fork off children. To test X * how a program is invoking its children, run this X * program as a child. X * X * Generally, processes should be created with: X * X * - a reasonable arg count & list X * - arg 0 should look like the name of the command X * X * - real and effective UIDs and GIDs should be reasonable. X * Beware setuid programs that fork children! X * X * - no pending alarm. Version 7 apparently does not X * reset alarms upon an exec! X * X * - file descriptors 0 (STDIN), 1 (STDOUT), and 2 (STDERR) X * opened reasonably X * - all other file descriptors closed (this program will X * describe all open channels) X * X * - all signals (except SIGKILL) set to SIG_DFL (this X * program will print all signals set otherwise) X * X * The output is fairly simple to understand. When in X * doubt, read the code (and a UNIX manual: exec(2), X * getuid(2), alarm(2), signal(2), stat(2)). X * X * Room for Improvement: X * X * - strings should be printed in a way that shows funny characters. X * - show misc. other bits of state X * - PID (who cares?) X * - umask X * - ulimit (System V) X * - stty settings of open TTYs X * X * Copyright (c) 1986 March 11 D. Hugh Redelmeier X * X * This program may be distributed and used without restriction. X */ X X#include <stdio.h> X Xextern unsigned alarm(); /* should be unsigned, but may be int */ X X#include <sys/types.h> X#include <sys/stat.h> X Xstruct stat sb; X X#include <errno.h> Xextern int errno; Xextern char *sys_errlist[]; X X#include <signal.h> X Xint (*signal())(); X Xmain(argc, argv, envp) Xint argc; Xchar **argv, **envp; X{ X register int i; X unsigned al = alarm(0); /* get it while it is hot */ X X printf("%d arg(s):", argc); X for (i=0; i<argc; i++) X if (argv[i] == NULL) X printf(" NULL!"); X else X printf(" \"%s\"", argv[i]); X printf("\n"); X if (argv[argc] != NULL) X printf("Arg list is not ended with a NULL!\n"); X X printf("Real UID = %d, GID = %d; Effective UID = %d, GID = %d.\n", X getuid(), getgid(), geteuid(), getegid()); X X if (al) X printf("Alarm set to go off in %u seconds.\n", al); X X printf("File Descriptors:\n"); X for (i=0; i!=40; i++) /* I hope 40 is enough. */ X if (fstat(i, &sb) == -1) { X if (errno != EBADF) X printf("\t%d error: %s\n", i, sys_errlist[errno]); X } else { X printf("\t%d: dev=%d, ino=%d, perm=0%04o, ", X i, sb.st_dev, sb.st_ino, sb.st_mode&07777); X switch (sb.st_mode & S_IFMT) { X case S_IFREG: X printf("pipe or regular file\n"); X break; X /* extend as desired */ X default: X printf("IFMT=0%o\n", sb.st_mode>>12); X break; X } X } X X printf("Signals:\n"); X for (i=1; i!=40; i++) { /* I hope 40 is enough. */ X register int n = (int) signal(i, SIG_IGN); X switch (n) { X case -1: X case SIG_DFL: X break; X case SIG_IGN: X printf("\t%d: SIG_IGN\n", i); X break; X default: X printf("\t%d: %d\n", i, n); X break; X } X } X X printf("Environment:\n"); X for (i=0; envp[i]!=NULL; i++) X printf("\t\"%s\"\n", envp[i]); X X exit(0); X} @//E*O*F forktest.c// if test 3059 -ne "`wc -c <'forktest.c'`"; then echo shar: error transmitting "'forktest.c'" '(should have been 3059 characters)' fi fi # end of overwriting check echo shar: "End of shell archive." exit 0