AUSAM/source/S/tap.c

Compare this file to the similar file:
Show the results in this format:

#
/* tap [-fildes] pid:
 *
 *	display the contents of an active pipe on the fildes
 *	defaults to fildes 1 if no fildes is specified.  Must be
 *	run as a set-user-id to root program.
 *
 *					Written By Bryan Palmer.
 */ 

#include <local-system>
#include <param.h>
#include <user.h>
#include <proc.h>
#include <file.h>
#include <stat16.h>
#define	NINODE	1
#include <inode.h>
#include <stdio.h>

#define STANDOUT 1
#define NOTNICE -30
#define NICE 0

char usage[] "Usage: tap [-fildes] pid ...\n";	/* cretin message */ 
char unix[] "/unix";				/* unix lives here */ 
char mem[] "/dev/mem";				/* memory */ 
char swap[] "/dev/swap";			/* swap disk */ 
char dev[] "/dev";				/* where the devices live */ 
char root[] "/";				/* root device */

int memfd;					/* memory fildes */ 
int swapfd;					/* swap fildes */ 
int rootfd;					/* root fildes */

int ruid;					/* my uid */ 

struct nll
{
	int n_name[4];
	int n_type;
	int n_value;
} nll[]
{

	'_f', 'il', 'e\0', '\0\0', 0, 0,
	0,
};

main(cookyc, vcooky)
register char **vcooky;
register int cookyc;
{
	register int fildes;


	cookyc--, vcooky++;

	/* find if the person wants to look at a
	 * different fildes to standard out (1)
	 * and change the variable fildes to allow
	 * this to happen.
	 */ 
	if(**vcooky == '-')
	{
		fildes = atoi(&vcooky[0][1]);
		if((fildes < 0) || (fildes > NOFILE))
		{
			fprintf(stderr, usage);
			fprintf(stderr, "fildes defaulted to 1\n\n");
			fildes = STANDOUT;
		}
		cookyc--, vcooky++;
	}
	else
		fildes = STANDOUT;


	/* do a nlist on unix to
	 * obtain the addresses of 
	 * the file structures
	 */
	nlist(unix, nll);
	if(nll[0].n_value == 0)
	{
		fprintf(stderr, "Cant do a nlist for \"%s\" in \"%s\"\n",
			nll[0].n_name, unix);
		exit(1);
	}

	/* open up the root device so */
	getrootdev();

	/* open the swap space and
	 * the memory for future reading
	 */ 
	if((memfd = open(mem, 0)) == -1)
	{
		perror(mem);
		exit(1);
	}

	if((swapfd = open(swap, 0)) == -1)
	{
		perror(swap);
		exit(2);
	}

	ruid = getreal();

	if(cookyc)
	{
		do
		{
			tap(fildes, atoi(*vcooky));
			vcooky++;
		}
		while(--cookyc);
	}
	else
	{
		fprintf(stderr, usage);
		exit(1);
	}

	exit(0);
}

struct proc *getslot(pid)
register int pid;
{
	register struct proc *ppr;
	register int i;
	int hiwater;


	ppr = &proc[2];	/* skip past unix and init */ 
	hiwater = gprocs(proc);
	for(i = 2; i < hiwater; i++)
	{
		/* find the slot containing the process
		 * and make sure that the person has permission
		 * to read the pipe
		 */ 
		if((ppr->p_stat) && (ppr->p_pid == pid) && (ppr->p_stat != SZOMB) && ((ppr->p_uid == ruid) || (ruid == 0)))
			return(ppr);
		ppr++;
	}

	return(0);	/* proc not found */ 

}

getuser(pptr, fildes)
register struct proc *pptr;
{
	register int device;
	long position, tmp;
	struct user u;
	int ff;



	position = &0->u_ofile[fildes];
	tmp = pptr->p_addr;
	if(pptr->p_flag & SLOAD)
	{
		/* user stucture is in core */ 
		device = memfd;
		position =+ tmp<<6;
	}
	else
	{
		/* user structure on swap space */ 
		device = swapfd;
		position =+ tmp * 512;
	}

	/* seek to the address of the appropriate file
	 * file structure and return it
	 */
	if(lseek(device, position, 0) == -1)
	{
		perror("lseek error");
		return(-1);
	}
	if(read(device, &ff, 2) != 2)
	{
		perror("read error");
		return(-1);
	}

	return(ff);
}


