From: David van Moolenbroek Date: Fri, 9 Oct 2015 20:56:06 +0000 (+0000) Subject: w(1): switch to libkvm X-Git-Url: http://zhaoyanbai.com/repos/%22http:/www.isc.org/icons/zpipe.c?a=commitdiff_plain;h=refs%2Fchanges%2F51%2F3251%2F2;p=minix.git w(1): switch to libkvm Change-Id: I6d836d9aa2e1dfe8df1d866a5cc33868522f767e --- diff --git a/common/lib/libutil/Makefile.inc b/common/lib/libutil/Makefile.inc index 1caa21b35..2173f7a90 100644 --- a/common/lib/libutil/Makefile.inc +++ b/common/lib/libutil/Makefile.inc @@ -1,7 +1,7 @@ # $NetBSD: Makefile.inc,v 1.4 2011/11/13 21:56:53 christos Exp $ .PATH.c: ${.PARSEDIR} .if defined(__MINIX) -SRCS+= snprintb.c +SRCS+= snprintb.c proc_compare.c .else SRCS+= snprintb.c proc_compare.c getfstypename.c .endif # defined(__MINIX) diff --git a/distrib/sets/lists/minix-man/mi b/distrib/sets/lists/minix-man/mi index 1f74dd21d..994382087 100644 --- a/distrib/sets/lists/minix-man/mi +++ b/distrib/sets/lists/minix-man/mi @@ -2411,6 +2411,7 @@ ./usr/man/man3/prefresh.3 minix-man ./usr/man/man3/printf.3 minix-man ./usr/man/man3/printw.3 minix-man +./usr/man/man3/proc_compare.3 minix-man ./usr/man/man3/prop_array.3 minix-man ./usr/man/man3/prop_array_add.3 minix-man ./usr/man/man3/prop_array_capacity.3 minix-man diff --git a/lib/libutil/Makefile b/lib/libutil/Makefile index 6d4e492f8..de36cd6ed 100644 --- a/lib/libutil/Makefile +++ b/lib/libutil/Makefile @@ -30,7 +30,7 @@ MAN= efun.3 \ login.3 login_cap.3 loginx.3 \ \ opendisk.3 openpty.3 parsedate.3 pidfile.3 pidlock.3 \ - pw_getconf.3 pw_init.3 pw_lock.3 secure_path.3 \ + proc_compare.3 pw_getconf.3 pw_init.3 pw_lock.3 secure_path.3 \ raise_default_signal.3 \ snprintb.3 sockaddr_snprintf.3 stat_flags.3 strpct.3 ttyaction.3 \ ttymsg.3 util.3 diff --git a/minix/usr.bin/w/minix_proc.c b/minix/usr.bin/w/minix_proc.c deleted file mode 100644 index c7204b1c3..000000000 --- a/minix/usr.bin/w/minix_proc.c +++ /dev/null @@ -1,253 +0,0 @@ -/* MINIX3 implementations of a subset of some BSD-kernel-specific functions. */ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include /* for KERN_PROC_ */ - -#include -#include - -#include "minix_proc.h" - -/* - * Parse a procfs psinfo file, and fill the given minix_proc structure with the - * results. Return 1 on success, or 0 if this process should be skipped. - */ -static int -parse_psinfo(FILE *fp, int op, int __unused arg, pid_t pid, - struct minix_proc *p) -{ - char type, state, pstate, name[256]; - unsigned int uid, pgrp, dev; - int version; - - assert(op == KERN_PROC_ALL); /* this is all we support right now */ - - if (fscanf(fp, "%d", &version) != 1 || version != PSINFO_VERSION) - return 0; - - if (fscanf(fp, " %c %*d %255s %c %*d %*d %*u %*u %*u %*u", - &type, name, &state) != 3) - return 0; - - if (type != TYPE_USER) - return 0; /* user processes only */ - - if (fscanf(fp, " %*u %*u %*u %c %*d %u %*u %u %*d %*c %*d %u", - &pstate, &uid, &pgrp, &dev) != 4) - return 0; - - /* The fields as expected by the main w(1) code. */ - p->p_pid = pid; - p->p__pgid = (pid_t)pgrp; - p->p_tpgid = (dev != 0) ? (pid_t)pgrp : 0; - p->p_tdev = (dev_t)dev; - strlcpy(p->p_comm, name, sizeof(p->p_comm)); - - /* Some fields we need for ranking ("sorting") processes later. */ - p->p_minix_state = state; - p->p_minix_pstate = pstate; - - return 1; -} - -/* - * The w(1)-specific implementation of kvm_getproc2. Return an array of - * process information structures (of type minix_proc), along with the number - * of processes in the resulting array. Return NULL on failure, in which case - * errno should be set to something meaningful. - */ -struct minix_proc * -minix_getproc(void * __unused dummy, int op, int arg, int elemsize, int *cnt) -{ - struct minix_proc *procs; - char path[PATH_MAX]; - DIR *dp; - FILE *fp; - struct dirent *de; - pid_t pid, *pids; - unsigned int i, npids, size; - int e; - - assert(elemsize == sizeof(struct minix_proc)); - - /* - * First see how much memory we will need in order to store the actual - * process data. We store the PIDs in a (relatively small) allocated - * memory area immediately, so that we don't have to reiterate through - * the /proc directory twice. - */ - if ((dp = opendir(_PATH_PROC)) == NULL) - return NULL; - - if ((pids = malloc(size = sizeof(pid_t) * 64)) == NULL) { - e = errno; - closedir(dp); - errno = e; - return NULL; - } - npids = 0; - - while ((de = readdir(dp)) != NULL) { - if ((pid = (pid_t)atoi(de->d_name)) > 0) { - if (sizeof(pid_t) * npids == size && - (pids = realloc(pids, size *= 2)) == NULL) - break; - pids[npids++] = pid; - } - } - - closedir(dp); - - /* No results, or out of memory? Then bail out. */ - if (npids == 0 || pids == NULL) { - if (pids != NULL) { - e = errno; - free(pids); - errno = e; - } else - errno = ENOENT; /* no processes found */ - return NULL; - } - - /* Now obtain actual process data for the PIDs we obtained. */ - if ((procs = malloc(sizeof(struct minix_proc) * npids)) == NULL) { - e = errno; - free(pids); - errno = e; - return NULL; - } - - *cnt = 0; - for (i = 0; i < npids; i++) { - pid = pids[i]; - - snprintf(path, sizeof(path), _PATH_PROC "%u/psinfo", pid); - - /* Processes may legitimately disappear between calls. */ - if ((fp = fopen(path, "r")) == NULL) - continue; - - if (parse_psinfo(fp, op, arg, pid, &procs[*cnt])) - (*cnt)++; - - fclose(fp); - } - - free(pids); - - /* The returned data is not freed, but we are called only once. */ - return procs; -} - -/* - * A w(1)-specific MINIX3 implementation of kvm_getargv2. Return an array of - * strings representing the command line of the given process, optionally (if - * not 0) limited to a number of printable characters if the arguments were - * to be printed with a space in between. Return NULL on failure. Since the - * caller will not use earlier results after calling this function again, we - * can safely return static results. - */ -char ** -minix_getargv(void * __unused dummy, const struct minix_proc * p, int nchr) -{ -#define MAX_ARGS 32 - static char *argv[MAX_ARGS+1], buf[4096]; - char path[PATH_MAX]; - ssize_t i, bytes; - int fd, argc; - - /* Get the command line of the process from procfs. */ - snprintf(path, sizeof(path), _PATH_PROC "%u/cmdline", p->p_pid); - - if ((fd = open(path, O_RDONLY)) < 0) - return NULL; - - bytes = read(fd, buf, sizeof(buf)); - - close(fd); - - if (bytes <= 0) - return NULL; - - /* - * Construct an array of arguments. Stop whenever we run out of bytes - * or printable characters (simply counting the null characters as - * spaces), or whenever we fill up our argument array. Note that this - * is security-sensitive code, as it effectively processes (mostly-) - * arbitrary input from other users. - */ - bytes--; /* buffer should/will be null terminated */ - if (nchr != 0 && bytes > nchr) - bytes = nchr; - argc = 0; - for (i = 0; i < bytes && argc < MAX_ARGS; i++) { - if (i == 0 || buf[i-1] == 0) - argv[argc++] = &buf[i]; - } - buf[i] = 0; - argv[argc] = NULL; - - return argv; -} - -/* - * A w(1)-specific implementation of proc_compare_wrapper. Return 0 if the - * first given process is more worthy of being shown as the representative - * process of what a user is doing, or 1 for the second process. Since procfs - * currently does not expose enough information to do this well, we use some - * very basic heuristics, and leave a proper implementation to future work. - */ -int -minix_proc_compare(const struct minix_proc * p1, const struct minix_proc * p2) -{ - static const int state_prio[] = /* best to worst */ - { STATE_RUN, STATE_WAIT, STATE_SLEEP, STATE_STOP, STATE_ZOMBIE }; - unsigned int i; - int sp1 = -1, sp2 = -1; - - if (p1 == NULL) return 1; - if (p2 == NULL) return 0; - - /* - * Pick any runnable candidate over a waiting candidate, any waiting - * candidate over a sleeping candidate, etcetera. The rationale is - * roughly as follows: runnable means that something is definitely - * happening; waiting means that probably something interesting is - * happening, which eliminates e.g. shells; sleeping means that not - * much is going on; stopped and zombified means that definitely - * nothing is going on. - */ - for (i = 0; i < sizeof(state_prio) / sizeof(state_prio[0]); i++) { - if (p1->p_minix_state == state_prio[i]) sp1 = i; - if (p2->p_minix_state == state_prio[i]) sp2 = i; - } - if (sp1 != sp2) - return (sp1 > sp2); - - /* - * Pick any non-PM-sleeping process over any PM-sleeping process. - * Here the rationale is that PM-sleeping processes are typically - * waiting for another process, which means that the other process is - * probably more worthy of reporting. Again, the shell is an example - * of a process we'd rather not report if there's something else. - */ - if (sp1 == STATE_SLEEP) { - if (p1->p_minix_pstate != PSTATE_NONE) return 1; - if (p2->p_minix_pstate != PSTATE_NONE) return 0; - } - - /* - * Pick the candidate with the largest PID. The rationale is that - * statistically that will most likely yield the most recently spawned - * process, which makes it the most interesting process as well. - */ - return p1->p_pid < p2->p_pid; -} diff --git a/minix/usr.bin/w/minix_proc.h b/minix/usr.bin/w/minix_proc.h deleted file mode 100644 index a216dbb45..000000000 --- a/minix/usr.bin/w/minix_proc.h +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef _W_MINIX_PROC_H -#define _W_MINIX_PROC_H - -/* - * This header file is tailored very specifically to the needs of w(1), which - * needs process information but uses a BSD infrastructure (namely, the Kernel - * Data Access Library or, eh, KVM.. huh?) which we cannot implement in MINIX3 - * without making a very, very large number of changes all over the place. - * - * In order to allow w(1) to function on MINIX3, we override some of the KVM - * functionality with MINIX3 implementations, by means of #defines. While that - * is indeed butt ugly, this approach does have advantages: we are able to - * implement the full expected functionality with minimal changes to w(1) - * itself, and whenever w(1) uses a KVM function or a process information field - * that this header does not supply, w(1) will break during compilation. - */ - -struct minix_proc { - pid_t p_pid; /* process ID */ - pid_t p__pgid; /* process group ID */ - pid_t p_tpgid; /* tty process group ID (= p_pgid or 0) */ - dev_t p_tdev; /* controlling terminal (= tty rdev or 0) */ - char p_minix_state; /* minix specific: process kernel state */ - char p_minix_pstate; /* minix specific: process PM state */ - char p_comm[256]; /* simple command line (= process name) */ -}; -#undef kinfo_proc2 -#define kinfo_proc2 minix_proc - -struct minix_proc *minix_getproc(void *dummy, int op, int arg, int elemsize, - int *cnt); -#undef kvm_getproc2 -#define kvm_getproc2 minix_getproc - -#undef kvm_geterr -#define kvm_geterr(dummy) strerror(errno) - -char **minix_getargv(void *dummy, const struct minix_proc *p, int nchr); -#undef kvm_getargv2 -#define kvm_getargv2 minix_getargv - -int minix_proc_compare(const struct minix_proc *p1, - const struct minix_proc *p2); -#undef proc_compare_wrapper -#define proc_compare_wrapper minix_proc_compare - -#endif /* !_W_MINIX_PROC_H */ diff --git a/sys/sys/sysctl.h b/sys/sys/sysctl.h index 1eea8f207..28f8db72c 100644 --- a/sys/sys/sysctl.h +++ b/sys/sys/sysctl.h @@ -1345,10 +1345,8 @@ int sysctlbyname(const char *, void *, size_t *, const void *, size_t); int sysctlgetmibinfo(const char *, int *, u_int *, char *, size_t *, struct sysctlnode **, int); int sysctlnametomib(const char *, int *, size_t *); -#if !defined(__minix) int proc_compare(const struct kinfo_proc2 *, const struct kinfo_lwp *, const struct kinfo_proc2 *, const struct kinfo_lwp *); -#endif /* !defined(__minix) */ void *asysctl(const int *, size_t, size_t *); void *asysctlbyname(const char *, size_t *); __END_DECLS diff --git a/usr.bin/w/Makefile b/usr.bin/w/Makefile index 67e1cd4f1..b17eee804 100644 --- a/usr.bin/w/Makefile +++ b/usr.bin/w/Makefile @@ -6,14 +6,8 @@ PROG= w SRCS= fmt.c pr_time.c w.c MAN= w.1 uptime.1 -.if defined(__MINIX) -.PATH: ${NETBSDSRCDIR}/minix/usr.bin/w -SRCS+= minix_proc.c -CPPFLAGS+= -I${NETBSDSRCDIR}/minix/usr.bin/w -.else DPADD= ${LIBKVM} ${LIBUTIL} LDADD= -lkvm -lutil -.endif LINKS= ${BINDIR}/w ${BINDIR}/uptime CPPFLAGS+= -DSUPPORT_UTMP -DSUPPORT_UTMPX diff --git a/usr.bin/w/w.c b/usr.bin/w/w.c index 5cfba1b73..292d145d1 100644 --- a/usr.bin/w/w.c +++ b/usr.bin/w/w.c @@ -86,11 +86,6 @@ __RCSID("$NetBSD: w.c,v 1.82 2014/12/22 15:24:14 dennis Exp $"); #include "extern.h" -#if defined(__minix) -/* MINIX3 note: please see this header for information about the port. */ -#include "minix_proc.h" -#endif /* defined(__minix) */ - struct timeval boottime; struct winsize ws; kvm_t *kd; @@ -124,10 +119,8 @@ struct entry { static void pr_args(struct kinfo_proc2 *); static void pr_header(time_t *, int); -#if !defined(__minix) static int proc_compare_wrapper(const struct kinfo_proc2 *, const struct kinfo_proc2 *); -#endif /* !defined(__minix) */ #if defined(SUPPORT_UTMP) || defined(SUPPORT_UTMPX) static int ttystat(const char *, struct stat *); static void process(struct entry *); @@ -152,9 +145,7 @@ main(int argc, char **argv) struct utmpx *utx; #endif const char *progname; -#if !defined(__minix) char errbuf[_POSIX2_LINE_MAX]; -#endif /* !defined(__minix) */ setprogname(argv[0]); @@ -201,15 +192,9 @@ main(int argc, char **argv) use_sysctl = (memf == NULL && nlistf == NULL); -#if !defined(__minix) if ((kd = kvm_openfiles(nlistf, memf, NULL, memf == NULL ? KVM_NO_FILES : O_RDONLY, errbuf)) == NULL) errx(1, "%s", errbuf); -#else - if (!use_sysctl) - errx(1, "The -M and -N flags are not supported on MINIX3."); - kd = NULL; -#endif /* !defined(__minix) */ (void)time(&now); @@ -615,7 +600,6 @@ process(struct entry *ep) } #endif -#if !defined(__minix) static int proc_compare_wrapper(const struct kinfo_proc2 *p1, const struct kinfo_proc2 *p2) @@ -636,7 +620,6 @@ proc_compare_wrapper(const struct kinfo_proc2 *p1, return proc_compare(p1, l1, p2, l2); } -#endif /* !defined(__minix) */ static void fixhost(struct entry *ep)