KNF.
This commit is contained in:
parent
ae3fd5e972
commit
907831a0b3
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: procfs_ops.c,v 1.4 1999/03/28 00:46:47 bgrayson Exp $ */
|
||||
/* $NetBSD: procfs_ops.c,v 1.5 1999/05/09 19:23:38 thorpej Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1999 The NetBSD Foundation, Inc.
|
||||
@ -17,8 +17,8 @@
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the NetBSD
|
||||
* Foundation, Inc. and its contributors.
|
||||
* This product includes software developed by the NetBSD
|
||||
* Foundation, Inc. and its contributors.
|
||||
* 4. Neither the name of The NetBSD Foundation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
@ -52,136 +52,154 @@
|
||||
#include <err.h>
|
||||
#include <kvm.h>
|
||||
|
||||
/* Assume that no process status file will ever be larger than this. */
|
||||
/* Assume that no process status file will ever be larger than this. */
|
||||
#define STATUS_SIZE 8192
|
||||
|
||||
/* Handy macro for only printing a warning once. Notice that
|
||||
/*
|
||||
* Handy macro for only printing a warning once. Notice that
|
||||
* one needs to use two sets of parentheses when invoking the
|
||||
* macro: WARNX_ONLY_ONCE(("mesgstr", arg1, arg2, ...)); */
|
||||
#define WARNX_ONLY_ONCE(x) { \
|
||||
static int firsttime=1; \
|
||||
if (firsttime) { \
|
||||
firsttime=0; \
|
||||
warnx x ; \
|
||||
} \
|
||||
* macro: WARNX_ONLY_ONCE(("mesgstr", arg1, arg2, ...));
|
||||
*/
|
||||
#define WARNX_ONLY_ONCE(x) \
|
||||
{ \
|
||||
static int firsttime = 1; \
|
||||
if (firsttime) { \
|
||||
firsttime = 0; \
|
||||
warnx x ; \
|
||||
} \
|
||||
}
|
||||
|
||||
static int verify_procfs_fd __P((int, const char *));
|
||||
static int parsekinfo __P((const char *, struct kinfo_proc *));
|
||||
struct kinfo_proc * procfs_getprocs __P((int, int, int *));
|
||||
static int verify_procfs_fd __P((int, const char *));
|
||||
static int parsekinfo __P((const char *, struct kinfo_proc *));
|
||||
struct kinfo_proc *procfs_getprocs __P((int, int, int *));
|
||||
|
||||
static int
|
||||
verify_procfs_fd (fd, path)
|
||||
int fd;
|
||||
verify_procfs_fd(fd, path)
|
||||
int fd;
|
||||
const char *path;
|
||||
{
|
||||
struct statfs procfsstat;
|
||||
|
||||
/* If the fstatfs fails, die immediately. Since we
|
||||
* already have the FD open, any error is probably one
|
||||
* that can't be worked around. */
|
||||
if (fstatfs(fd, &procfsstat)) {
|
||||
/*
|
||||
* If the fstatfs fails, die immediately. Since we already have the
|
||||
* FD open, any error is probably one that can't be worked around.
|
||||
*/
|
||||
if (fstatfs(fd, &procfsstat))
|
||||
err(1, "fstatfs on %s", path);
|
||||
}
|
||||
/* Now verify that the open file is truly on a procfs
|
||||
* filesystem. */
|
||||
|
||||
/* Now verify that the open file is truly on a procfs filesystem. */
|
||||
if (strcmp(procfsstat.f_fstypename, MOUNT_PROCFS)) {
|
||||
warnx("%s is on a '%s' filesystem, not 'procfs'???", path,
|
||||
procfsstat.f_fstypename);
|
||||
warnx("%s is on a `%s' filesystem, not `procfs'", path,
|
||||
procfsstat.f_fstypename);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
parsekinfo (path, kp)
|
||||
parsekinfo(path, kp)
|
||||
const char *path;
|
||||
struct kinfo_proc *kp;
|
||||
{
|
||||
char fullpath[MAXPATHLEN];
|
||||
int dirfd, fd, nbytes, devmajor, devminor;
|
||||
char fullpath[MAXPATHLEN];
|
||||
int dirfd, fd, nbytes, devmajor, devminor;
|
||||
struct timeval usertime, systime, starttime;
|
||||
char buff[STATUS_SIZE];
|
||||
char flagstr[256];
|
||||
char buff[STATUS_SIZE];
|
||||
char flagstr[256];
|
||||
|
||||
/* Verify that /proc/<pid> is a procfs file (and that no
|
||||
* one has mounted anything on top of it). If we didn't
|
||||
* do this, an intruder could hide processes by simply
|
||||
* mount_null'ing /tmp on top of the /proc/<pid>
|
||||
* directory. (And we can't just print warnings if we fail
|
||||
* to open /proc/<pid>/status, because the process may
|
||||
* have died since our getdents() call.) */
|
||||
/*
|
||||
* Verify that /proc/<pid> is a procfs file (and that no one has
|
||||
* mounted anything on top of it). If we didn't do this, an intruder
|
||||
* could hide processes by simply mount_null'ing /tmp on top of the
|
||||
* /proc/<pid> directory. (And we can't just print warnings if we
|
||||
* fail to open /proc/<pid>/status, because the process may have died
|
||||
* since our getdents() call.)
|
||||
*/
|
||||
snprintf(fullpath, MAXPATHLEN, "/proc/%s", path);
|
||||
dirfd=open(fullpath, O_RDONLY, 0);
|
||||
dirfd = open(fullpath, O_RDONLY, 0);
|
||||
if (verify_procfs_fd(dirfd, fullpath)) {
|
||||
close(dirfd);
|
||||
return -1;
|
||||
}
|
||||
/* Open /proc/"path"/status, and parse it into the kinfo_proc. */
|
||||
|
||||
/* Open /proc/<pid>/status, and parse it into the kinfo_proc. */
|
||||
snprintf(fullpath, MAXPATHLEN, "/proc/%s/status", path);
|
||||
fd=open(fullpath, O_RDONLY, 0);
|
||||
fd = open(fullpath, O_RDONLY, 0);
|
||||
close(dirfd);
|
||||
if (fd == -1) {
|
||||
/* Don't print warning, as the process may have
|
||||
* died since our scan of the directory entries. */
|
||||
/*warn("Open failed for %s", fullpath);*/
|
||||
/*
|
||||
* Don't print warning, as the process may have died since our
|
||||
* scan of the directory entries.
|
||||
*/
|
||||
close(fd);
|
||||
return -1; /* Process may no longer exist. */
|
||||
return -1; /* Process may no longer exist. */
|
||||
}
|
||||
/* Bail out for this process attempt if it isn't on a
|
||||
* procfs. Some intruder could have mounted something
|
||||
* on top of portions of /proc. */
|
||||
|
||||
/*
|
||||
* Bail out for this process attempt if it isn't on a procfs. Some
|
||||
* intruder could have mounted something on top of portions of /proc.
|
||||
*/
|
||||
if (verify_procfs_fd(fd, fullpath)) {
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
nbytes=read(fd, buff, STATUS_SIZE);
|
||||
|
||||
nbytes = read(fd, buff, STATUS_SIZE - 1);
|
||||
close(fd);
|
||||
if (nbytes <= 0) {
|
||||
/* Don't print warning, as the process may have
|
||||
* died since our scan of the directory entries. */
|
||||
/*warn("Read failed for %s", fullpath);*/
|
||||
return -1; /* Process may no longer exist. */
|
||||
/*
|
||||
* Don't print warning, as the process may have died since our
|
||||
* scan of the directory entries.
|
||||
*/
|
||||
return -1; /* Process may no longer exist. */
|
||||
}
|
||||
/* Terminate the buffer. */
|
||||
|
||||
/* Make sure the buffer is terminated. */
|
||||
buff[nbytes] = '\0';
|
||||
|
||||
sscanf(buff, "%s %d %d %d %d %d,%d %s %ld,%ld %ld,%ld %ld,%ld %s %d",
|
||||
kp->kp_proc.p_comm, &kp->kp_proc.p_pid,
|
||||
&kp->kp_eproc.e_ppid, &kp->kp_eproc.e_pgid,
|
||||
&kp->kp_eproc.e_sid, &devmajor, &devminor,
|
||||
flagstr, &starttime.tv_sec, &starttime.tv_usec,
|
||||
&usertime.tv_sec, &usertime.tv_usec,
|
||||
&systime.tv_sec, &systime.tv_usec,
|
||||
kp->kp_eproc.e_wmesg, &kp->kp_eproc.e_ucred.cr_uid);
|
||||
kp->kp_proc.p_comm, &kp->kp_proc.p_pid,
|
||||
&kp->kp_eproc.e_ppid, &kp->kp_eproc.e_pgid,
|
||||
&kp->kp_eproc.e_sid, &devmajor, &devminor,
|
||||
flagstr, &starttime.tv_sec, &starttime.tv_usec,
|
||||
&usertime.tv_sec, &usertime.tv_usec,
|
||||
&systime.tv_sec, &systime.tv_usec,
|
||||
kp->kp_eproc.e_wmesg, &kp->kp_eproc.e_ucred.cr_uid);
|
||||
|
||||
kp->kp_proc.p_wmesg = kp->kp_eproc.e_wmesg;
|
||||
kp->kp_proc.p_wchan = (void*)1; /* Set it to _something_. */
|
||||
kp->kp_proc.p_wchan = (void *) 1; /* XXX Set it to _something_. */
|
||||
kp->kp_eproc.e_tdev = makedev(devmajor, devminor);
|
||||
/* Put both user and sys time into rtime field. */
|
||||
|
||||
/* Put both user and sys time into rtime field. */
|
||||
kp->kp_proc.p_rtime.tv_sec = usertime.tv_sec + systime.tv_sec;
|
||||
kp->kp_proc.p_rtime.tv_usec = usertime.tv_usec + systime.tv_usec;
|
||||
/* CPU time isn't shown unless the ki_u.u_valid flag is
|
||||
* set. Unfortunately, we don't have access to that here. */
|
||||
/* Set the flag for whether or not there is
|
||||
* a controlling terminal. */
|
||||
|
||||
/*
|
||||
* CPU time isn't shown unless the ki_u.u_valid flag is set.
|
||||
* Unfortunately, we don't have access to that here.
|
||||
*/
|
||||
|
||||
/* Set the flag for whether or not there is a controlling terminal. */
|
||||
if (strstr(flagstr, "ctty"))
|
||||
kp->kp_proc.p_flag |= P_CONTROLT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct kinfo_proc *
|
||||
procfs_getprocs(op, arg, cnt)
|
||||
int op, arg;
|
||||
int *cnt;
|
||||
int op, arg;
|
||||
int *cnt;
|
||||
{
|
||||
struct stat statbuf;
|
||||
int procdirfd, nbytes, knum=0, maxknum=0;
|
||||
char *direntbuff;
|
||||
int procdirfd, nbytes, knum = 0, maxknum = 0;
|
||||
char *direntbuff;
|
||||
struct kinfo_proc *kp;
|
||||
int mib[4];
|
||||
size_t len;
|
||||
int mib[4];
|
||||
size_t len;
|
||||
struct statfs procfsstat;
|
||||
|
||||
/* First, make sure that /proc is a procfs filesystem. */
|
||||
/* First, make sure that /proc is a procfs filesystem. */
|
||||
if (statfs("/proc", &procfsstat)) {
|
||||
warn("statfs on /proc failed");
|
||||
return 0;
|
||||
@ -191,12 +209,15 @@ procfs_getprocs(op, arg, cnt)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Try to stat /proc/1/status. If we can't do
|
||||
* that, then just return right away. */
|
||||
/*
|
||||
* Try to stat /proc/1/status. If we can't do that, then just return
|
||||
* right away.
|
||||
*/
|
||||
if (stat("/proc/1/status", &statbuf)) {
|
||||
warn("stat of /proc/1/status");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Now, try to open /proc, and read in all process' information. */
|
||||
procdirfd = open("/proc", O_RDONLY, 0);
|
||||
if (procdirfd == -1) {
|
||||
@ -215,75 +236,81 @@ procfs_getprocs(op, arg, cnt)
|
||||
close(procdirfd);
|
||||
return 0;
|
||||
}
|
||||
/* Use sysctl to find out the total number of processes.
|
||||
* There's still a race condition -- once we do the
|
||||
* sysctl, someone could use a sysctl to bump it, and
|
||||
* fork off a lot of processes. So, to be _really_
|
||||
* safe, let's allocate twice as much memory. */
|
||||
|
||||
/*
|
||||
* Use sysctl to find out the total number of processes. There's still
|
||||
* a race condition -- once we do the sysctl, someone could use a
|
||||
* sysctl to bump it, and fork off a lot of processes. So, to be
|
||||
* _really_ safe, let's allocate twice as much memory.
|
||||
*/
|
||||
mib[0] = CTL_KERN;
|
||||
mib[1] = KERN_MAXPROC;
|
||||
len = sizeof(maxknum);
|
||||
if (sysctl(mib, 2, &maxknum, &len, NULL, 0) == -1) {
|
||||
err(1,"sysctl to fetch maxproc");
|
||||
}
|
||||
maxknum *= 2; /* Double it, to be really paranoid. */
|
||||
if (sysctl(mib, 2, &maxknum, &len, NULL, 0) == -1)
|
||||
err(1, "sysctl to fetch maxproc");
|
||||
maxknum *= 2; /* Double it, to be really paranoid. */
|
||||
|
||||
kp = (struct kinfo_proc *) malloc(sizeof(struct kinfo_proc)*maxknum);
|
||||
memset(kp, 0, sizeof(struct kinfo_proc)*maxknum);
|
||||
kp = (struct kinfo_proc *) malloc(sizeof(struct kinfo_proc) * maxknum);
|
||||
memset(kp, 0, sizeof(struct kinfo_proc) * maxknum);
|
||||
|
||||
/* Read in a batch of entries at a time. */
|
||||
while ((knum < maxknum) &&
|
||||
(nbytes = getdents(procdirfd, direntbuff,
|
||||
statbuf.st_blksize)) != 0) {
|
||||
int i;
|
||||
/* Read in a batch of entries at a time. */
|
||||
while ((knum < maxknum) &&
|
||||
(nbytes = getdents(procdirfd, direntbuff,
|
||||
statbuf.st_blksize)) != 0) {
|
||||
int i;
|
||||
struct dirent *dp;
|
||||
for (i=0; i<nbytes; /* nothing */) {
|
||||
dp = (struct dirent *) &direntbuff[i];
|
||||
for (i = 0; i < nbytes; /* nothing */ ) {
|
||||
dp = (struct dirent *) & direntbuff[i];
|
||||
i += dp->d_reclen;
|
||||
if (!strcmp(dp->d_name, ".")) continue;
|
||||
if (!strcmp(dp->d_name, "..")) continue;
|
||||
if (!strcmp(dp->d_name, "curproc")) continue;
|
||||
if (parsekinfo(dp->d_name, &kp[knum]) != 0) continue;
|
||||
/* Now check some of the flags. If the
|
||||
* newest entry doesn't match the flag
|
||||
* settings, then don't bump the pointer
|
||||
* past it! */
|
||||
if (strcmp(dp->d_name, ".") == 0)
|
||||
continue;
|
||||
if (strcmp(dp->d_name, "..") == 0)
|
||||
continue;
|
||||
if (strcmp(dp->d_name, "curproc") == 0)
|
||||
continue;
|
||||
if (parsekinfo(dp->d_name, &kp[knum]) != 0)
|
||||
continue;
|
||||
/*
|
||||
* Now check some of the flags. If the newest entry
|
||||
* doesn't match the flag settings, then don't bump
|
||||
* the pointer past it!
|
||||
*/
|
||||
switch (op) {
|
||||
case KERN_PROC_PID:
|
||||
if (kp[knum].kp_proc.p_pid == arg)
|
||||
knum++;
|
||||
break;
|
||||
case KERN_PROC_PGRP:
|
||||
if (kp[knum].kp_eproc.e_pgid == arg)
|
||||
knum++;
|
||||
break;
|
||||
case KERN_PROC_SESSION:
|
||||
if (kp[knum].kp_eproc.e_sid == arg)
|
||||
knum++;
|
||||
break;
|
||||
case KERN_PROC_TTY:
|
||||
if (kp[knum].kp_eproc.e_tdev == arg)
|
||||
knum++;
|
||||
break;
|
||||
case KERN_PROC_UID:
|
||||
if (kp[knum].kp_eproc.e_ucred.cr_uid == arg)
|
||||
knum++;
|
||||
break;
|
||||
case KERN_PROC_RUID:
|
||||
WARNX_ONLY_ONCE(("KERN_PROC_RUID flag "
|
||||
"not implemented. Returning "
|
||||
"info for all processes."));
|
||||
case KERN_PROC_PID:
|
||||
if (kp[knum].kp_proc.p_pid == arg)
|
||||
knum++;
|
||||
break;
|
||||
case KERN_PROC_ALL:
|
||||
break;
|
||||
case KERN_PROC_PGRP:
|
||||
if (kp[knum].kp_eproc.e_pgid == arg)
|
||||
knum++;
|
||||
break;
|
||||
default:
|
||||
WARNX_ONLY_ONCE(("Bad switch case! "
|
||||
"Returning info for "
|
||||
"all processes."));
|
||||
break;
|
||||
case KERN_PROC_SESSION:
|
||||
if (kp[knum].kp_eproc.e_sid == arg)
|
||||
knum++;
|
||||
break;
|
||||
break;
|
||||
case KERN_PROC_TTY:
|
||||
if (kp[knum].kp_eproc.e_tdev == arg)
|
||||
knum++;
|
||||
break;
|
||||
case KERN_PROC_UID:
|
||||
if (kp[knum].kp_eproc.e_ucred.cr_uid == arg)
|
||||
knum++;
|
||||
break;
|
||||
case KERN_PROC_RUID:
|
||||
WARNX_ONLY_ONCE(("KERN_PROC_RUID flag "
|
||||
"not implemented. Returning "
|
||||
"info for all processes."));
|
||||
knum++;
|
||||
break;
|
||||
case KERN_PROC_ALL:
|
||||
knum++;
|
||||
break;
|
||||
default:
|
||||
WARNX_ONLY_ONCE(("Bad switch case! "
|
||||
"Returning info for "
|
||||
"all processes."));
|
||||
knum++;
|
||||
break;
|
||||
}
|
||||
if (knum > maxknum) {
|
||||
WARNX_ONLY_ONCE(("Warning: only reporting "
|
||||
@ -291,7 +318,6 @@ procfs_getprocs(op, arg, cnt)
|
||||
"processes!", maxknum));
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user