tap(fildes, pid)
int fildes, pid;
{
	register struct proc *procptr;
	register int ff;
	struct file ffle;	/* file struct */ 

	/* the reading of the proc table and the
	 * locating of the user structure must be niced
	 * to guarentee some sort of result.  The nice
	 * is turned off when this area is passed.
	 */ 


	nice(NOTNICE);	/* aid the seeking of the user structure */ 
	if((procptr = getslot(pid)) == 0)
	{
		nice(NICE);
		fprintf(stderr, "%d: process not found\n", pid);
		return(-1);
	}
	if((ff = getuser(procptr, fildes)) == -1)
	{
		nice(NICE);
		fprintf(stderr, "%d: User structure not found?\n", pid);
		return(-2);
	}
	nice(NICE);	/* niceness no longer needed */ 

	/* seek to the location of the desired file
	 * structure to obtain the inode.  Also check
	 * that the file is really a pipe and check that
	 * the file is really open.
	 */ 

	if(ff == 0)
	{
		/* file not open */ 
		fprintf(stderr, "%d: file descriptor not open\n", fildes);
		return(-8);
	}

	/* locate file structure */ 
	if(seek(memfd, ff, 0) == -1)
	{
		perror(mem);
		return(-3);
	}
	/* read in file structure */ 
	if(read(memfd, &ffle, sizeof ffle) == -1)
	{
		perror(mem);
		return(-4);
	}
	/* check 'is pipe?' */ 
	if(!(ffle.f_flag & FPIPE))
	{
		fprintf(stderr, "%d: not a pipe\n", fildes);
		return(-3);
	}

	/* locate inode */ 
	if(seek(memfd, ffle.f_inode, 0) == -1)
	{
		perror(mem);
		return(-5);
	}

	/* read in inode */ 
	if(read(memfd, &inode, sizeof inode[0]) != sizeof inode[0])
	{
		perror(mem);
		return(-5);
	}

	/* sort the pipe out and write the contents */ 
	if(printaddrs(ffle.f_inode, pid, fildes) == -1)
	{
		fprintf(stderr, "%d: pipe now closed\n", pid);
		return(-1);
	}
	writepipe(pid, &inode[0]);
}

getrootdev()
{

	struct direct
	{
		int d_inode;
		char d_name[14];
	} direct;
	register struct direct *dd;
	int fd;
	register char *ch;
	struct statbuf sb, se;
	int  devnum;

	/* stat '/' to obtain the major and minor device
	 * numbers of the root device
	 */

	if(stat(root,&se) == -1)
	{
		perror(root);
		exit(1);
	}
	devnum = (se.sb_major << 8) + se.sb_minor;

	/* chdir to /dev than search thru the directory
	 * looking for the root device
	 * Then attempt to open it as a raw device.  If this fails
	 * open it as a cooked device.  If this fails rack off
	 */ 


	if(chdir(dev) == -1)
	{
		perror(dev);
		exit(1);
	}

	/* open '.' */ 
	if((fd = open("", 0)) == -1)
	{
		perror(dev);
		exit(1);
	}

	dd = &direct;
	while(read(fd, dd, 16) == 16)
	{
		if((dd->d_inode) && (stat(dd->d_name, &sb) != -1) && (sb.sb_addr[0] == devnum) && ((sb.sb_flags & IFTYP) == IFBLK))
		{
			close(fd);
			if((rootfd = open(dd->d_name, 0)) == -1)
			{
				perror(dd->d_name);
				exit(1);
			}
			return(0);
		}
	}

	fprintf(stderr, "No root device??\n");
	exit(1);

}

writepipe(pid, inp)
int pid;
register struct inode *inp;
{
	char buff[512];
	register int i;

	fflush(stdout);	/* cause stdio to sync with hard wire io */ 
	for(i = 0; i < 8; i++)
	{
		if(inp->i_addr[i])
		{
			if(seek(rootfd, inp->i_addr[i], 3) != -1)
			{
				read(rootfd, buff, sizeof buff);
				write(1, buff, sizeof buff);
			}
		}
	}
	fprintf(stdout, "\n\n");
}

printaddrs(inp, pid, fildes)
struct inode *inp;
int pid, fildes;
{
	long readptr, writeptr;
	int rchk, wchk;
	register int i;


	rchk = wchk = 0;
	seek(memfd, nll[0].n_value, 0);	/* seek to file structure */ 
	read(memfd, file, sizeof file);
	for(i = 0; i < NFILE; i++)
	{
		if(file[i].f_inode == inp)
		{
			if(file[i].f_flag & FREAD)
			{
				readptr = file[i].f_offset;
				rchk++;
			}
			else if(file[i].f_flag & FWRITE)
			{
				writeptr = file[i].f_offset;
				wchk++;
			}
		}
	}
	fprintf(stdout, "Proc: %d		Fildes: %d\n", pid, fildes);
	if(rchk)
		fprintf(stdout, "Read  pointer: %D\n", readptr);
	if(wchk)
		fprintf(stdout, "Write pointer: %D\n", writeptr);
	if((rchk == 0) && (wchk == 0))
		return(-1);
	return(0);
}