digging out stuff from process address space
Rayan Zachariassen
rayan at CS.TORONTO.EDU
Tue Aug 1 11:57:36 AEST 1989
Jeff, thanks for your response. It did indeed guide me the right way.
My confusion about DFCOPENT was due to its description in the manual page:
DFCOPENT
If the given argument is zero, return the file
descriptor corresponding to the text region of the
process. If the given argument is non-zero, interpret
this value as a virtual address of the process. Return
the file descriptor corresponding to the region
containing this address. This call may be used to
locate symbol tables of the process.
This gave me the impression that opening /debug/<pid> would give only the
text segment of the process and one would have to use DFCOPENT with a virtual
address to get the stack segment, for example. I got even more confused by
seeing strange things in the top page of the stack segment as read from a
/debug/<pid> fd... once it was a symbol table, another time it was the
contents of the root crontab (which I had edited shortly before). I get
the feeling that page isn't being cleared when mapped into the process
address space (if so, you will want to fix it, if not, I remain confused).
For people listening in, the reason I was wondering about this was to
be able to print the hosts people are logged in from in a who listing.
We have this (suid, of course) in /local/bin/who. I really hate having to
stop login shells like this.
#include <stdio.h>
#include <sys/types.h>
#include <utmp.h>
#include <sys/schedctl.h>
#include <core.h>
#include <sys/fs/dbfcntl.h>
#include <sys/signal.h>
main(argc, argv)
int argc;
char *argv[];
{
int i;
char *at, *host;
struct utmp *utp;
extern struct utmp *getutent();
extern char *ctime(), *gethost();
/* if this isn't a normal everyday vanilla 'who', punt to the SGI one */
if (argc > 1) {
(void) execv("/bin/who", argv);
(void) execv("/usr/bin/who", argv);
fprintf(stderr, "%s: can't find normal 'who', giving up.\n",
argv[0]);
exit(1);
}
/* setup for critical region in gethost() */
/* ignore all signals */
for (i = 1; i < MAXSIG; ++i)
(void) signal(i, SIG_IGN);
/* up my priority so this runs fast... */
(void) schedctl(NDPRI, 0, NDPHIMAX);
while ((utp = getutent()) != NULL) {
if (utp->ut_type != USER_PROCESS)
continue;
at = ctime(&utp->ut_time);
at[16] = '\0';
printf("%-8.8s %-8.8s%s", utp->ut_name, utp->ut_line, at+4);
if ((host = gethost(utp->ut_pid)) != NULL)
printf(" (%s)", host);
putchar('\n');
}
exit(0);
}
char *
gethost(pid)
int pid;
{
register char *cp;
int fd, n, i;
static char buf[0x3000];
extern char *strchr();
(void) sprintf(buf, "/debug/%d", pid);
if ((fd = open(buf, 0)) < 0) {
perror("open");
return NULL;
}
/* critical section start */
if (fcntl(fd, DFCSTOP, 0) < 0) {
perror("fcntl 1");
return NULL;
}
if (lseek(fd, (long)stackbas(sizeof buf), 0) < 0) {
perror("lseek");
return NULL;
}
if ((n = read(fd, buf, sizeof buf)) < 0) {
perror("read");
return NULL;
}
i = CLEARNOSIG;
if (fcntl(fd, DFCRUN, &i) < 0) {
perror("fcntl 3");
return NULL;
}
/* critical section end */
cp = buf + n;
while (--cp > buf) {
if (*cp == 'R' && *(cp+1) == 'E'
&& strncmp(cp, "REMOTEHOST=",11) == 0)
return strchr(cp, '=') + 1;
}
return NULL;
}
More information about the Comp.sys.sgi
mailing list