friedl@vsi.COM (Stephen J. Friedl) (10/22/88)
Hi folks, I've had numerous requests for this code that uses the /proc filesystem for the 3B15, but I've had numerous bounces as well - I hope nobody objects to this posting. It runs on the 3B15 with System V Release 3.1 (or later), compile and run it, no special system permissions required. Have fun, and please send me feedback and other /proc utilities; I'll be a repository for these. Steve #----------------- cut here for pstop.c ----------------------- #ident "%W%" /* * pstop.c / pstart.c * * written by : Stephen J. Friedl * V-Systems, Inc. * +1 714 545 6442 * friedl@vsi.com * * *NOTE* this program is in the public domain, and may * be used by anybody for any purpose whatsoever. Please * pass it around, and enjoy. * * This program starts and stops processes from running. * argv[0] determines the start/stop operation, and the only * arg is a Pid. * * The general idea is to open the /proc slot for this guy, * extract the current state, and issue the appropriate ioctl() * instruction to stop (PIOCSTOP) or start (PIOCRUN) the process. * * This program must be linked to "pstart" and "pstop", and * it does not need to be setuid or setgid (it will only * operate on the current user's processes). * * This program checks most kinds of errors and does the * right thing. * * BEGIN-MAKE pstop : pstop.c ${CC} -o $@ pstop.c ln pstop pstart * END-MAKE */ #include <stdio.h> #include <string.h> #include <errno.h> #include <fcntl.h> #include <varargs.h> #include <sys/types.h> #include <sys/fs/prioctl.h> /* * values to exit() */ #ifndef EXIT_SUCCESS # define EXIT_SUCCESS 0 # define EXIT_FAILURE 1 #endif /* * general handy macros */ #define pr (void)printf #define spr (void)sprintf #define fpr (void)fprintf #define se stderr #define STOPPING 1 /* stop the process */ #define STARTING 2 /* start the process */ static int operation = 0; /* what we're doing here... */ static int Pid = 0; /* PID we're looking at */ static char *ProgName = NULL; /* program name (argv[0]) */ static void die(); static void pid_die(); static char *tailpath(); main(argc, argv) int argc; char *argv[]; { struct prpsinfo psinfo; /* ps(1) information */ struct prstatus prstat; /* process status information */ char buf[50], /* buffer for the /proc/##### filename */ *cmdname; /* tail end of the command name */ int proc_fd; /* fildes of the process */ ProgName = argv[0]; if (argc == 1) die("usage: %s pid", ProgName); /* * determine whether we are stopping or starting */ cmdname = tailpath(argv[0]); if (strcmp(cmdname, "pstop") == 0) operation = STOPPING; else if (strcmp(cmdname, "pstart") == 0) operation = STARTING; else die("cmdname must be pstop or pstart"); Pid = atoi(argv[1]); /* * now that we have the process ID, open the PID file. * If we can't open it, find out why so we can print * some kind of reasonable error message. * * note that the process must be opened in r/w mode * to be able to stop or start it... */ spr(buf, "/proc/%05d", Pid); if (proc_fd = open(buf, O_RDWR), proc_fd < 0) { switch (errno) { case EPERM: case EACCES: pid_die("Permission denied"); /*NOTREACHED*/ case ENOENT: pid_die("No such process"); /*NOTREACHED*/ default: pid_die("cannot open (errno = %d)", errno); /*NOTREACHED*/ } } /* * now get PS information about the command so we can see it. */ if (ioctl(proc_fd, PIOCPSINFO, &psinfo) < 0) pid_die("cannot get ps info (errno = %d)", errno); /* * now grab the status to see if we're already stopped. */ if (ioctl(proc_fd, PIOCSTATUS, &prstat) < 0) pid_die("cannot get process status (errno = %d)", errno); if (operation == STOPPING) { if (prstat.pr_state == PR_STOP) pid_die("already stopped"); if (ioctl(proc_fd, PIOCSTOP, 0) < 0) pid_die("cannot stop process (errno = %d)", errno); fpr(se, "%s: PID %05d: stopped\n", ProgName, Pid); } else { if (prstat.pr_state == PR_RUN) pid_die("already running"); if (ioctl(proc_fd, PIOCRUN, 0) < 0) pid_die("cannot restart process (errno = %d)", errno); fpr(se, "%s: PID %05d: restarted\n", ProgName, Pid); } exit(EXIT_SUCCESS); /*NOTREACHED*/ } /* * die() * * Given a printf-style arg list, print a message (including * the program name) and exit. */ /*VARARGS*/ static void die(va_alist) va_dcl { va_list args; char *format; fpr(stderr, "%s: ", ProgName); va_start(args); format = va_arg(args, char *); (void)vfprintf(stderr, format, args); va_end(args); (void)fputc('\n', stderr); exit(EXIT_FAILURE); } /* * pid_die() * * Given a printf-style arg list, print a message (including * the program name and process ID) and exit. * * This is just like die but with the extra PID argument. */ /*VARARGS*/ static void pid_die(va_alist) va_dcl { va_list args; char *format; fpr(stderr, "%s: PID %05d: ", ProgName, Pid); va_start(args); format = va_arg(args, char *); (void)vfprintf(stderr, format, args); va_end(args); (void)fputc('\n', stderr); exit(EXIT_FAILURE); } /* * tailpath() * * Given a full pathname, return a pointer to the tail end of it. */ static char * tailpath(fullpath) char *fullpath; { char *p; if (p = strrchr(fullpath, '/')) return(p+1); else return(fullpath); } #----------------- cut here for pstop.c ----------------------- -- Steve Friedl V-Systems, Inc. +1 714 545 6442 3B2-kind-of-guy friedl@vsi.com {backbones}!vsi.com!friedl attmail!vsi!friedl ---------Nancy Reagan on the Three Stooges: "Just say Moe"---------