AUSAM/source/S/tap.c
#
/* 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);
}