/proc code for the 3B15

Stephen J. Friedl friedl at vsi.COM
Sat Oct 22 14:17:22 AEST 1988


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 at 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 at vsi.com     {backbones}!vsi.com!friedl    attmail!vsi!friedl
---------Nancy Reagan on the Three Stooges: "Just say Moe"---------



More information about the Comp.sys.att mailing list