/*
 * @(#)memlook.c v1.0 10 Nov 1997 Rob Thomas robt@cymru.com
 * memlook.c -- A process memory utilization reporting tool.
 * 
 * memlook allows you to get the inside scoop on the amount of total
 * memory, resident set size, and stack size of a given process.  In
 * addition to that, memlook allows you to monitor the memory stats
 * over a given time period.  So running memlook like so:
 * pudge# memlook 5108 5
 * Will give you the memory stats for PID 5108 every 5 seconds.  You
 * can also run memlook like so:
 * pudge# memlook 5108
 * And it will give you just a quick, one-time snapshot of the memory
 * stats.
 *
 * memlook utilizes the /proc filesystem.  If your UNIX variant does
 * not have /proc, then obviously memlook will not work.
 *
 * REMEMBER:  Due to kernel-enforced rules, you are not allowed to peruse
 * any PID that you do not own or is setuid/setgid.  Only root can peruse
 * all PIDs.
 *
 * As always, set tabstop=4...
 *
 */

static char copyright[] = "@(#)memlook.c v1.0 10 Nov 1997 Robert Owen Thomas robt@cymru.com";
 
#include <stdio.h>
#include <sys/types.h>
#include <sys/signal.h>
#include <sys/syscall.h>
#include <sys/procfs.h>
#include <sys/param.h>
#include <fcntl.h>
 
int	counter = 10;
 
int		showUsage(const char *);
void	getInfo(int, int);
 
int
main (int argc, char *argv[])
{
	int			fd,
				pid,
				timeloop = 0;
	char		pidpath[BUFSIZ];
 
	switch (argc) {
		case 2:
			break;
		case 3:
			timeloop = atoi(argv[2]);
			break;
		default:
			showUsage(argv[0]);
			break;
	}
 
	pid = atoi(argv[1]);
	sprintf(pidpath, "/proc/%-d", pid);
        
	if ((fd = open(pidpath, O_RDONLY)) < 0) {
		perror(pidpath);
		exit(1);
	}

	if (0 < timeloop) {
		for (;;) {
			getInfo(fd, pid);
			sleep(timeloop);
		}
	}

	getInfo(fd, pid);		
	close(fd); 
	exit(0);
}
 
int
showUsage(const char *progname)
{
        
	fprintf(stderr, "%s: usage: %s <PID> [time delay]\n", progname, progname);
	exit(3);
}

void
getInfo(int fd, int pid)
{
	prpsinfo_t	prp;
	prstatus_t	prs;

   if (ioctl(fd, PIOCPSINFO, &prp) < 0) {
		perror("ioctl");
		exit(5);
	}

   if (ioctl(fd, PIOCSTATUS, &prs) < 0) {
		perror("ioctl");
		exit(7);
	}

	if (counter > 9) {
		fprintf(stdout, "PID\tIMAGE\t\tRSS\t\tHEAP\t\tSTACK\n");
		counter = 0;
	}

	fprintf(stdout, "%d\t%-9d\t%-9d\t%-15d\t%-15d\n", pid, prp.pr_bysize,
		prp.pr_byrssize, prs.pr_brksize, prs.pr_stksize);

	counter++;
}
 
