430 lines
13 KiB
Plaintext
430 lines
13 KiB
Plaintext
$OpenBSD: patch-src_ck-sysdeps-openbsd_c,v 1.10 2012/01/08 19:42:02 naddy Exp $
|
|
--- src/ck-sysdeps-openbsd.c.orig Tue Dec 20 20:17:24 2011
|
|
+++ src/ck-sysdeps-openbsd.c Tue Dec 20 20:18:44 2011
|
|
@@ -0,0 +1,425 @@
|
|
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
|
+ *
|
|
+ * Copyright (C) 2006 William Jon McCann <mccann@jhu.edu>
|
|
+ * Copyright (C) 2007 Joe Marcus Clarke <marcus@FreeBSD.org>
|
|
+ * Copyright (C) 2008 Jared D. McNeill <jmcneill@NetBSD.org>
|
|
+ * Copyright (C) 2009 Robert Nagy <robert@openbsd.org>
|
|
+ *
|
|
+ * This program is free software; you can redistribute it and/or modify
|
|
+ * it under the terms of the GNU General Public License as published by
|
|
+ * the Free Software Foundation; either version 2 of the License, or
|
|
+ * (at your option) any later version.
|
|
+ *
|
|
+ * This program is distributed in the hope that it will be useful,
|
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
+ * GNU General Public License for more details.
|
|
+ *
|
|
+ * You should have received a copy of the GNU General Public License
|
|
+ * along with this program; if not, write to the Free Software
|
|
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
+ *
|
|
+ */
|
|
+
|
|
+#include "config.h"
|
|
+
|
|
+#include <stdlib.h>
|
|
+#include <stdio.h>
|
|
+#include <fcntl.h>
|
|
+#include <unistd.h>
|
|
+#include <string.h>
|
|
+#include <errno.h>
|
|
+#include <paths.h>
|
|
+#include <ttyent.h>
|
|
+#include <kvm.h>
|
|
+#include <sys/param.h>
|
|
+#include <sys/types.h>
|
|
+#include <sys/stat.h>
|
|
+#include <sys/sysctl.h>
|
|
+#include <sys/user.h>
|
|
+#include <sys/ioctl.h>
|
|
+
|
|
+#ifdef __OpenBSD__
|
|
+#include <sys/stdint.h>
|
|
+#endif
|
|
+
|
|
+#include <dev/wscons/wsdisplay_usl_io.h>
|
|
+
|
|
+#define DEV_ENCODE(M,m) ( \
|
|
+ ( (M&0xfff) << 8) | ( (m&0xfff00) << 12) | (m&0xff) \
|
|
+)
|
|
+
|
|
+#include "ck-sysdeps.h"
|
|
+
|
|
+#ifndef ERROR
|
|
+#define ERROR -1
|
|
+#endif
|
|
+
|
|
+/* adapted from procps */
|
|
+struct _CkProcessStat
|
|
+{
|
|
+ int pid;
|
|
+ int ppid; /* stat,status pid of parent process */
|
|
+ char state; /* stat,status single-char code for process state (S=sleeping) */
|
|
+ char cmd[16]; /* stat,status basename of executable file in call to exec(2) */
|
|
+ unsigned long long utime; /* stat user-mode CPU time accumulated by process */
|
|
+ unsigned long long stime; /* stat kernel-mode CPU time accumulated by process */
|
|
+ unsigned long long cutime; /* stat cumulative utime of process and reaped children */
|
|
+ unsigned long long cstime; /* stat cumulative stime of process and reaped children */
|
|
+ unsigned long long start_time; /* stat start time of process -- seconds since 1-1-70 */
|
|
+ unsigned long start_code; /* stat address of beginning of code segment */
|
|
+ unsigned long end_code; /* stat address of end of code segment */
|
|
+ unsigned long start_stack; /* stat address of the bottom of stack for the process */
|
|
+ unsigned long kstk_esp; /* stat kernel stack pointer */
|
|
+ unsigned long kstk_eip; /* stat kernel instruction pointer */
|
|
+ unsigned long wchan; /* stat (special) address of kernel wait channel proc is sleeping in */
|
|
+ long priority; /* stat kernel scheduling priority */
|
|
+ long nice; /* stat standard unix nice level of process */
|
|
+ long rss; /* stat resident set size from /proc/#/stat (pages) */
|
|
+ long alarm; /* stat ? */
|
|
+ unsigned long rtprio; /* stat real-time priority */
|
|
+ unsigned long sched; /* stat scheduling class */
|
|
+ unsigned long vsize; /* stat number of pages of virtual memory ... */
|
|
+ unsigned long rss_rlim; /* stat resident set size limit? */
|
|
+ unsigned long flags; /* stat kernel flags for the process */
|
|
+ unsigned long min_flt; /* stat number of minor page faults since process start */
|
|
+ unsigned long maj_flt; /* stat number of major page faults since process start */
|
|
+ unsigned long cmin_flt; /* stat cumulative min_flt of process and child processes */
|
|
+ unsigned long cmaj_flt; /* stat cumulative maj_flt of process and child processes */
|
|
+ int pgrp; /* stat process group id */
|
|
+ int session; /* stat session id */
|
|
+ int nlwp; /* stat number of threads, or 0 if no clue */
|
|
+ int tty; /* stat full device number of controlling terminal */
|
|
+ int tpgid; /* stat terminal process group id */
|
|
+ int exit_signal; /* stat might not be SIGCHLD */
|
|
+ int processor; /* stat current (or most recent?) CPU */
|
|
+ uintptr_t penv; /* stat address of initial environment vector */
|
|
+ char tty_text[11]; /* stat device name */
|
|
+
|
|
+};
|
|
+
|
|
+pid_t
|
|
+ck_process_stat_get_ppid (CkProcessStat *stat)
|
|
+{
|
|
+ g_return_val_if_fail (stat != NULL, -1);
|
|
+
|
|
+ return stat->ppid;
|
|
+}
|
|
+
|
|
+char *
|
|
+ck_process_stat_get_cmd (CkProcessStat *stat)
|
|
+{
|
|
+ g_return_val_if_fail (stat != NULL, NULL);
|
|
+
|
|
+ return g_strdup (stat->cmd);
|
|
+}
|
|
+
|
|
+char *
|
|
+ck_process_stat_get_tty (CkProcessStat *stat)
|
|
+{
|
|
+ g_return_val_if_fail (stat != NULL, NULL);
|
|
+
|
|
+ return g_strdup (stat->tty_text);
|
|
+}
|
|
+
|
|
+static gboolean
|
|
+get_kinfo_proc (pid_t pid,
|
|
+ struct kinfo_proc *p)
|
|
+{
|
|
+ size_t len;
|
|
+
|
|
+ int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, pid,
|
|
+ sizeof(struct kinfo_proc), 0 };
|
|
+
|
|
+ if (sysctl(mib, nitems(mib), NULL, &len, NULL, 0) < 0)
|
|
+ return FALSE;
|
|
+
|
|
+ mib[5] = (len / sizeof(struct kinfo_proc));
|
|
+
|
|
+ if (sysctl(mib, nitems(mib), p, &len, NULL, 0) < 0)
|
|
+ return FALSE;
|
|
+
|
|
+ return TRUE;
|
|
+}
|
|
+
|
|
+/* return 1 if it works, or 0 for failure */
|
|
+static gboolean
|
|
+stat2proc (pid_t pid,
|
|
+ CkProcessStat *P)
|
|
+{
|
|
+ struct kinfo_proc p;
|
|
+ char *ttname;
|
|
+ int num;
|
|
+ int tty_maj;
|
|
+ int tty_min;
|
|
+
|
|
+ if (! get_kinfo_proc (pid, &p)) {
|
|
+ return FALSE;
|
|
+ }
|
|
+
|
|
+ num = KI_MAXCOMLEN;
|
|
+ if (num >= sizeof P->cmd) {
|
|
+ num = sizeof P->cmd - 1;
|
|
+ }
|
|
+
|
|
+ memcpy (P->cmd, p.p_comm, num);
|
|
+
|
|
+ P->cmd[num] = '\0';
|
|
+ P->pid = p.p_pid;
|
|
+ P->ppid = p.p_ppid;
|
|
+ P->pgrp = p.p__pgid;
|
|
+ P->session = p.p_sid;
|
|
+ P->rss = p.p_vm_rssize;
|
|
+ P->vsize = p.p_vm_dsize + p.p_vm_dsize + p.p_vm_ssize; /* XXX */
|
|
+ P->start_time = p.p_ustart_sec;
|
|
+ P->wchan = (unsigned long) p.p_wchan;
|
|
+ P->state = p.p_stat;
|
|
+ P->nice = p.p_nice;
|
|
+ P->flags = p.p_realflag;
|
|
+ P->tpgid = p.p_tpgid;
|
|
+ P->processor = p.p_cpuid;
|
|
+
|
|
+ /* we like it Linux-encoded :-) */
|
|
+ tty_maj = major (p.p_tdev);
|
|
+ tty_min = minor (p.p_tdev);
|
|
+ P->tty = DEV_ENCODE (tty_maj,tty_min);
|
|
+
|
|
+ snprintf (P->tty_text, sizeof P->tty_text, "%3d,%-3d", tty_maj, tty_min);
|
|
+
|
|
+ if (p.p_tdev != NODEV && (ttname = devname (p.p_tdev, S_IFCHR)) != NULL) {
|
|
+ memcpy (P->tty_text, ttname, sizeof P->tty_text);
|
|
+ }
|
|
+
|
|
+ if (p.p_tdev == NODEV) {
|
|
+ /* XXX nasty hack */
|
|
+#if defined(__i386__) || defined(__amd64__)
|
|
+ memcpy (P->tty_text, "/dev/ttyC4", sizeof P->tty_text);
|
|
+#else
|
|
+ memcpy (P->tty_text, "/dev/ttyC0", sizeof P->tty_text);
|
|
+#endif
|
|
+ }
|
|
+
|
|
+ if (P->pid != pid) {
|
|
+ return FALSE;
|
|
+ }
|
|
+
|
|
+ return TRUE;
|
|
+}
|
|
+
|
|
+gboolean
|
|
+ck_process_stat_new_for_unix_pid (pid_t pid,
|
|
+ CkProcessStat **stat,
|
|
+ GError **error)
|
|
+{
|
|
+ gboolean res;
|
|
+ CkProcessStat *proc;
|
|
+
|
|
+ g_return_val_if_fail (pid > 1, FALSE);
|
|
+
|
|
+ if (stat == NULL) {
|
|
+ return FALSE;
|
|
+ }
|
|
+
|
|
+ proc = g_new0 (CkProcessStat, 1);
|
|
+ proc->pid = pid;
|
|
+ res = stat2proc (pid, proc);
|
|
+ if (res) {
|
|
+ *stat = proc;
|
|
+ } else {
|
|
+ *stat = NULL;
|
|
+ }
|
|
+
|
|
+ return res;
|
|
+}
|
|
+
|
|
+void
|
|
+ck_process_stat_free (CkProcessStat *stat)
|
|
+{
|
|
+ g_free (stat);
|
|
+}
|
|
+
|
|
+GHashTable *
|
|
+ck_unix_pid_get_env_hash (pid_t pid)
|
|
+{
|
|
+ GHashTable *hash;
|
|
+ char **penv;
|
|
+ kvm_t *kd;
|
|
+ struct kinfo_proc p;
|
|
+ int i;
|
|
+
|
|
+ kd = kvm_openfiles (NULL, NULL, NULL, O_RDONLY, NULL);
|
|
+ if (kd == NULL) {
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ if (! get_kinfo_proc (pid, &p)) {
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ penv = kvm_getenvv (kd, &p, 0);
|
|
+ if (penv == NULL) {
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ hash = g_hash_table_new_full (g_str_hash,
|
|
+ g_str_equal,
|
|
+ g_free,
|
|
+ g_free);
|
|
+
|
|
+ for (i = 0; penv[i] != NULL; i++) {
|
|
+ char **vals;
|
|
+
|
|
+ vals = g_strsplit (penv[i], "=", 2);
|
|
+ if (vals != NULL) {
|
|
+ g_hash_table_insert (hash,
|
|
+ g_strdup (vals[0]),
|
|
+ g_strdup (vals[1]));
|
|
+ g_strfreev (vals);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ kvm_close (kd);
|
|
+
|
|
+ return hash;
|
|
+}
|
|
+
|
|
+char *
|
|
+ck_unix_pid_get_env (pid_t pid,
|
|
+ const char *var)
|
|
+{
|
|
+ GHashTable *hash;
|
|
+ char *val;
|
|
+
|
|
+ /*
|
|
+ * Would probably be more efficient to just loop through the
|
|
+ * environment and return the value, avoiding building the hash
|
|
+ * table, but this works for now.
|
|
+ */
|
|
+ hash = ck_unix_pid_get_env_hash (pid);
|
|
+ val = g_strdup (g_hash_table_lookup (hash, var));
|
|
+ g_hash_table_destroy (hash);
|
|
+
|
|
+ return val;
|
|
+}
|
|
+
|
|
+uid_t
|
|
+ck_unix_pid_get_uid (pid_t pid)
|
|
+{
|
|
+ uid_t uid;
|
|
+ gboolean res;
|
|
+ struct kinfo_proc p;
|
|
+
|
|
+ g_return_val_if_fail (pid > 1, 0);
|
|
+
|
|
+ uid = -1;
|
|
+
|
|
+ res = get_kinfo_proc (pid, &p);
|
|
+
|
|
+ if (res) {
|
|
+ uid = p.p_uid;
|
|
+ }
|
|
+
|
|
+ return uid;
|
|
+}
|
|
+
|
|
+gboolean
|
|
+ck_unix_pid_get_login_session_id (pid_t pid,
|
|
+ char **idp)
|
|
+{
|
|
+ g_return_val_if_fail (pid > 1, FALSE);
|
|
+
|
|
+ return FALSE;
|
|
+}
|
|
+
|
|
+gboolean
|
|
+ck_get_max_num_consoles (guint *num)
|
|
+{
|
|
+ /* XXX how can we find out how many are configured? */
|
|
+ if (num != NULL) {
|
|
+ *num = 7;
|
|
+ }
|
|
+
|
|
+ return TRUE;
|
|
+}
|
|
+
|
|
+char *
|
|
+ck_get_console_device_for_num (guint num)
|
|
+{
|
|
+ char *device;
|
|
+
|
|
+// VT are only available on i386 and amd64
|
|
+#if defined(__i386__) || defined(__amd64__)
|
|
+ /* The device number is always one less than the VT number. */
|
|
+ num--;
|
|
+#endif
|
|
+
|
|
+ device = g_strdup_printf ("/dev/ttyC%u", num);
|
|
+
|
|
+ return device;
|
|
+}
|
|
+
|
|
+gboolean
|
|
+ck_get_console_num_from_device (const char *device,
|
|
+ guint *num)
|
|
+{
|
|
+ guint n;
|
|
+ gboolean ret;
|
|
+
|
|
+ n = 0;
|
|
+ ret = FALSE;
|
|
+
|
|
+ if (device == NULL) {
|
|
+ return FALSE;
|
|
+ }
|
|
+
|
|
+ if (sscanf (device, "/dev/ttyC%u", &n) == 1) {
|
|
+// VT are only available on i386 and amd64
|
|
+#if defined(__i386__) || defined(__amd64__)
|
|
+ /* The VT number is always one more than the device number. */
|
|
+ n++;
|
|
+#endif
|
|
+ ret = TRUE;
|
|
+ }
|
|
+
|
|
+ if (num != NULL) {
|
|
+ *num = n;
|
|
+ }
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+gboolean
|
|
+ck_get_active_console_num (int console_fd,
|
|
+ guint *num)
|
|
+{
|
|
+ gboolean ret;
|
|
+ int res;
|
|
+ int active;
|
|
+
|
|
+ g_assert (console_fd != -1);
|
|
+
|
|
+ active = 0;
|
|
+ ret = FALSE;
|
|
+
|
|
+// VT are only available on i386 and amd64
|
|
+#if defined(__i386__) || defined(__amd64__)
|
|
+ res = ioctl (console_fd, VT_GETACTIVE, &active);
|
|
+ if (res == ERROR) {
|
|
+ perror ("ioctl VT_GETACTIVE");
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ g_debug ("Active VT is: %d (ttyC%d)", active, active - 1);
|
|
+#else
|
|
+ res = 0;
|
|
+ g_debug ("Active console is: ttyC%d", active);
|
|
+#endif
|
|
+ ret = TRUE;
|
|
+
|
|
+ out:
|
|
+ if (num != NULL) {
|
|
+ *num = active;
|
|
+ }
|
|
+
|
|
+ return ret;
|
|
+}
|