Beispiel #1
0
/**
 * Read all processes to initialize the information tree.
 * @param reference  reference of ProcessTree
 * @return treesize>0 if succeeded otherwise =0.
 */
int initprocesstree_sysdep(ProcessTree_T **reference) {
        int                treesize;
        static kvm_t      *kvm_handle;
        ProcessTree_T     *pt;
        struct kinfo_proc *pinfo;

        if (! (kvm_handle = kvm_open(NULL, _PATH_DEVNULL, NULL, O_RDONLY, prog))) {
                LogError("system statistic error -- cannot initialize kvm interface\n");
                return 0;
        }

        pinfo = kvm_getprocs(kvm_handle, KERN_PROC_PROC, 0, &treesize);
        if (! pinfo || (treesize < 1)) {
                LogError("system statistic error -- cannot get process tree\n");
                kvm_close(kvm_handle);
                return 0;
        }

        pt = CALLOC(sizeof(ProcessTree_T), treesize);

        for (int i = 0; i < treesize; i++) {
                StringBuffer_T cmdline = StringBuffer_create(64);
                pt[i].pid       = pinfo[i].ki_pid;
                pt[i].ppid      = pinfo[i].ki_ppid;
                pt[i].uid       = pinfo[i].ki_ruid;
                pt[i].euid      = pinfo[i].ki_uid;
                pt[i].gid       = pinfo[i].ki_rgid;
                pt[i].starttime = pinfo[i].ki_start.tv_sec;
                pt[i].cputime   = (long)(pinfo[i].ki_runtime / 100000);
                pt[i].mem_kbyte = (unsigned long)(pinfo[i].ki_rssize * pagesize_kbyte);
                int flags       = pinfo[i].ki_stat;
                char * procname = pinfo[i].ki_comm;
                if (flags == SZOMB)
                        pt[i].zombie = true;
                pt[i].cpu_percent = 0;
                pt[i].time = get_float_time();
                char **args;
                if ((args = kvm_getargv(kvm_handle, &pinfo[i], 0))) {
                        for (int j = 0; args[j]; j++)
                                StringBuffer_append(cmdline, args[j + 1] ? "%s " : "%s", args[j]);
                        pt[i].cmdline = Str_dup(StringBuffer_toString(StringBuffer_trim(cmdline)));
                }
                StringBuffer_free(&cmdline);
                if (! pt[i].cmdline || ! *pt[i].cmdline) {
                        FREE(pt[i].cmdline);
                        pt[i].cmdline = Str_dup(procname);
                }
        }

        *reference = pt;
        kvm_close(kvm_handle);

        return treesize;
}
Beispiel #2
0
char *
glibtop_get_proc_args_p (glibtop *server, glibtop_proc_args *buf,
			 pid_t pid, unsigned max_len)
{
	struct kinfo_proc *pinfo;
	char *retval, **args, **ptr;
	size_t size = 0, pos = 0;
	int count;

	glibtop_init_p (server, (1L << GLIBTOP_SYSDEPS_PROC_ARGS), 0);

	memset (buf, 0, sizeof (glibtop_proc_args));

	/* Ignore init */
	if (pid < 2) return NULL;

	glibtop_suid_enter (server);

	/* Get the process data */
	pinfo = kvm_getprocs (server->machine->kd, KERN_PROC_PID, pid,
			       sizeof (*pinfo), &count);
	if (pinfo == NULL) {
		glibtop_suid_leave (server);
		glibtop_warn_io_r (server, "kvm_getprocs (%d)", pid);
		return NULL;
	}

	args = kvm_getargv (server->machine->kd, pinfo, max_len);
	if (args == NULL) {
		glibtop_suid_leave (server);
		glibtop_warn_io_r (server, "kvm_getargv (%d)", pid);
		return NULL;
	}

	glibtop_suid_leave (server);

	for (ptr = args; *ptr; ptr++)
		size += strlen (*ptr)+1;

	size += 2;
	retval = g_malloc0 (size);

	for (ptr = args; *ptr; ptr++) {
		const size_t len = strlen (*ptr)+1;
		memcpy (retval+pos, *ptr, len);
		pos += len;
	}

	buf->size = pos ? pos-1 : 0;

	buf->flags = _glibtop_sysdeps_proc_args;

	return retval;
}
/**
 * Read all processes to initialize the information tree.
 * @param reference  reference of ProcessTree
 * @param pflags Process engine flags
 * @return treesize > 0 if succeeded otherwise 0.
 */
int initprocesstree_sysdep(ProcessTree_T **reference, ProcessEngine_Flags pflags) {
        kvm_t *kvm_handle = kvm_open(NULL, _PATH_DEVNULL, NULL, O_RDONLY, prog);
        if (! kvm_handle) {
                LogError("system statistic error -- cannot initialize kvm interface\n");
                return 0;
        }

        int treesize;
        struct kinfo_proc *pinfo = kvm_getprocs(kvm_handle, KERN_PROC_ALL, 0, &treesize);
        if (! pinfo || (treesize < 1)) {
                LogError("system statistic error -- cannot get process tree\n");
                kvm_close(kvm_handle);
                return 0;
        }

        ProcessTree_T *pt = CALLOC(sizeof(ProcessTree_T), treesize);

        StringBuffer_T cmdline = NULL;
        if (pflags & ProcessEngine_CollectCommandLine)
                cmdline = StringBuffer_create(64);
        for (int i = 0; i < treesize; i++) {
                pt[i].pid          = pinfo[i].kp_pid;
                pt[i].ppid         = pinfo[i].kp_ppid;
                pt[i].cred.uid     = pinfo[i].kp_ruid;
                pt[i].cred.euid    = pinfo[i].kp_uid;
                pt[i].cred.gid     = pinfo[i].kp_rgid;
                pt[i].threads      = pinfo[i].kp_nthreads;
                pt[i].uptime       = systeminfo.time / 10. - pinfo[i].kp_start.tv_sec;
                pt[i].cpu.time     = (double)((pinfo[i].kp_lwp.kl_uticks + pinfo[i].kp_lwp.kl_sticks + pinfo[i].kp_lwp.kl_iticks) / 1000000.);
                pt[i].memory.usage = (uint64_t)pinfo[i].kp_vm_rssize * (uint64_t)pagesize;
                pt[i].zombie       = pinfo[i].kp_stat == SZOMB ? true : false;
                if (pflags & ProcessEngine_CollectCommandLine) {
                        char **args = kvm_getargv(kvm_handle, &pinfo[i], 0);
                        if (args) {
                                StringBuffer_clear(cmdline);
                                for (int j = 0; args[j]; j++)
                                        StringBuffer_append(cmdline, args[j + 1] ? "%s " : "%s", args[j]);
                                if (StringBuffer_length(cmdline))
                                        pt[i].cmdline = Str_dup(StringBuffer_toString(StringBuffer_trim(cmdline)));
                        }
                        if (! pt[i].cmdline || ! *pt[i].cmdline) {
                                FREE(pt[i].cmdline);
                                pt[i].cmdline = Str_dup(pinfo[i].kp_comm);
                        }
                }
        }
        if (pflags & ProcessEngine_CollectCommandLine)
                StringBuffer_free(&cmdline);

        *reference = pt;
        kvm_close(kvm_handle);

        return treesize;
}
Beispiel #4
0
static void
pr_args(struct kinfo_proc *kp)
{
	char **argv, *str;
	int left;

	if (kp == NULL)
		goto nothing;		/* XXX - can this happen? */
	left = argwidth;
	argv = kvm_getargv(kd, kp, argwidth+60);  /* +60 for ftpd snip */
	if (argv == NULL)
		goto nothing;

	if (*argv == NULL || **argv == '\0') {
		/* Process has zeroed argv[0], display executable name. */
		fmt_putc('(', &left);
		fmt_puts(kp->p_comm, &left);
		fmt_putc(')', &left);
	}
	while (*argv) {
		/*
		 * ftp argv[0] is in the following format:
		 * ftpd: HOSTNAME: [USER/PASS: ]CMD args (ftpd)
		 */
		if (strncmp(*argv, "ftpd:", 5) == 0) {
			if ((str = strchr(*argv + 5, ':')) != NULL)
				str = strchr(str + 1, ':');
			if (str != NULL) {
				if ((str[0] == ':') &&
				    isspace((unsigned char)str[1]))
					str += 2;
				fmt_puts(str, &left);
			} else
				fmt_puts(*argv, &left);
		} else
			fmt_puts(*argv, &left);
		argv++;
		fmt_putc(' ', &left);
	}
	return;
nothing:
	putchar('-');
}
Beispiel #5
0
/**
 * Read all processes to initialize the information tree.
 * @param reference  reference of ProcessTree
 * @return treesize>0 if succeeded otherwise =0.
 */
int initprocesstree_sysdep(ProcessTree_T **reference) {
  int                i;
  int                treesize;
  static kvm_t      *kvm_handle;
  ProcessTree_T     *pt;
  struct kinfo_proc *pinfo;

  if (!(kvm_handle = kvm_open(NULL, _PATH_DEVNULL, NULL, O_RDONLY, prog))) {
    LogError("system statistic error -- cannot initialize kvm interface\n");
    return FALSE;
  }

  pinfo = kvm_getprocs(kvm_handle, KERN_PROC_ALL, 0, &treesize);
  if (!pinfo || (treesize < 1)) {
    LogError("system statistic error -- cannot get process tree\n");
    kvm_close(kvm_handle);
    return FALSE;
  }

  pt = xcalloc(sizeof(ProcessTree_T), treesize);

  for (i = 0; i < treesize; i++) {
    int        j, flags;
    char      *procname = NULL;
    char     **args;
    Buffer_T   cmdline;

    memset(&cmdline, 0, sizeof(Buffer_T));
#if (__FreeBSD_version > 500000)
    pt[i].pid       = pinfo[i].ki_pid;
    pt[i].ppid      = pinfo[i].ki_ppid;
    pt[i].starttime = pinfo[i].ki_start.tv_sec;
    pt[i].cputime   = (long)(pinfo[i].ki_runtime / 100000);
    pt[i].mem_kbyte = (unsigned long)(pinfo[i].ki_rssize * pagesize_kbyte);
    flags           = pinfo[i].ki_stat;
    args            = kvm_getargv(kvm_handle, &pinfo[i], 0);
    procname        = pinfo[i].ki_comm;
#else
    pt[i].pid       = pinfo[i].kp_proc.p_pid;
    pt[i].ppid      = pinfo[i].kp_eproc.e_ppid;
    pt[i].starttime = pinfo[i].kp_eproc.e_stats.p_start.tv_sec;
    pt[i].cputime   = (long)(pinfo[i].kp_proc.p_runtime / 100000);
    pt[i].mem_kbyte = (unsigned long)(pinfo[i].kp_eproc.e_vm.vm_rssize * pagesize_kbyte);
    flags           = pinfo[i].kp_proc.p_stat;
    args            = kvm_getargv(kvm_handle, &pinfo[i], 0);
    procname        = pinfo[i].kp_proc.p_comm;
#endif
    if (flags == SZOMB)
      pt[i].status_flag |= PROCESS_ZOMBIE;
    pt[i].cpu_percent = 0;
    pt[i].time = get_float_time();

    if (args) {
      for (j = 0; args[j]; j++)
        Util_stringbuffer(&cmdline, args[j + 1] ? "%s " : "%s", args[j]);
      pt[i].cmdline = cmdline.buf;
    }
    if (! pt[i].cmdline || ! *pt[i].cmdline)
      pt[i].cmdline = xstrdup(procname);
  }

  *reference = pt;
  kvm_close(kvm_handle);

  return treesize;
}
Beispiel #6
0
int
main(int argc, char *argv[])
{
	struct kinfo_proc *kp;
	struct kinfo_proc *dkp;
	struct stat *stp;
	time_t touched;
	int ch, i, nentries, nusers, wcmd, longidle, longattime, dropgid;
	const char *memf, *nlistf, *p;
	char *x_suffix;
	char buf[MAXHOSTNAMELEN], errbuf[_POSIX2_LINE_MAX];
	char fn[MAXHOSTNAMELEN];
	char *dot;

	(void)setlocale(LC_ALL, "");
	use_ampm = (*nl_langinfo(T_FMT_AMPM) != '\0');
	use_comma = (*nl_langinfo(RADIXCHAR) != ',');

	/* Are we w(1) or uptime(1)? */
	if (this_is_uptime(argv[0]) == 0) {
		wcmd = 0;
		p = "";
	} else {
		wcmd = 1;
		p = "dhiflM:N:nsuw";
	}

	dropgid = 0;
	memf = _PATH_DEVNULL;
	nlistf = NULL;
	while ((ch = getopt(argc, argv, p)) != -1)
		switch (ch) {
		case 'd':
			dflag = 1;
			break;
		case 'h':
			header = 0;
			break;
		case 'i':
			sortidle = 1;
			break;
		case 'M':
			header = 0;
			memf = optarg;
			dropgid = 1;
			break;
		case 'N':
			nlistf = optarg;
			dropgid = 1;
			break;
		case 'n':
			nflag = 1;
			break;
		case 'f': case 'l': case 's': case 'u': case 'w':
			warnx("[-flsuw] no longer supported");
			/* FALLTHROUGH */
		case '?':
		default:
			usage(wcmd);
		}
	argc -= optind;
	argv += optind;

	if (!(_res.options & RES_INIT))
		res_init();
	_res.retrans = 2;	/* resolver timeout to 2 seconds per try */
	_res.retry = 1;		/* only try once.. */

	/*
	 * Discard setgid privileges if not the running kernel so that bad
	 * guys can't print interesting stuff from kernel memory.
	 */
	if (dropgid)
		setgid(getgid());

	if ((kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, errbuf)) == NULL)
		errx(1, "%s", errbuf);

	(void)time(&now);

	if (*argv)
		sel_users = argv;

	setutxent();
	for (nusers = 0; (utmp = getutxent()) != NULL;) {
		if (utmp->ut_type != USER_PROCESS)
			continue;
		if (!(stp = ttystat(utmp->ut_line)))
			continue;	/* corrupted record */
		++nusers;
		if (wcmd == 0)
			continue;
		if (sel_users) {
			int usermatch;
			char **user;

			usermatch = 0;
			for (user = sel_users; !usermatch && *user; user++)
				if (!strcmp(utmp->ut_user, *user))
					usermatch = 1;
			if (!usermatch)
				continue;
		}
		if ((ep = calloc(1, sizeof(struct entry))) == NULL)
			errx(1, "calloc");
		*nextp = ep;
		nextp = &ep->next;
		memmove(&ep->utmp, utmp, sizeof *utmp);
		ep->tdev = stp->st_rdev;
		/*
		 * If this is the console device, attempt to ascertain
		 * the true console device dev_t.
		 */
		if (ep->tdev == 0) {
			size_t size;

			size = sizeof(dev_t);
			(void)sysctlbyname("machdep.consdev", &ep->tdev, &size, NULL, 0);
		}
		touched = stp->st_atime;
		if (touched < ep->utmp.ut_tv.tv_sec) {
			/* tty untouched since before login */
			touched = ep->utmp.ut_tv.tv_sec;
		}
		if ((ep->idle = now - touched) < 0)
			ep->idle = 0;
	}
	endutxent();

	if (header || wcmd == 0) {
		pr_header(&now, nusers);
		if (wcmd == 0) {
			(void)kvm_close(kd);
			exit(0);
		}

#define HEADER_USER		"USER"
#define HEADER_TTY		"TTY"
#define HEADER_FROM		"FROM"
#define HEADER_LOGIN_IDLE	"LOGIN@  IDLE "
#define HEADER_WHAT		"WHAT\n"
#define WUSED  (W_DISPUSERSIZE + W_DISPLINESIZE + W_DISPHOSTSIZE + \
		sizeof(HEADER_LOGIN_IDLE) + 3)	/* header width incl. spaces */ 
		(void)printf("%-*.*s %-*.*s %-*.*s  %s", 
				W_DISPUSERSIZE, W_DISPUSERSIZE, HEADER_USER,
				W_DISPLINESIZE, W_DISPLINESIZE, HEADER_TTY,
				W_DISPHOSTSIZE, W_DISPHOSTSIZE, HEADER_FROM,
				HEADER_LOGIN_IDLE HEADER_WHAT);
	}

	if ((kp = kvm_getprocs(kd, KERN_PROC_ALL, 0, &nentries)) == NULL)
		err(1, "%s", kvm_geterr(kd));
	for (i = 0; i < nentries; i++, kp++) {
		if (kp->ki_stat == SIDL || kp->ki_stat == SZOMB ||
		    kp->ki_tdev == NODEV)
			continue;
		for (ep = ehead; ep != NULL; ep = ep->next) {
			if (ep->tdev == kp->ki_tdev) {
				/*
				 * proc is associated with this terminal
				 */
				if (ep->kp == NULL && kp->ki_pgid == kp->ki_tpgid) {
					/*
					 * Proc is 'most interesting'
					 */
					if (proc_compare(ep->kp, kp))
						ep->kp = kp;
				}
				/*
				 * Proc debug option info; add to debug
				 * list using kinfo_proc ki_spare[0]
				 * as next pointer; ptr to ptr avoids the
				 * ptr = long assumption.
				 */
				dkp = ep->dkp;
				ep->dkp = kp;
				debugproc(kp) = dkp;
			}
		}
	}
	if ((ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) == -1 &&
	     ioctl(STDERR_FILENO, TIOCGWINSZ, &ws) == -1 &&
	     ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) == -1) || ws.ws_col == 0)
	       ttywidth = 79;
        else
	       ttywidth = ws.ws_col - 1;
	argwidth = ttywidth - WUSED;
	if (argwidth < 4)
		argwidth = 8;
	for (ep = ehead; ep != NULL; ep = ep->next) {
		if (ep->kp == NULL) {
			ep->args = strdup("-");
			continue;
		}
		ep->args = fmt_argv(kvm_getargv(kd, ep->kp, argwidth),
		    ep->kp->ki_comm, NULL, MAXCOMLEN);
		if (ep->args == NULL)
			err(1, NULL);
	}
	/* sort by idle time */
	if (sortidle && ehead != NULL) {
		struct entry *from, *save;

		from = ehead;
		ehead = NULL;
		while (from != NULL) {
			for (nextp = &ehead;
			    (*nextp) && from->idle >= (*nextp)->idle;
			    nextp = &(*nextp)->next)
				continue;
			save = from;
			from = from->next;
			save->next = *nextp;
			*nextp = save;
		}
	}

	for (ep = ehead; ep != NULL; ep = ep->next) {
		struct addrinfo hints, *res;
		struct sockaddr_storage ss;
		struct sockaddr *sa = (struct sockaddr *)&ss;
		struct sockaddr_in *lsin = (struct sockaddr_in *)&ss;
		struct sockaddr_in6 *lsin6 = (struct sockaddr_in6 *)&ss;
		time_t t;
		int isaddr;

		p = *ep->utmp.ut_host ? ep->utmp.ut_host : "-";
		if ((x_suffix = strrchr(p, ':')) != NULL) {
			if ((dot = strchr(x_suffix, '.')) != NULL &&
			    strchr(dot+1, '.') == NULL)
				*x_suffix++ = '\0';
			else
				x_suffix = NULL;
		}

		isaddr = 0;
		memset(&ss, '\0', sizeof(ss));
		if (inet_pton(AF_INET6, p, &lsin6->sin6_addr) == 1) {
			lsin6->sin6_len = sizeof(*lsin6);
			lsin6->sin6_family = AF_INET6;
			isaddr = 1;
		} else if (inet_pton(AF_INET, p, &lsin->sin_addr) == 1) {
			lsin->sin_len = sizeof(*lsin);
			lsin->sin_family = AF_INET;
			isaddr = 1;
		}
		if (!nflag) {
			/* Attempt to change an IP address into a name */
			if (isaddr && realhostname_sa(fn, sizeof(fn), sa,
			    sa->sa_len) == HOSTNAME_FOUND)
				p = fn;
		} else if (!isaddr) {
			/*
			 * If a host has only one A/AAAA RR, change a
			 * name into an IP address
			 */
			memset(&hints, 0, sizeof(hints));
			hints.ai_flags = AI_PASSIVE;
			hints.ai_family = AF_UNSPEC;
			hints.ai_socktype = SOCK_STREAM;
			if (getaddrinfo(p, NULL, &hints, &res) == 0) {
				if (res->ai_next == NULL &&
				    getnameinfo(res->ai_addr, res->ai_addrlen,
					fn, sizeof(fn), NULL, 0,
					NI_NUMERICHOST) == 0)
					p = fn;
				freeaddrinfo(res);
			}
		}

		if (x_suffix) {
			(void)snprintf(buf, sizeof(buf), "%s:%s", p, x_suffix);
			p = buf;
		}
		if (dflag) {
			for (dkp = ep->dkp; dkp != NULL; dkp = debugproc(dkp)) {
				const char *ptr;

				ptr = fmt_argv(kvm_getargv(kd, dkp, argwidth),
				    dkp->ki_comm, NULL, MAXCOMLEN);
				if (ptr == NULL)
					ptr = "-";
				(void)printf("\t\t%-9d %s\n",
				    dkp->ki_pid, ptr);
			}
		}
		(void)printf("%-*.*s %-*.*s %-*.*s ",
		    W_DISPUSERSIZE, W_DISPUSERSIZE, ep->utmp.ut_user,
		    W_DISPLINESIZE, W_DISPLINESIZE,
		    *ep->utmp.ut_line ?
		    (strncmp(ep->utmp.ut_line, "tty", 3) &&
		    strncmp(ep->utmp.ut_line, "cua", 3) ?
		    ep->utmp.ut_line : ep->utmp.ut_line + 3) : "-",
		    W_DISPHOSTSIZE, W_DISPHOSTSIZE, *p ? p : "-");
		t = ep->utmp.ut_tv.tv_sec;
		longattime = pr_attime(&t, &now);
		longidle = pr_idle(ep->idle);
		(void)printf("%.*s\n", argwidth - longidle - longattime,
		    ep->args);
	}
	(void)kvm_close(kd);
	exit(0);
}
Beispiel #7
0
void
command(const struct kinfo_proc *kp, VARENT *ve)
{
	VAR *v;
	int left, wantspace = 0;
	char **argv, **p;

	v = ve->var;
	if (ve->next != NULL || termwidth != UNLIMITED) {
		if (ve->next == NULL) {
			left = termwidth - (totwidth - v->width);
			if (left < 1) /* already wrapped, just use std width */
				left = v->width;
		} else
			left = v->width;
	} else
		left = -1;
	if (needenv && kd != NULL) {
		argv = kvm_getenvv(kd, kp, termwidth);
		if ((p = argv) != NULL) {
			while (*p) {
				fmt_puts(*p, &left);
				p++;
				if (*p)
					fmt_putc(' ', &left);
				else
					wantspace = 1;
			}
		}
	} else
		argv = NULL;
	if (needcomm) {
		if (!commandonly) {
			if (kd != NULL) {
				argv = kvm_getargv(kd, kp, termwidth);
				if ((p = argv) != NULL) {
					if (wantspace) {
						fmt_putc(' ', &left);
						wantspace = 0;
					}
					while (*p) {
						fmt_puts(*p, &left);
						p++;
						if (*p)
							fmt_putc(' ', &left);
						else
							wantspace = 1;
					}
				}
			}
			if (argv == NULL || argv[0] == '\0' ||
			    strcmp(cmdpart(argv[0]), kp->p_comm)) {
				if (wantspace) {
					fmt_putc(' ', &left);
					wantspace = 0;
				}
				fmt_putc('(', &left);
				fmt_puts(kp->p_comm, &left);
				fmt_putc(')', &left);
			}
		} else {
			if (wantspace) {
				fmt_putc(' ', &left);
				wantspace = 0;
			}
			fmt_puts(kp->p_comm, &left);
		}
	}
	if (ve->next && left > 0) {
		if (wantspace) {
			fmt_putc(' ', &left);
			wantspace = 0;
		}
		printf("%*s", left, "");
	}
}
Beispiel #8
0
void OS_get_table() {
  kvm_t *kd;
  char errbuf[_POSIX2_LINE_MAX];
  struct kinfo_proc *procs;          /* array of processes */
  int count;                         /* returns number of processes */
  int i, j;
  int seconds, minutes, secleft;     /* for time[20] */
  int milsec, shortmsec;             /* for miliseconds of time[20] */      
  int ttynum;
  long start;
  char *ttydev;
  static time_t now;                 /* for started[20] */
  struct tm *tp;                     /* for month/day/hour/min/AM/PM fields of started[20] */
  int SECSPERHOUR = 3600;
  int SECSPERDAY = 24 * 3600;
  pid_t sesid;
  int length;
  char cmndline[MAXARGLN+1];
  char ** argv;

  /* for bless_into_proc */
  static char format[F_LASTFIELD + 1];
  
  /* variables to hold some values for bless_into_proc */
  char state[20];
  char cputime[20];
  char started[20];
  char session[20];
  char shortsess[20];

  /* Open the kvm interface, get a descriptor */
  if ((kd = kvm_open(NULL, NULL, NULL, 0, errbuf)) == NULL) {
    /* fprintf(stderr, "kvm_open: %s\n", errbuf); */
    ppt_croak("kvm_open: ", errbuf);
  }  
 
  /* Get the list of processes. */
  if ((procs = kvm_getprocs(kd, KERN_PROC_ALL, 0, &count)) == NULL) {
	kvm_close(kd);
    /* fprintf(stderr, "kvm_getprocs: %s\n", kvm_geterr(kd)); */
    ppt_croak("kvm_getprocs: ", kvm_geterr(kd));
  }

  /* Iterate through the processes in kinfo_proc, sending proc info */
  /* to bless_into_proc for each proc */
  for (i=0; i < count; i++) {
    static struct pstats ps;
    static struct session seslead;
    strcpy(format, Defaultformat);
	
    /* get ttydev */
    ttynum=procs[i].kp_eproc.e_tdev;
    ttydev=devname(ttynum, S_IFCHR);
    if (ttydev == NULL) ttydev = "??";

    /* get the state of processes */
    switch (procs[i].kp_proc.p_stat) 
      {
      case SIDL:
        strcpy(state, IDLE);
        break;
      case SRUN:
        strcpy(state, RUN);
        break;
      case SSLEEP:
        strcpy(state, SLEEP);
        break;
      case SSTOP:
        strcpy(state, STOP);
        break;
      case SZOMB: 
        strcpy(state, ZOMBIE);
        break;
      default:
        strcpy(state, UNKNOWN);
        break;
      }

    /* get the cpu time of processes */
    seconds=procs[i].kp_proc.p_rtime.tv_sec;
    milsec=procs[i].kp_proc.p_rtime.tv_usec;
    shortmsec=roundit(milsec);  

    if (seconds < 60) {
      if (seconds < 10)
        sprintf(cputime, "0:0%d.%d", seconds, shortmsec);
      else
        sprintf(cputime, "0:%d.%d", seconds, shortmsec);
    }
    else {
      minutes=seconds/60;
      secleft=seconds-(minutes * 60);
      if (secleft < 10)
        sprintf(cputime, "%d:0%d.%d", minutes, secleft, shortmsec);
      else
        sprintf(cputime, "%d:%d.%d", minutes, secleft, shortmsec);
    }

    /* get the start time of process (when started) */
    /* fill the pstats struct using kvm_read */
    if (kvm_read(kd, (u_long)procs[i].kp_proc.p_stats, (char *)&ps, sizeof(ps)) == sizeof(ps)) {
      start=ps.p_start.tv_sec;
      tp=localtime(&start);
      if (!now)
        (void)time(&now);
      if (now - ps.p_start.tv_sec < 24 * SECSPERHOUR) {
        static char fmt[] = __CONCAT("%l:%", "M%p");
        (void)strftime(started, sizeof(started) - 1, fmt, tp);
      } 
      else if (now - ps.p_start.tv_sec < 7 * SECSPERDAY) {
        static char fmt[] = __CONCAT("%a%", "I%p");
        (void)strftime(started, sizeof(started) - 1, fmt, tp);
      } 
      else
        (void)strftime(started, sizeof(started) - 1, "%e%b%y", tp);
    }

    /* get the session ID (ie: session pointer ID) */
    sprintf(session, "%x", (u_long)procs[i].kp_eproc.e_sess);   
    length=strlen(session);
    for (j=0; j < length; j++) {
      if (session[1] == '1') 
        shortsess[j]=session[j+1];
      else
        shortsess[j]=session[j+2];
    } 
    
    /* fill the session leader and proc struct using kvm_read */
    if (kvm_read(kd, (u_long)procs[i].kp_eproc.e_sess, (char *)&seslead, sizeof(seslead)) == sizeof(seslead)) {
      static struct proc leader; 
      if (kvm_read(kd, (u_long)seslead.s_leader, (char *)&leader, sizeof(leader)) == sizeof(leader)) {
        sesid=leader.p_pid;     
      }
    }

	/* retrieve the arguments */
	cmndline[0] = '\0';
	argv = kvm_getargv(kd, (const struct kinfo_proc *) &(procs[i]) , 0);
	if (argv) {
	  int j = 0;
	  while (argv[j] && strlen(cmndline) <= MAXARGLN) {
		strcat(cmndline, argv[j]);
		strcat(cmndline, " ");
		j++;
	  }
	}

    /* access everything else directly from the kernel, send it */
    /* into bless_into_proc */
    bless_into_proc( format,
                     Fields,
                     procs[i].kp_eproc.e_pcred.p_ruid,
                     procs[i].kp_eproc.e_pcred.p_rgid,
                     procs[i].kp_proc.p_pid,
                     procs[i].kp_eproc.e_ppid,
                     procs[i].kp_eproc.e_pgid,
                     procs[i].kp_proc.p_priority - PZERO,
                     shortsess,
                     sesid,
                     cputime,
                     procs[i].kp_eproc.e_wmesg,
                     procs[i].kp_proc.p_comm,
                     state,
                     started,
                     ttydev,
                     ttynum,
					 cmndline
                     );
  }
  if (kd) {
	kvm_close(kd);
  }
}
Beispiel #9
0
int
main(int argc, char **argv)
{
	struct kinfo_proc *kp;
	struct kinfo_proc *dkp;
	struct hostent *hp;
	in_addr_t l;
	int ch, i, nentries, nusers, wcmd, longidle, dropgid;
	char *memf, *nlistf, *p, *x;
#ifdef SUPPORT_UTMP
	struct utmp *ut;
#endif
#ifdef SUPPORT_UTMPX
	struct utmpx *utx;
#endif
	char buf[MAXHOSTNAMELEN], errbuf[_POSIX2_LINE_MAX];

	(void)setlocale(LC_ALL, "");
	use_ampm = (*nl_langinfo(T_FMT_AMPM) != '\0');
	use_comma = (*nl_langinfo(RADIXCHAR) != ',');

	/* Are we w(1) or uptime(1)? */
	if (this_is_uptime(argv[0]) == 0) {
		wcmd = 0;
		p = "";
	} else {
		wcmd = 1;
		p = "dhiflM:N:nsuw";
	}

	dropgid = 0;
	memf = nlistf = _PATH_DEVNULL;
	while ((ch = getopt(argc, argv, p)) != -1)
		switch (ch) {
		case 'd':
			dflag = 1;
			break;
		case 'h':
			header = 0;
			break;
		case 'i':
			sortidle = 1;
			break;
		case 'M':
			header = 0;
			memf = optarg;
			dropgid = 1;
			break;
		case 'N':
			nlistf = optarg;
			dropgid = 1;
			break;
		case 'n':
			nflag = 1;
			break;
		case 'f': case 'l': case 's': case 'u': case 'w':
			warnx("[-flsuw] no longer supported");
			/* FALLTHROUGH */
		case '?':
		default:
			usage(wcmd);
		}
	argc -= optind;
	argv += optind;

	if (!(_res.options & RES_INIT))
		res_init();
	_res.retrans = 2;	/* resolver timeout to 2 seconds per try */
	_res.retry = 1;		/* only try once.. */

	/*
	 * Discard setgid privileges if not the running kernel so that bad
	 * guys can't print interesting stuff from kernel memory.
	 */
	if (dropgid)
		setgid(getgid());

	if ((kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, errbuf)) == NULL)
		errx(1, "%s", errbuf);

	(void)time(&now);
#ifdef SUPPORT_UTMPX
	setutxent();
#endif
#ifdef SUPPORT_UTMP
	setutent();
#endif

	if (*argv)
		sel_users = argv;

	nusers = 0;
#ifdef SUPPORT_UTMPX
	while ((utx = getutxent()) != NULL) {
		if (utx->ut_type != USER_PROCESS)
			continue;
		++nusers;

		if (sel_users) {
			int usermatch;
			char **user;

			usermatch = 0;
			for (user = sel_users; !usermatch && *user; user++)
				if (!strncmp(utx->ut_name, *user, UTX_USERSIZE))
					usermatch = 1;
			if (!usermatch)
				continue;
		}

		if ((ep = calloc(1, sizeof(struct entry))) == NULL)
			err(1, NULL);
		(void)memcpy(ep->name, utx->ut_name, sizeof(utx->ut_name));
		(void)memcpy(ep->line, utx->ut_line, sizeof(utx->ut_line));
		(void)memcpy(ep->host, utx->ut_host, sizeof(utx->ut_host));
		ep->name[sizeof(utx->ut_name)] = '\0';
		ep->line[sizeof(utx->ut_line)] = '\0';
		ep->host[sizeof(utx->ut_host)] = '\0';
#if 1
		/* XXX: Actually we don't support the utx->ut_ss stuff yet */
		if (!nflag || getnameinfo((struct sockaddr *)&utx->ut_ss,
		    utx->ut_ss.ss_len, ep->host, sizeof(ep->host), NULL, 0,
		    NI_NUMERICHOST) != 0) {
			(void)memcpy(ep->host, utx->ut_host,
			    sizeof(utx->ut_host));
			ep->host[sizeof(utx->ut_host)] = '\0';
		}
#endif
		ep->type[0] = 'x';
		ep->tv = utx->ut_tv;
		ep->pid = utx->ut_pid;

		*nextp = ep;
		nextp = &(ep->next);
		if (wcmd != 0)
			process(ep);
	}
#endif

#ifdef SUPPORT_UTMP
	while ((ut = getutent()) != NULL) {
		if (ut->ut_name[0] == '\0')
			continue;
		++nusers;
		if (sel_users) {
			int usermatch;
			char **user;

			usermatch = 0;
			for (user = sel_users; !usermatch && *user; user++)
				if (!strncmp(ut->ut_name, *user, UT_NAMESIZE))
					usermatch = 1;
			if (!usermatch)
				continue;
		}

		/* Don't process entries that we have utmpx for */
		for (ep = ehead; ep != NULL; ep = ep->next) {
			if (strncmp(ep->line, ut->ut_line,
			    sizeof(ut->ut_line)) == 0)
				break;
		}
		if (ep != NULL) {
			--nusers; /* Duplicate entry */
			continue;
		}

		if ((ep = calloc(1, sizeof(struct entry))) == NULL)
			err(1, NULL);
		(void)memcpy(ep->name, ut->ut_name, sizeof(ut->ut_name));
		(void)memcpy(ep->line, ut->ut_line, sizeof(ut->ut_line));
		(void)memcpy(ep->host, ut->ut_host, sizeof(ut->ut_host));
		ep->name[sizeof(ut->ut_name)] = '\0';
		ep->line[sizeof(ut->ut_line)] = '\0';
		ep->host[sizeof(ut->ut_host)] = '\0';
		ep->tv.tv_sec = ut->ut_time;

		*nextp = ep;
		nextp = &(ep->next);
		if (wcmd != 0)
			process(ep);
	}
#endif

#ifdef SUPPORT_UTMPX
	endutxent();
#endif
#ifdef SUPPORT_UTMP
	endutent();
#endif	
	
	if (header || wcmd == 0) {
		pr_header(&now, nusers);
		if (wcmd == 0) {
			(void)kvm_close(kd);
			exit(0);
		}

#define HEADER_USER		"USER"
#define HEADER_TTY		"TTY"
#define HEADER_FROM		"FROM"
#define HEADER_LOGIN_IDLE	"LOGIN@  IDLE "
#define HEADER_WHAT		"WHAT\n"
#define WUSED  (maxname + maxline + maxhost + \
		sizeof(HEADER_LOGIN_IDLE) + 3)	/* header width incl. spaces */ 
		(void)printf("%-*.*s %-*.*s %-*.*s  %s", 
				maxname, maxname, HEADER_USER,
				maxline, maxline, HEADER_TTY,
				maxhost, maxhost, HEADER_FROM,
				HEADER_LOGIN_IDLE HEADER_WHAT);
	}

	if ((kp = kvm_getprocs(kd, KERN_PROC_ALL, 0, &nentries)) == NULL)
		err(1, "%s", kvm_geterr(kd));
	for (i = 0; i < nentries; i++, kp++) {
		if (kp->kp_stat == SIDL || kp->kp_stat == SZOMB)
			continue;
		for (ep = ehead; ep != NULL; ep = ep->next) {
			if (ep->tdev == kp->kp_tdev) {
				/*
				 * proc is associated with this terminal
				 */
				if (ep->kp == NULL && kp->kp_pgid == kp->kp_tpgid) {
					/*
					 * Proc is 'most interesting'
					 */
					if (proc_compare(ep->kp, kp))
						ep->kp = kp;
				}
				/*
				 * Proc debug option info; add to debug
				 * list using kinfo_proc kp_eproc.e_spare
				 * as next pointer; ptr to ptr avoids the
				 * ptr = long assumption.
				 */
				dkp = ep->dkp;
				ep->dkp = kp;
				debugproc(kp) = dkp;
			}
			if (ep->pid != 0 && ep->pid == kp->kp_pid) {
				ep->kp = kp;
				break;
			}
		}
	}
	if ((ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) == -1 &&
	     ioctl(STDERR_FILENO, TIOCGWINSZ, &ws) == -1 &&
	     ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) == -1) || ws.ws_col == 0)
	       ttywidth = 79;
        else
	       ttywidth = ws.ws_col - 1;
	argwidth = ttywidth - WUSED;
	if (argwidth < 4)
		argwidth = 8;
	for (ep = ehead; ep != NULL; ep = ep->next) {
		if (ep->kp == NULL) {
			ep->args = "-";
			continue;
		}
		ep->args = fmt_argv(kvm_getargv(kd, ep->kp, argwidth),
		    ep->kp->kp_comm, MAXCOMLEN);
		if (ep->args == NULL)
			err(1, NULL);
	}
	/* sort by idle time */
	if (sortidle && ehead != NULL) {
		struct entry *from, *save;

		from = ehead;
		ehead = NULL;
		while (from != NULL) {
			for (nextp = &ehead;
			    (*nextp) && from->idle >= (*nextp)->idle;
			    nextp = &(*nextp)->next)
				continue;
			save = from;
			from = from->next;
			save->next = *nextp;
			*nextp = save;
		}
	}
#if defined(SUPPORT_UTMP) && defined(SUPPORT_UTMPX)
	else if (ehead != NULL) {
		struct entry *from = ehead, *save;

		ehead = NULL;
		while (from != NULL) {
			for (nextp = &ehead;
			    (*nextp) && strcmp(from->line, (*nextp)->line) > 0;
			    nextp = &(*nextp)->next)
				continue;
			save = from;
			from = from->next;
			save->next = *nextp;
			*nextp = save;
		}
	}
#endif

	if (!nflag) {
		if (gethostname(domain, sizeof(domain)) < 0 ||
		    (p = strchr(domain, '.')) == NULL)
			domain[0] = '\0';
		else {
			domain[sizeof(domain) - 1] = '\0';
			memmove(domain, p, strlen(p) + 1);
		}
	}

	for (ep = ehead; ep != NULL; ep = ep->next) {
		char host_buf[UTX_HOSTSIZE + 1];

		host_buf[UTX_HOSTSIZE] = '\0';
		strncpy(host_buf, ep->host, maxhost);
		p = *host_buf ? host_buf : "-";
		if ((x = strchr(p, ':')) != NULL)
			*x++ = '\0';
		if (!nflag && isdigit(*p) && (l = inet_addr(p)) != -1 &&
		    (hp = gethostbyaddr(&l, sizeof(l), AF_INET))) {
			if (domain[0] != '\0') {
				p = hp->h_name;
				p += strlen(hp->h_name);
				p -= strlen(domain);
				if (p > hp->h_name &&
				    strcasecmp(p, domain) == 0)
					*p = '\0';
			}
			p = hp->h_name;
		}
		if (nflag && *p && strcmp(p, "-") &&
		    inet_addr(p) == INADDR_NONE) {
			hp = gethostbyname(p);

			if (hp != NULL) {
				struct in_addr in;

				memmove(&in, hp->h_addr, sizeof(in));
				p = inet_ntoa(in);
			}
		}
		if (x) {
			(void)snprintf(buf, sizeof(buf), "%s:%s", p, x);
			p = buf;
		}
		if (dflag) {
			for (dkp = ep->dkp; dkp != NULL; dkp = debugproc(dkp)) {
				char *ptr;

				ptr = fmt_argv(kvm_getargv(kd, dkp, argwidth),
				    dkp->kp_comm, MAXCOMLEN);
				if (ptr == NULL)
					ptr = "-";
				(void)printf("\t\t%-9d %s\n",
				    dkp->kp_pid, ptr);
			}
		}
		(void)printf("%-*.*s %-*.*s %-*.*s ",
		    maxname, maxname, ep->name,
		    maxline, maxline,
		    strncmp(ep->line, "tty", 3) &&
		    strncmp(ep->line, "cua", 3) ?
		    ep->line : ep->line + 3,
		    maxhost, maxhost, *p ? p : "-");
		then = (time_t)ep->tv.tv_sec;
		pr_attime(&then, &now);
		longidle = pr_idle(ep->idle);
		(void)printf("%.*s\n", argwidth - longidle, ep->args);
	}
	(void)kvm_close(kd);
	exit(0);
}
/* ---------------------------------------------------------------------
 */
int
netsnmp_arch_swrun_container_load( netsnmp_container *container, u_int flags)
{
    struct kinfo_proc   *proc_table;
    int                  nprocs, i, rc;
    char                 buf[BUFSIZ], **argv, *cp;
    char                *name, *path;
    netsnmp_swrun_entry *entry;

    if ( 0 == kd ) {
        DEBUGMSGTL(("swrun:load:arch"," Can't query kvm info\n"));
        return 1;     /* No handle for retrieving process table */
    }
    proc_table = kvm_getprocs(kd, KERN_PROC_ALL, 0, &nprocs );
    for ( i=0 ; i<nprocs; i++ ) {
        if ( 0 == proc_table[i].SWRUN_K_STAT )
            continue;
        entry = netsnmp_swrun_entry_create(proc_table[i].SWRUN_K_PID);
        if (NULL == entry)
            continue;   /* error already logged by function */
        rc = CONTAINER_INSERT(container, entry);

        /*
         * There are two possible sources for the command being run:
         *   - SWRUN_K_COMM  (from the proc_table entry directly)
         *   - running kvm_getargv on the process entry.
         *
         * We'll use argv[0] (if set) for hrSWRunPath,
         *   since that might potentially contain the
         *   absolute path to the running binary.
         * We'll use SWRUN_K_COMM for hrSWRunName,
         *   and as an alternative for hrSWRunPath
         */
        argv = kvm_getargv( kd, &(proc_table[i]), 0);

        entry->hrSWRunName_len = snprintf(entry->hrSWRunName,
                                   sizeof(entry->hrSWRunName)-1,
                                          "%s", proc_table[i].SWRUN_K_COMM);

        if ( argv && *argv)
            entry->hrSWRunPath_len = snprintf(entry->hrSWRunPath,
                                       sizeof(entry->hrSWRunPath)-1,
                                              "%s", argv[0]);
        else {
            memcpy( entry->hrSWRunPath, entry->hrSWRunName,
                                        entry->hrSWRunName_len );
            entry->hrSWRunPath_len = entry->hrSWRunName_len;
        }

        /*
         * Stitch together the rest of argv[] to build hrSWRunParameters
         *
         * Note:
         *   We add a separating space before each argv[] parameter,
         *   *including* the first one.  So we need to skip this
         *   leading space (buf[0]) when setting hrSWRunParameters.
         * This is also why we cleared the first *two* characters
         *   in the buffer initially. If there were no command-line
         *   arguments, then buf[1] would still be a null string.
         */
        buf[0] = '\0';
        buf[1] = '\0';
        if (argv)
            argv++;    /* Skip argv[0] */
        while ( argv && *argv ) {
            strcat(buf, " ");
            strcat(buf, *argv);
            argv++;
        }
        entry->hrSWRunParameters_len = snprintf(entry->hrSWRunParameters,
                                         sizeof(entry->hrSWRunParameters)-1,
                                          "%s", buf+1);

        entry->hrSWRunType = (P_SYSTEM & proc_table[i].SWRUN_K_FLAG) 
#ifdef SWRUN_K_CLASS
                             ? ((PRI_ITHD == proc_table[i].SWRUN_K_CLASS)
                                ? 3  /* device driver    */
                                : 2  /* operating system */
                               )
#else
                             ? 2  /* operating system */
#endif
                             : 4  /*  application     */
                             ;

        switch (proc_table[i].SWRUN_K_STAT) {
        case SRUN:    entry->hrSWRunStatus = HRSWRUNSTATUS_RUNNING;
                      break;
        case SSLEEP:
        case SWAIT:   entry->hrSWRunStatus = HRSWRUNSTATUS_RUNNABLE;
                      break;
        case SSTOP:
        case SLOCK:   entry->hrSWRunStatus = HRSWRUNSTATUS_NOTRUNNABLE;
                      break;
        case SIDL:
        case SZOMB:
        default:      entry->hrSWRunStatus = HRSWRUNSTATUS_INVALID;
                      break;
        }
        
#if defined(freebsd5) && __FreeBSD_version >= 500014
# ifdef NOT_DEFINED
   Apparently following these pointers triggers a SIG10 error

        entry->hrSWRunPerfCPU  = proc_table[i].ki_paddr->p_uticks;
        entry->hrSWRunPerfCPU += proc_table[i].ki_paddr->p_sticks;
        entry->hrSWRunPerfCPU += proc_table[i].ki_paddr->p_iticks;
        entry->hrSWRunPerfMem  = proc_table[i].ki_vmspace->vm_tsize;
        entry->hrSWRunPerfMem += proc_table[i].ki_vmspace->vm_ssize;
        entry->hrSWRunPerfMem += proc_table[i].ki_vmspace->vm_dsize;
        entry->hrSWRunPerfMem *= (getpagesize()/1024);  /* in kB */
# endif
        entry->hrSWRunPerfCPU  = proc_table[i].ki_runtime / 100000;
        entry->hrSWRunPerfMem  = proc_table[i].ki_size / 1024;;
#else
        /*
         * early FreeBSD, NetBSD, OpenBSD
         */
        entry->hrSWRunPerfCPU  = proc_table[i].kp_proc.p_uticks;
        entry->hrSWRunPerfCPU += proc_table[i].kp_proc.p_sticks;
        entry->hrSWRunPerfCPU += proc_table[i].kp_proc.p_iticks;
        entry->hrSWRunPerfMem  = proc_table[i].kp_eproc.e_vm.vm_tsize;
        entry->hrSWRunPerfMem += proc_table[i].kp_eproc.e_vm.vm_ssize;
        entry->hrSWRunPerfMem += proc_table[i].kp_eproc.e_vm.vm_dsize;
        entry->hrSWRunPerfMem *= (getpagesize() / 1024);
#endif
    }
    /*
     * 'proc_table' is owned by the kvm library,
     *   so shouldn't be freed here.
     */

    DEBUGMSGTL(("swrun:load:arch"," loaded %d entries\n",
                CONTAINER_SIZE(container)));

    return 0;
}
Beispiel #11
0
sg_process_stats *sg_get_process_stats(int *entries){
	VECTOR_DECLARE_STATIC(proc_state, sg_process_stats, 64,
			      proc_state_init, proc_state_destroy);
	int proc_state_size = 0;
	sg_process_stats *proc_state_ptr;
#ifdef HPUX
	struct pst_status pstat_procinfo[PROCESS_BATCH];
	long procidx = 0;
	long long pagesize;
	int num, i;
#endif
#ifdef AIX
	struct procentry64 *procs = NULL;
	long long pagesize;
	int fetched = 0;
	pid_t index = 0;
	unsigned proc_idx;
	time_t utime, stime;
	int ncpus;
	struct timeval now_tval;
	double now_time;
	char cmndline[ARG_MAX];
	char comm[ARG_MAX];
	struct procentry64 curproc_for_getargs;
#define PROCS_TO_FETCH  1000
#endif
#ifdef ALLBSD
	int mib[4];
	size_t size;
	struct kinfo_proc *kp_stats;
	int procs, i;
	char *proctitle;
#if (defined(FREEBSD) && !defined(FREEBSD5)) || defined(DFBSD)
	kvm_t *kvmd;
	char **args, **argsp;
	int argslen = 0;
#else
	long buflen;
	char *p, *proctitletmp;
#endif
#ifdef NETBSD2
	int lwps;
	struct kinfo_lwp *kl_stats;
#endif
#endif
#if defined(SOLARIS) || defined(LINUX)
	DIR *proc_dir;
	struct dirent *dir_entry;
	char filename[MAX_FILE_LENGTH];
	FILE *f;
#ifdef SOLARIS
	psinfo_t process_info;
#endif
#ifdef LINUX
	char s;
	/* If someone has a executable of 4k filename length, they deserve to get it truncated :) */
	char ps_name[4096];
	char *ptr;
	VECTOR_DECLARE_STATIC(psargs, char, 128, NULL, NULL);
	unsigned long stime, utime, starttime;
	int x;
	int fn;
	int len;
	int rc;
	time_t uptime;
	long tickspersec;
#endif

#ifdef LINUX
	if ((f=fopen("/proc/uptime", "r")) == NULL) {
		sg_set_error_with_errno(SG_ERROR_OPEN, "/proc/uptime");
		return NULL;
	}
	if((fscanf(f,"%lu %*d",&uptime)) != 1){
		sg_set_error(SG_ERROR_PARSE, NULL);
		return NULL;
	}
	fclose(f);
#endif

	if((proc_dir=opendir(PROC_LOCATION))==NULL){
		sg_set_error_with_errno(SG_ERROR_OPENDIR, PROC_LOCATION);
		return NULL;
	}

	while((dir_entry=readdir(proc_dir))!=NULL){
		if(atoi(dir_entry->d_name) == 0) continue;

#ifdef SOLARIS
		snprintf(filename, MAX_FILE_LENGTH, "/proc/%s/psinfo", dir_entry->d_name);
#endif
#ifdef LINUX
		snprintf(filename, MAX_FILE_LENGTH, "/proc/%s/stat", dir_entry->d_name);
#endif
		if((f=fopen(filename, "r"))==NULL){
			/* Open failed.. Process since vanished, or the path was too long.
			 * Ah well, move onwards to the next one */
			continue;
		}
#ifdef SOLARIS
		fread(&process_info, sizeof(psinfo_t), 1, f);
		fclose(f);
#endif

		if (VECTOR_RESIZE(proc_state, proc_state_size + 1) < 0) {
			return NULL;
		}
		proc_state_ptr = proc_state+proc_state_size;

#ifdef SOLARIS		
		proc_state_ptr->pid = process_info.pr_pid;
		proc_state_ptr->parent = process_info.pr_ppid;
		proc_state_ptr->pgid = process_info.pr_pgid;
		proc_state_ptr->uid = process_info.pr_uid;
		proc_state_ptr->euid = process_info.pr_euid;
		proc_state_ptr->gid = process_info.pr_gid;
		proc_state_ptr->egid = process_info.pr_egid;
		proc_state_ptr->proc_size = (process_info.pr_size) * 1024;
		proc_state_ptr->proc_resident = (process_info.pr_rssize) * 1024;
		proc_state_ptr->time_spent = process_info.pr_time.tv_sec;
		proc_state_ptr->cpu_percent = (process_info.pr_pctcpu * 100.0) / 0x8000;
		proc_state_ptr->nice = (int)process_info.pr_lwp.pr_nice - 20;
		if (sg_update_string(&proc_state_ptr->process_name,
				     process_info.pr_fname) < 0) {
			return NULL;
		}
		if (sg_update_string(&proc_state_ptr->proctitle,
				     process_info.pr_psargs) < 0) {
			return NULL;
		}

		switch (process_info.pr_lwp.pr_state) {
		case 1:
			proc_state_ptr->state = SG_PROCESS_STATE_SLEEPING;
			break;
		case 2:
		case 5:
			proc_state_ptr->state = SG_PROCESS_STATE_RUNNING; 
			break;
		case 3:
			proc_state_ptr->state = SG_PROCESS_STATE_ZOMBIE; 
			break;
		case 4:
			proc_state_ptr->state = SG_PROCESS_STATE_STOPPED; 
			break;
		}
#endif
#ifdef LINUX
		x = fscanf(f, "%d %4096s %c %d %d %*d %*d %*d %*u %*u %*u %*u %*u %lu %lu %*d %*d %*d %d %*d %*d %lu %llu %llu %*u %*u %*u %*u %*u %*u %*u %*u %*u %*u %*u %*u %*u %*d %*d\n", &(proc_state_ptr->pid), ps_name, &s, &(proc_state_ptr->parent), &(proc_state_ptr->pgid), &utime, &stime, &(proc_state_ptr->nice), &starttime, &(proc_state_ptr->proc_size), &(proc_state_ptr->proc_resident));
		/* +3 becuase man page says "Resident  Set Size: number of pages the process has in real memory, minus 3 for administrative purposes." */
		proc_state_ptr->proc_resident = (proc_state_ptr->proc_resident + 3) * getpagesize();
		switch (s) {
		case 'S':
			proc_state_ptr->state = SG_PROCESS_STATE_SLEEPING;
			break;
		case 'R':
			proc_state_ptr->state = SG_PROCESS_STATE_RUNNING;
			break;
		case 'Z':
			proc_state_ptr->state = SG_PROCESS_STATE_ZOMBIE;
			break;
		case 'T':
		case 'D':
			proc_state_ptr->state = SG_PROCESS_STATE_STOPPED;
			break;
		}
	
		/* pa_name[0] should = '(' */
		ptr = strchr(&ps_name[1], ')');	
		if(ptr !=NULL) *ptr='\0';

		if (sg_update_string(&proc_state_ptr->process_name,
				     &ps_name[1]) < 0) {
			return NULL;
		}

		/* cpu */
		proc_state_ptr->cpu_percent = (100.0 * (utime + stime)) / ((uptime * 100.0) - starttime);
		tickspersec = sysconf (_SC_CLK_TCK);
		if (tickspersec < 0) {
			proc_state_ptr->time_spent = 0;
		}
		else {
			proc_state_ptr->time_spent = (utime + stime) / tickspersec;
		}

		fclose(f);

		/* uid / gid */
		snprintf(filename, MAX_FILE_LENGTH, "/proc/%s/status", dir_entry->d_name);
		if ((f=fopen(filename, "r")) == NULL) {
			/* Open failed.. Process since vanished, or the path was too long.
			 * Ah well, move onwards to the next one */
			continue;
		}

		if((ptr=sg_f_read_line(f, "Uid:"))==NULL){
			fclose(f);
			continue;
		}
		sscanf(ptr, "Uid:\t%d\t%d\t%*d\t%*d\n", &(proc_state_ptr->uid), &(proc_state_ptr->euid));

		if((ptr=sg_f_read_line(f, "Gid:"))==NULL){
			fclose(f);
			continue;
		}
		sscanf(ptr, "Gid:\t%d\t%d\t%*d\t%*d\n", &(proc_state_ptr->gid), &(proc_state_ptr->egid));

		fclose(f);

		/* proctitle */	
		snprintf(filename, MAX_FILE_LENGTH, "/proc/%s/cmdline", dir_entry->d_name);

		if((fn=open(filename, O_RDONLY)) == -1){
			/* Open failed.. Process since vanished, or the path was too long.
			 * Ah well, move onwards to the next one */
			continue;
		}

#define READ_BLOCK_SIZE 128
		len = 0;
		do {
			if (VECTOR_RESIZE(psargs, len + READ_BLOCK_SIZE) < 0) {
				return NULL;
			}
			rc = read(fn, psargs + len, READ_BLOCK_SIZE);
			if (rc > 0) {
				len += rc;
			}
		} while (rc == READ_BLOCK_SIZE);
		close(fn);

		if (rc == -1) {
			/* Read failed; move on. */
			continue;
		}

		/* Turn \0s into spaces within the command line. */
		ptr = psargs;
		for(x = 0; x < len; x++) {
			if (*ptr == '\0') *ptr = ' ';
			ptr++;
		}

		if (len == 0) {
			/* We want psargs to be NULL. */
			if (VECTOR_RESIZE(psargs, 0) < 0) {
				return NULL;
			}
		} else {
			/* Not empty, so append a \0. */
			if (VECTOR_RESIZE(psargs, len + 1) < 0) {
				return NULL;
			}
			psargs[len] = '\0';
		}

		if (sg_update_string(&proc_state_ptr->proctitle, psargs) < 0) {
			return NULL;
		}
#endif

		proc_state_size++;
	}
	closedir(proc_dir);
#endif

#ifdef ALLBSD
	mib[0] = CTL_KERN;
	mib[1] = KERN_PROC;
	mib[2] = KERN_PROC_ALL;

	if(sysctl(mib, 3, NULL, &size, NULL, 0) < 0) {
		sg_set_error_with_errno(SG_ERROR_SYSCTL,
		                        "CTL_KERN.KERN_PROC.KERN_PROC_ALL");
		return NULL;
	}

	procs = size / sizeof(struct kinfo_proc);

	kp_stats = sg_malloc(size);
	if(kp_stats == NULL) {
		return NULL;
	}
	memset(kp_stats, 0, size);

	if(sysctl(mib, 3, kp_stats, &size, NULL, 0) < 0) {
		sg_set_error_with_errno(SG_ERROR_SYSCTL,
		                        "CTL_KERN.KERN_PROC.KERN_PROC_ALL");
		free(kp_stats);
		return NULL;
	}

#if (defined(FREEBSD) && !defined(FREEBSD5)) || defined(DFBSD)
	kvmd = sg_get_kvm2();
#endif

	for (i = 0; i < procs; i++) {
		const char *name;

#ifdef FREEBSD5
		if (kp_stats[i].ki_stat == 0) {
#else
		if (kp_stats[i].kp_proc.p_stat == 0) {
#endif
			/* FreeBSD 5 deliberately overallocates the array that
			 * the sysctl returns, so we'll get a few junk
			 * processes on the end that we have to ignore. (Search
			 * for "overestimate by 5 procs" in
			 * src/sys/kern/kern_proc.c for more details.) */
			continue;
		}

		if (VECTOR_RESIZE(proc_state, proc_state_size + 1) < 0) {
			return NULL;
		}
		proc_state_ptr = proc_state+proc_state_size;

#ifdef FREEBSD5
		name = kp_stats[i].ki_comm;
#elif defined(DFBSD)
		name = kp_stats[i].kp_thread.td_comm;
#else
		name = kp_stats[i].kp_proc.p_comm;
#endif
		if (sg_update_string(&proc_state_ptr->process_name, name) < 0) {
			return NULL;
		}

#if defined(FREEBSD5) || defined(NETBSD) || defined(OPENBSD)

#ifdef FREEBSD5
		mib[2] = KERN_PROC_ARGS;
		mib[3] = kp_stats[i].ki_pid;
#else
		mib[1] = KERN_PROC_ARGS;
		mib[2] = kp_stats[i].kp_proc.p_pid;
		mib[3] = KERN_PROC_ARGV;
#endif

		free(proc_state_ptr->proctitle);
		proc_state_ptr->proctitle = NULL;

/* Starting size - we'll double this straight away */
#define PROCTITLE_START_SIZE 64
		buflen = PROCTITLE_START_SIZE;
		size = buflen;
		proctitle = NULL;

		do {
			if((long) size >= buflen) {
				buflen *= 2;
				size = buflen;
				proctitletmp = sg_realloc(proctitle, buflen);
				if(proctitletmp == NULL) {
					free(proctitle);
					proctitle = NULL;
					proc_state_ptr->proctitle = NULL;
					size = 0;
					break;
				}
				proctitle = proctitletmp;
				bzero(proctitle, buflen);
			}

			if(sysctl(mib, 4, proctitle, &size, NULL, 0) < 0) {
				free(proctitle);
				proctitle = NULL;
				proc_state_ptr->proctitle = NULL;
				size = 0;
				break;
			}
		} while((long) size >= buflen);

		if(size > 0) {
			proc_state_ptr->proctitle = sg_malloc(size+1);
			if(proc_state_ptr->proctitle == NULL) {
				return NULL;
			}
			p = proctitle;
#ifdef OPENBSD
			/* On OpenBSD, this value has the argv pointers (which
			 * are terminated by a NULL) at the front, so we have
			 * to skip over them to get to the strings. */
			while (*(char ***)p != NULL) {
				p += sizeof(char **);
			}
			p += sizeof(char **);
#endif
			proc_state_ptr->proctitle[0] = '\0';
			do {
				sg_strlcat(proc_state_ptr->proctitle, p, size+1);
				sg_strlcat(proc_state_ptr->proctitle, " ", size+1);
				p += strlen(p) + 1;
			} while (p < proctitle + size);
			free(proctitle);
			proctitle = NULL;
			/* remove trailing space */
			proc_state_ptr->proctitle[strlen(proc_state_ptr->proctitle)-1] = '\0';
		}
		else {
			if(proctitle != NULL) {
				free(proctitle);
				proctitle = NULL;
			}
			proc_state_ptr->proctitle = NULL;
		}
#else
		free(proc_state_ptr->proctitle);
		proc_state_ptr->proctitle = NULL;
		if(kvmd != NULL) {
			args = kvm_getargv(kvmd, &(kp_stats[i]), 0);
			if(args != NULL) {
				argsp = args;
				while(*argsp != NULL) {
					argslen += strlen(*argsp) + 1;
					argsp++;
				}
				proctitle = sg_malloc(argslen + 1);
				proctitle[0] = '\0';
				if(proctitle == NULL) {
					return NULL;
				}
				while(*args != NULL) {
					sg_strlcat(proctitle, *args, argslen + 1);
					sg_strlcat(proctitle, " ", argslen + 1);
					args++;
				}
				/* remove trailing space */
				proctitle[strlen(proctitle)-1] = '\0';
				proc_state_ptr->proctitle = proctitle;
			}
			else {
				proc_state_ptr->proctitle = NULL;
			}
		}
		else {
			proc_state_ptr->proctitle = NULL;
		}
#endif

#ifdef FREEBSD5
		proc_state_ptr->pid = kp_stats[i].ki_pid;
		proc_state_ptr->parent = kp_stats[i].ki_ppid;
		proc_state_ptr->pgid = kp_stats[i].ki_pgid;
#else
		proc_state_ptr->pid = kp_stats[i].kp_proc.p_pid;
		proc_state_ptr->parent = kp_stats[i].kp_eproc.e_ppid;
		proc_state_ptr->pgid = kp_stats[i].kp_eproc.e_pgid;
#endif

#ifdef FREEBSD5
		proc_state_ptr->uid = kp_stats[i].ki_ruid;
		proc_state_ptr->euid = kp_stats[i].ki_uid;
		proc_state_ptr->gid = kp_stats[i].ki_rgid;
		proc_state_ptr->egid = kp_stats[i].ki_svgid;
#elif defined(DFBSD)
		proc_state_ptr->uid = kp_stats[i].kp_eproc.e_ucred.cr_ruid;
		proc_state_ptr->euid = kp_stats[i].kp_eproc.e_ucred.cr_svuid;
		proc_state_ptr->gid = kp_stats[i].kp_eproc.e_ucred.cr_rgid;
		proc_state_ptr->egid = kp_stats[i].kp_eproc.e_ucred.cr_svgid;
#else
		proc_state_ptr->uid = kp_stats[i].kp_eproc.e_pcred.p_ruid;
		proc_state_ptr->euid = kp_stats[i].kp_eproc.e_pcred.p_svuid;
		proc_state_ptr->gid = kp_stats[i].kp_eproc.e_pcred.p_rgid;
		proc_state_ptr->egid = kp_stats[i].kp_eproc.e_pcred.p_svgid;
#endif

#ifdef FREEBSD5
		proc_state_ptr->proc_size = kp_stats[i].ki_size;
		/* This is in pages */
		proc_state_ptr->proc_resident =
			kp_stats[i].ki_rssize * getpagesize();
		/* This is in microseconds */
		proc_state_ptr->time_spent = kp_stats[i].ki_runtime / 1000000;
		proc_state_ptr->cpu_percent =
			((double)kp_stats[i].ki_pctcpu / FSCALE) * 100.0;
		proc_state_ptr->nice = kp_stats[i].ki_nice;
#else
		proc_state_ptr->proc_size =
			kp_stats[i].kp_eproc.e_vm.vm_map.size;
		/* This is in pages */
		proc_state_ptr->proc_resident =
			kp_stats[i].kp_eproc.e_vm.vm_rssize * getpagesize();
#if defined(NETBSD) || defined(OPENBSD)
		proc_state_ptr->time_spent =
			kp_stats[i].kp_proc.p_rtime.tv_sec;
#elif defined(DFBSD)
		proc_state_ptr->time_spent = 
			( kp_stats[i].kp_thread.td_uticks +
			kp_stats[i].kp_thread.td_sticks +
			kp_stats[i].kp_thread.td_iticks ) / 1000000;
#else
		/* This is in microseconds */
		proc_state_ptr->time_spent =
			kp_stats[i].kp_proc.p_runtime / 1000000;
#endif
		proc_state_ptr->cpu_percent =
			((double)kp_stats[i].kp_proc.p_pctcpu / FSCALE) * 100.0;
		proc_state_ptr->nice = kp_stats[i].kp_proc.p_nice;
#endif

#ifdef NETBSD2
		{
			size_t size;
			int mib[5];

			mib[0] = CTL_KERN;
			mib[1] = KERN_LWP;
			mib[2] = kp_stats[i].kp_proc.p_pid;
			mib[3] = sizeof(struct kinfo_lwp);
			mib[4] = 0;

			if(sysctl(mib, 5, NULL, &size, NULL, 0) < 0) {
				sg_set_error_with_errno(SG_ERROR_SYSCTL, "CTL_KERN.KERN_LWP.pid.structsize.0");
				return NULL;
			}

			lwps = size / sizeof(struct kinfo_lwp);
			mib[4] = lwps;

			kl_stats = sg_malloc(size);
			if(kl_stats == NULL) {
				return NULL;
			}

			if(sysctl(mib, 5, kl_stats, &size, NULL, 0) < 0) {
				sg_set_error_with_errno(SG_ERROR_SYSCTL, "CTL_KERN.KERN_LWP.pid.structsize.buffersize");
				return NULL;
			}
		}

		switch(kp_stats[i].kp_proc.p_stat) {
		case SIDL:
			proc_state_ptr->state = SG_PROCESS_STATE_RUNNING;
			break;
		case SACTIVE:
			{
				int i;

				for(i = 0; i < lwps; i++) {
					switch(kl_stats[i].l_stat) {
					case LSONPROC:
					case LSRUN:
						proc_state_ptr->state = SG_PROCESS_STATE_RUNNING;
						goto end;
					case LSSLEEP:
						proc_state_ptr->state = SG_PROCESS_STATE_SLEEPING;
						goto end;
					case LSSTOP:
					case LSSUSPENDED:
						proc_state_ptr->state = SG_PROCESS_STATE_STOPPED;
						goto end;
					}
					proc_state_ptr->state = SG_PROCESS_STATE_UNKNOWN;
				}
				end: ;
			}
			break;
		case SSTOP:
			proc_state_ptr->state = SG_PROCESS_STATE_STOPPED;
			break;
		case SZOMB:
			proc_state_ptr->state = SG_PROCESS_STATE_ZOMBIE;
			break;
		default:
			proc_state_ptr->state = SG_PROCESS_STATE_UNKNOWN;
			break;
		}

		free(kl_stats);
#else
#ifdef FREEBSD5
		switch (kp_stats[i].ki_stat) {
#else
		switch (kp_stats[i].kp_proc.p_stat) {
#endif
		case SIDL:
		case SRUN:
#ifdef SONPROC
		case SONPROC: /* NetBSD */
#endif
			proc_state_ptr->state = SG_PROCESS_STATE_RUNNING;
			break;
		case SSLEEP:
#ifdef SWAIT
		case SWAIT: /* FreeBSD 5 */
#endif
#ifdef SLOCK
		case SLOCK: /* FreeBSD 5 */
#endif
			proc_state_ptr->state = SG_PROCESS_STATE_SLEEPING;
			break;
		case SSTOP:
			proc_state_ptr->state = SG_PROCESS_STATE_STOPPED;
			break;
		case SZOMB:
#ifdef SDEAD
		case SDEAD: /* OpenBSD & NetBSD */
#endif
			proc_state_ptr->state = SG_PROCESS_STATE_ZOMBIE;
			break;
		default:
			proc_state_ptr->state = SG_PROCESS_STATE_UNKNOWN;
			break;
		}
#endif
		proc_state_size++;
	}

	free(kp_stats);
#endif

#ifdef HPUX
	if ((pagesize = sysconf(_SC_PAGESIZE)) == -1) {
		sg_set_error_with_errno(SG_ERROR_SYSCONF, "_SC_PAGESIZE");
		return NULL;
	}

	while (1) {
		num = pstat_getproc(pstat_procinfo, sizeof pstat_procinfo[0],
		                    PROCESS_BATCH, procidx);
		if (num == -1) {
			sg_set_error_with_errno(SG_ERROR_PSTAT,
			                        "pstat_getproc");
			return NULL;
		} else if (num == 0) {
			break;
		}

		for (i = 0; i < num; i++) {
			struct pst_status *pi = &pstat_procinfo[i];

			if (VECTOR_RESIZE(proc_state, proc_state_size + 1) < 0) {
				return NULL;
			}
			proc_state_ptr = proc_state+proc_state_size;
	
			proc_state_ptr->pid = pi->pst_pid;
			proc_state_ptr->parent = pi->pst_ppid;
			proc_state_ptr->pgid = pi->pst_pgrp;
			proc_state_ptr->uid = pi->pst_uid;
			proc_state_ptr->euid = pi->pst_euid;
			proc_state_ptr->gid = pi->pst_gid;
			proc_state_ptr->egid = pi->pst_egid;
			proc_state_ptr->proc_size = (pi->pst_dsize + pi->pst_tsize + pi->pst_ssize) * pagesize;
			proc_state_ptr->proc_resident = pi->pst_rssize * pagesize;
			proc_state_ptr->time_spent = pi->pst_time;
			proc_state_ptr->cpu_percent = (pi->pst_pctcpu * 100.0) / 0x8000;
			proc_state_ptr->nice = pi->pst_nice;
	
			if (sg_update_string(&proc_state_ptr->process_name,
					     pi->pst_ucomm) < 0) {
				return NULL;
			}
			if (sg_update_string(&proc_state_ptr->proctitle,
					     pi->pst_cmd) < 0) {
				return NULL;
			}
	
			switch (pi->pst_stat) {
			case PS_SLEEP:
				proc_state_ptr->state = SG_PROCESS_STATE_SLEEPING;
				break;
			case PS_RUN:
				proc_state_ptr->state = SG_PROCESS_STATE_RUNNING;
				break;
			case PS_STOP:
				proc_state_ptr->state = SG_PROCESS_STATE_STOPPED;
				break;
			case PS_ZOMBIE:
				proc_state_ptr->state = SG_PROCESS_STATE_ZOMBIE;
				break;
			case PS_IDLE:
			case PS_OTHER:
				proc_state_ptr->state = SG_PROCESS_STATE_UNKNOWN;
				break;
			}
	
			proc_state_size++;
		}
		procidx = pstat_procinfo[num - 1].pst_idx + 1;
	}
#endif

#ifdef AIX
#define	TVALU_TO_SEC(x)	((x).tv_sec + ((double)((x).tv_usec) / 1000000.0))
#define	TVALN_TO_SEC(x)	((x).tv_sec + ((double)((x).tv_usec) / 1000000000.0))
	ncpus = sysconf(_SC_NPROCESSORS_ONLN);
	if( -1 == ncpus ) {
		ncpus = 1; /* sysconf error - assume 1 */
	}

	if ((pagesize = sysconf(_SC_PAGESIZE)) == -1) {
		sg_set_error_with_errno(SG_ERROR_SYSCONF, "_SC_PAGESIZE");
		return NULL;
	}

	proc_idx = 0;
	procs = /* (struct procentry64 *) */ malloc(sizeof(*procs) * PROCS_TO_FETCH);
	if(NULL == procs) {
		sg_set_error_with_errno(SG_ERROR_MALLOC, "sg_get_process_stats");
		return 0;
	}

	gettimeofday(&now_tval, 0);
	now_time = TVALU_TO_SEC(now_tval);

	/* keep on grabbing chunks of processes until getprocs returns a smaller
	   block than we asked for */
	do {
		int i;
		fetched = getprocs64(procs, sizeof(*procs), NULL, 0, &index, PROCS_TO_FETCH);
		if (VECTOR_RESIZE(proc_state, proc_state_size + fetched) < 0) {
			sg_set_error_with_errno(SG_ERROR_MALLOC, "sg_get_process_stats");
			free(procs);
			return NULL;
		}
		for( i = 0; i < fetched; ++i ) {
			struct procentry64 *pi = procs+i;
			int zombie = 0;

			proc_state_ptr = proc_state + proc_idx;

			zombie = 0;

			/* set a descriptive name for the process state */
			switch( pi->pi_state ) {
			case SSLEEP:
				proc_state_ptr->state = SG_PROCESS_STATE_SLEEPING;
				break;
			case SRUN:
				proc_state_ptr->state = SG_PROCESS_STATE_RUNNING;
				break;
			case SZOMB:
				proc_state_ptr->state = SG_PROCESS_STATE_ZOMBIE;
				zombie = 1;
				break;
			case SSTOP:
				proc_state_ptr->state = SG_PROCESS_STATE_STOPPED;
				break;
			case SACTIVE:
				proc_state_ptr->state = SG_PROCESS_STATE_RUNNING;
				break;
			case SIDL:
			default:
				proc_state_ptr->state = SG_PROCESS_STATE_UNKNOWN;
				break;
			}

			if( zombie ) {
				utime = pi->pi_utime;
				stime = pi->pi_stime;
			} else {
				utime = TVALN_TO_SEC(pi->pi_ru.ru_utime) + TVALN_TO_SEC(pi->pi_cru.ru_utime);
				stime = TVALN_TO_SEC(pi->pi_ru.ru_stime) + TVALN_TO_SEC(pi->pi_cru.ru_stime);
			}

			proc_state_ptr->pid = pi->pi_pid;
			proc_state_ptr->parent = pi->pi_ppid;
			proc_state_ptr->pgid = pi->pi_pgrp;
			proc_state_ptr->uid = pi->pi_cred.crx_ruid;
			proc_state_ptr->euid = pi->pi_cred.crx_uid;
			proc_state_ptr->gid = pi->pi_cred.crx_rgid;
			proc_state_ptr->egid = pi->pi_cred.crx_gid;
			proc_state_ptr->proc_size = pi->pi_size;
			proc_state_ptr->proc_resident = pi->pi_drss + pi->pi_trss; /* XXX might be wrong, see P::PT */
			proc_state_ptr->time_spent = utime + stime;
			proc_state_ptr->cpu_percent = (((double)(utime + stime) * 100) / ( now_time - pi->pi_start )) / ncpus;
			proc_state_ptr->nice = pi->pi_nice;

			/* determine comm & cmndline */
			if( (pi->pi_flags & SKPROC) == SKPROC ) {
				if( pi->pi_pid == 0 ) {
					snprintf(comm, ARG_MAX, "kproc (swapper)");
					snprintf(cmndline, ARG_MAX, "kproc (swapper)");
				} else {
					snprintf(comm, ARG_MAX, "kproc (%s)", pi->pi_comm);
					snprintf(cmndline, ARG_MAX, "kproc (%s)", pi->pi_comm);
				}
			} else {
				snprintf(comm, ARG_MAX, "%s", pi->pi_comm);
				curproc_for_getargs.pi_pid = pi->pi_pid;
				if( getargs(&curproc_for_getargs, sizeof(curproc_for_getargs), cmndline, ARG_MAX) < 0 ) {
					snprintf(cmndline, ARG_MAX, "%s", pi->pi_comm);
				} else {
					int done = 0;
					/* replace NUL characters in command line with spaces */
					char *c = cmndline;
					while( ! done ) {
						if( *c == '\0' ) {
							if( *(c+1) == '\0' ) {
								done = 1;
							} else {
								*c++ = ' ';
							}
						} else {
							++c;
						}
					}
				}
			}


			if (sg_update_string(&proc_state_ptr->process_name, comm) < 0) {
				free(procs);
				return NULL;
			}
			if (sg_update_string(&proc_state_ptr->proctitle, cmndline) < 0) {
				free(procs);
				return NULL;
			}

			proc_idx++;
		}
	} while( fetched >= PROCS_TO_FETCH );

	proc_state_size = proc_idx;

	free(procs);
#endif


#ifdef CYGWIN
	sg_set_error(SG_ERROR_UNSUPPORTED, "Cygwin");
	return NULL;
#endif
#ifdef WIN32
	/* FIXME The data needed for this is probably do able with the 
	 * "performance registry". Although using this appears to be a black
	 * art and closely guarded secret.
	 * This is not directly used in ihost, so not considered a priority */
	sg_set_error(SG_ERROR_UNSUPPORTED, "Win32");
	return NULL;
#endif

	*entries = proc_state_size;
	return proc_state;
}

sg_process_count *sg_get_process_count() {
	static sg_process_count process_stat;
#ifndef WIN32
	sg_process_stats *ps;
	int ps_size, x;
#else
	DWORD aProcesses[1024];
	DWORD cbNeeded;
#endif

	process_stat.sleeping = 0;
	process_stat.running = 0;
	process_stat.zombie = 0;
	process_stat.stopped = 0;
	process_stat.total = 0;

#ifndef WIN32
	ps = sg_get_process_stats(&ps_size);
	if (ps == NULL) {
		return NULL;
	}

	for(x = 0; x < ps_size; x++) {
		switch (ps->state) {
		case SG_PROCESS_STATE_RUNNING:
			process_stat.running++;
			break;
		case SG_PROCESS_STATE_SLEEPING:
			process_stat.sleeping++;
			break;
		case SG_PROCESS_STATE_STOPPED:
			process_stat.stopped++;
			break;
		case SG_PROCESS_STATE_ZOMBIE:
			process_stat.zombie++;
			break;
		default:
			/* currently no mapping for SG_PROCESS_STATE_UNKNOWN in
			 * sg_process_count */
			break;
		}
		ps++;
	}

	process_stat.total = ps_size;
#else
	if (!EnumProcesses(aProcesses, sizeof(aProcesses), &cbNeeded))
		return NULL;
	process_stat.total = cbNeeded / sizeof(DWORD);
#endif

	return &process_stat;
}

int sg_process_compare_name(const void *va, const void *vb) {
	const sg_process_stats *a = (sg_process_stats *)va;
	const sg_process_stats *b = (sg_process_stats *)vb;

	return strcmp(a->process_name, b->process_name);
}

int sg_process_compare_pid(const void *va, const void *vb) {
	const sg_process_stats *a = (sg_process_stats *)va;
	const sg_process_stats *b = (sg_process_stats *)vb;

	if (a->pid < b->pid) {
		return -1;
	} else if (a->pid == b->pid) {
		return 0;
	} else {
		return 1;
	}
}

int sg_process_compare_uid(const void *va, const void *vb) {
	const sg_process_stats *a = (sg_process_stats *)va;
	const sg_process_stats *b = (sg_process_stats *)vb;

	if (a->uid < b->uid) {
		return -1;
	} else if (a->uid == b->uid) {
		return 0;
	} else {
		return 1;
	}
}

int sg_process_compare_gid(const void *va, const void *vb) {
	const sg_process_stats *a = (sg_process_stats *)va;
	const sg_process_stats *b = (sg_process_stats *)vb;

	if (a->gid < b->gid) {
		return -1;
	} else if (a->gid == b->gid) {
		return 0;
	} else {
		return 1;
	}
}

int sg_process_compare_size(const void *va, const void *vb) {
	const sg_process_stats *a = (sg_process_stats *)va;
	const sg_process_stats *b = (sg_process_stats *)vb;

	if (a->proc_size < b->proc_size) {
		return -1;
	} else if (a->proc_size == b->proc_size) {
		return 0;
	} else {
		return 1;
	}
}

int sg_process_compare_res(const void *va, const void *vb) {
	const sg_process_stats *a = (sg_process_stats *)va;
	const sg_process_stats *b = (sg_process_stats *)vb;

	if (a->proc_resident < b->proc_resident) {
		return -1;
	} else if (a->proc_resident == b->proc_resident) {
		return 0;
	} else {
		return 1;
	}
}

int sg_process_compare_cpu(const void *va, const void *vb) {
	const sg_process_stats *a = (sg_process_stats *)va;
	const sg_process_stats *b = (sg_process_stats *)vb;

	if (a->cpu_percent < b->cpu_percent) {
		return -1;
	} else if (a->cpu_percent == b->cpu_percent) {
		return 0;
	} else {
		return 1;
	}
}

int sg_process_compare_time(const void *va, const void *vb) {
	const sg_process_stats *a = (sg_process_stats *)va;
	const sg_process_stats *b = (sg_process_stats *)vb;

	if (a->time_spent < b->time_spent) {
		return -1;
	} else if (a->time_spent == b->time_spent) {
		return 0;
	} else {
		return 1;
	}
}
Beispiel #12
0
/*
 * call-seq:
 *    ProcTable.ps(pid=nil)
 *    ProcTable.ps(pid=nil){ |ps| ... }
 *
 * In block form, yields a ProcTableStruct for each process entry that you
 * have rights to.  This method returns an array of ProcTableStruct's in
 * non-block form.
 *
 * If a +pid+ is provided, then only a single ProcTableStruct is yielded or
 * returned, or nil if no process information is found for that +pid+.
 */
static VALUE pt_ps(int argc, VALUE* argv, VALUE klass){
   kvm_t *kd;
   char errbuf[_POSIX2_LINE_MAX];
   char cmdline[_POSIX_ARG_MAX+1];
   char state[8];
   char** args = malloc(sizeof(char*));
   struct kinfo_proc* procs;
   int count;                     /* Holds total number of processes */
   int i = 0;
   VALUE v_pid, v_tty_num, v_tty_dev, v_start_time;
   VALUE v_pstruct = Qnil;
   VALUE v_array = Qnil;

   rb_scan_args(argc, argv, "01", &v_pid);

   if(!rb_block_given_p())
      v_array = rb_ary_new();

   // Open the kvm interface, get a descriptor
   if ((kd = kvm_open(NULL, NULL, NULL, 0, errbuf)) == NULL)
      rb_raise(cProcTableError, errbuf);

   // Get the list of processes
   if ((procs = kvm_getprocs(kd, KERN_PROC_ALL, 0, &count)) == NULL) {
      strcpy(errbuf,kvm_geterr(kd));
      kvm_close(kd);
      rb_raise(cProcTableError, errbuf);
   }

   for(i=0; i<count; i++){
      // Reset some variables
      v_tty_num = Qnil;
      v_tty_dev = Qnil;
      v_start_time = Qnil;

      // If a PID is provided, skip unless the PID matches
      if(!NIL_P(v_pid)){
#ifdef HAVE_ST_KP_PROC
         if(procs[i].kp_proc.p_pid != NUM2INT(v_pid))
            continue;
#else
         if(procs[i].ki_pid != NUM2INT(v_pid))
            continue;
#endif
      }

      // Get the command line arguments for the process
      cmdline[0] = '\0';
      args = kvm_getargv(kd, (const struct kinfo_proc *)&procs[i], 0);
      if(args){
         int j = 0;
         while (args[j] && strlen(cmdline) <= _POSIX_ARG_MAX) {
            strcat(cmdline, args[j]);
            strcat(cmdline, " ");
            j++;
          }
      }

      // Get the start time of the process
      v_start_time = rb_time_new(
#ifdef HAVE_ST_E_STATS
         procs[i].kp_eproc.e_stats.p_start.tv_sec,
         procs[i].kp_eproc.e_stats.p_start.tv_usec
#else
         0,0
#endif
      );

      // Get the state of the process
#ifdef HAVE_ST_KP_PROC
      switch(procs[i].kp_proc.p_stat)
#else
      switch(procs[i].ki_stat)
#endif
      {
         case SIDL:
            strcpy(state, "idle");
            break;
         case SRUN:
            strcpy(state, "run");
            break;
         case SSLEEP:
            strcpy(state, "sleep");
            break;
         case SSTOP:
            strcpy(state, "stop");
            break;
         case SZOMB:
            strcpy(state, "zombie");
            break;
         default:
            strcpy(state, "unknown");
            break;
      }

      // Get ttynum and ttydev. If ttynum is -1, there is no tty
#ifdef HAVE_ST_KP_EPROC
      v_tty_num = INT2FIX(procs[i].kp_eproc.e_tdev),
      v_tty_dev = rb_str_new2(devname(procs[i].kp_eproc.e_tdev, S_IFCHR));
#elif HAVE_ST_U_KPROC
      v_tty_num = INT2FIX(procs[i].u_kproc.ki_tdev),
      v_tty_dev = rb_str_new2(devname(procs[i].u_kproc.ki_tdev, S_IFCHR));
#else
      v_tty_num = INT2FIX(procs[i].ki_tdev),
      v_tty_dev = rb_str_new2(devname(procs[i].ki_tdev, S_IFCHR));
#endif

#ifdef HAVE_ST_KP_PROC
      v_pstruct = rb_struct_new(
         sProcStruct,
         INT2FIX(procs[i].kp_proc.p_pid),
         INT2FIX(procs[i].kp_eproc.e_ppid),
         INT2FIX(procs[i].kp_eproc.e_pgid),
         INT2FIX(procs[i].kp_eproc.e_pcred.p_ruid),
         INT2FIX(procs[i].kp_eproc.e_pcred.p_rgid),
         rb_str_new2(procs[i].kp_proc.p_comm),
         rb_str_new2(state),
         rb_float_new(procs[i].kp_proc.p_pctcpu),
#ifdef HAVE_ST_P_ONCPU
         INT2FIX(procs[i].kp_proc.p_oncpu),
#else
         Qnil,
#endif
         v_tty_num,
         v_tty_dev,
         rb_str_new2(procs[i].kp_eproc.e_wmesg),
#ifdef HAVE_ST_P_RUNTIME
         INT2FIX(procs[i].kp_proc.p_runtime/1000000),
#else
         Qnil,
#endif
         INT2FIX(procs[i].kp_proc.p_priority),
         INT2FIX(procs[i].kp_proc.p_usrpri),
         INT2FIX(procs[i].kp_proc.p_nice),
         rb_str_new2(cmdline),
         v_start_time,
#ifdef HAVE_ST_E_STATS
         LONG2NUM(procs[i].kp_eproc.e_stats.p_ru.ru_maxrss),
         LONG2NUM(procs[i].kp_eproc.e_stats.p_ru.ru_ixrss),
         LONG2NUM(procs[i].kp_eproc.e_stats.p_ru.ru_idrss),
         LONG2NUM(procs[i].kp_eproc.e_stats.p_ru.ru_isrss),
         LONG2NUM(procs[i].kp_eproc.e_stats.p_ru.ru_minflt),
         LONG2NUM(procs[i].kp_eproc.e_stats.p_ru.ru_majflt),
         LONG2NUM(procs[i].kp_eproc.e_stats.p_ru.ru_nswap),
         LONG2NUM(procs[i].kp_eproc.e_stats.p_ru.ru_inblock),
         LONG2NUM(procs[i].kp_eproc.e_stats.p_ru.ru_oublock),
         LONG2NUM(procs[i].kp_eproc.e_stats.p_ru.ru_msgsnd),
         LONG2NUM(procs[i].kp_eproc.e_stats.p_ru.ru_msgrcv),
         LONG2NUM(procs[i].kp_eproc.e_stats.p_ru.ru_nsignals),
         LONG2NUM(procs[i].kp_eproc.e_stats.p_ru.ru_nvcsw),
         LONG2NUM(procs[i].kp_eproc.e_stats.p_ru.ru_nivcsw),
         LONG2NUM(procs[i].kp_eproc.e_stats.p_ru.ru_utime.tv_sec),
         LONG2NUM(procs[i].kp_eproc.e_stats.p_ru.ru_stime.tv_sec)
#else
         Qnil, Qnil, Qnil, Qnil, Qnil, Qnil, Qnil, Qnil,
         Qnil, Qnil, Qnil, Qnil, Qnil, Qnil, Qnil, Qnil
#endif
      );
#else
      v_pstruct = rb_struct_new(
         sProcStruct,
         INT2FIX(procs[i].ki_pid),
         INT2FIX(procs[i].ki_ppid),
         INT2FIX(procs[i].ki_pgid),
         INT2FIX(procs[i].ki_ruid),
         INT2FIX(procs[i].ki_rgid),
         rb_str_new2(procs[i].ki_ocomm),
         rb_str_new2(state),
         rb_float_new(procs[i].ki_pctcpu),
         INT2FIX(procs[i].ki_oncpu),
         v_tty_num,
         v_tty_dev,
         rb_str_new2(procs[i].ki_wmesg),
         INT2FIX(procs[i].ki_runtime/1000000),
         INT2FIX(procs[i].ki_pri.pri_level),
         INT2FIX(procs[i].ki_pri.pri_user),
         INT2FIX(procs[i].ki_nice),
         rb_str_new2(cmdline),
         v_start_time,
         Qnil, Qnil, Qnil, Qnil, Qnil, Qnil, Qnil, Qnil,
         Qnil, Qnil, Qnil, Qnil, Qnil, Qnil, Qnil, Qnil
      );
#endif

      OBJ_FREEZE(v_pstruct); /* Read-only data */

      if(rb_block_given_p())
         rb_yield(v_pstruct);
      else
         rb_ary_push(v_array, v_pstruct);
   }

   free(args);

   if(kd)
      kvm_close(kd);

   if(!NIL_P(v_pid))
      return v_pstruct;

   return v_array; // Nil if block given
}
void OS_get_table() {
	kvm_t *kd;
	char errbuf[_POSIX2_LINE_MAX];
	struct kinfo_proc *procs;
	int count;
	int i, argcount;
	int ttynum;
	long start;
	char *ttydev;
	char cmndline[ARG_MAX+1];
	char **pargv;

	/* for bless_into_proc */
	static char format[F_LASTFIELD + 2];
	char state[20];

	/* open the kvm interface */
	if ((kd = kvm_open(NULL, NULL, NULL, KVM_NO_FILES, errbuf)) == NULL) {
		ppt_croak("kvm_open: %s", errbuf);
	}

	/* get processes */
	if ((procs = kvm_getprocs(kd, KERN_PROC_ALL, 0, sizeof(*procs), &count)) == NULL) {
		kvm_close(kd);
		ppt_croak("kvm_getprocs: %s", kvm_geterr(kd));
	}

	/* bless_into_proc each process's information */
	for (i=0; i < count; i++) {
		STRLCPY(1,format,Defaultformat);

		/* get ttydev */
		ttynum=procs[i].p_tdev;
		ttydev=devname(ttynum, S_IFCHR);
		if (ttydev == NULL) ttydev = "??";

		/* process state */
		switch (procs[i].p_stat) {
			case SIDL:
				STRLCPY(2,state,"IDLE");
				break;
			case SRUN:
				STRLCPY(3,state,"RUN");
				break;
			case SSLEEP:
				STRLCPY(4,state,"SLEEP");
				break;
			case SSTOP:
				STRLCPY(5,state,"STOP");
				break;
			case SZOMB:
				STRLCPY(6,state,"ZOMBIE");
				break;
			default:
				STRLCPY(7,state,"UNKNOWN");
				break;
		}

		/* arguments */
		cmndline[0] = '\0';
		pargv = kvm_getargv(kd, (const struct kinfo_proc *) &(procs[i]), 0);
		if (pargv) {
			argcount = 0;
			while (pargv[argcount] && strlen(cmndline)+strlen(pargv[argcount])+1 <= ARG_MAX) {
				STRLCAT(1,cmndline,pargv[argcount]);
				if (pargv[argcount+1]) {
					STRLCAT(2,cmndline," ");
				}
				argcount++;
			}
		}

		/* everything else is straightforward, bless the lot */
		bless_into_proc( format,
			Fields,
			ttynum,
			procs[i].p_ruid,
			procs[i].p_rgid,
			procs[i].p_uid,
			procs[i].p_gid,
			procs[i].p_pid,
			procs[i].p_ppid,
			procs[i].p__pgid,
			procs[i].p_sid,
			procs[i].p_rtime_sec,
			procs[i].p_uutime_sec,
			procs[i].p_ustime_sec,
			procs[i].p_ustart_sec,
			procs[i].p_comm,
			state,
			ttydev,
			cmndline
		);
	}
	if (kd) {
		kvm_close(kd);
	}
}
sg_process_stats *sg_get_process_stats(int *entries){
	VECTOR_DECLARE_STATIC(proc_state, sg_process_stats, 64,
			      proc_state_init, proc_state_destroy);
	int proc_state_size = 0;
	sg_process_stats *proc_state_ptr;
#ifdef ALLBSD
	int mib[4];
	size_t size;
	struct kinfo_proc *kp_stats;
	int procs, i;
	char *proctitle;
#if (defined(FREEBSD) && !defined(FREEBSD5)) || defined(DFBSD)
	kvm_t *kvmd;
	char **args, **argsp;
	int argslen = 0;
#else
	long buflen;
	char *p, *proctitletmp;
#endif
#ifdef NETBSD2
	int lwps;
	struct kinfo_lwp *kl_stats;
#endif
#endif
#if defined(SOLARIS) || defined(LINUX)
	DIR *proc_dir;
	struct dirent *dir_entry;
	char filename[MAX_FILE_LENGTH];
	FILE *f;
#ifdef SOLARIS
	psinfo_t process_info;
#endif
#ifdef LINUX
	char s;
	/* If someone has a executable of 4k filename length, they deserve to get it truncated :) */
	char ps_name[4096];
	char *ptr;
	VECTOR_DECLARE_STATIC(psargs, char, 128, NULL, NULL);
	unsigned long stime, utime, starttime;
	int x;
	int fn;
	int len;
	int rc;
	time_t uptime;
#endif

#ifdef LINUX
	if ((f=fopen("/proc/uptime", "r")) == NULL) {
		sg_set_error_with_errno(SG_ERROR_OPEN, "/proc/uptime");
		return NULL;
	}
	if((fscanf(f,"%lu %*d",&uptime)) != 1){
		sg_set_error(SG_ERROR_PARSE, NULL);
		return NULL;
	}
	fclose(f);
#endif

	if((proc_dir=opendir(PROC_LOCATION))==NULL){
		sg_set_error_with_errno(SG_ERROR_OPENDIR, PROC_LOCATION);
		return NULL;
	}

	while((dir_entry=readdir(proc_dir))!=NULL){
		if(atoi(dir_entry->d_name) == 0) continue;

#ifdef SOLARIS
		snprintf(filename, MAX_FILE_LENGTH, "/proc/%s/psinfo", dir_entry->d_name);
#endif
#ifdef LINUX
		snprintf(filename, MAX_FILE_LENGTH, "/proc/%s/stat", dir_entry->d_name);
#endif
		if((f=fopen(filename, "r"))==NULL){
			/* Open failed.. Process since vanished, or the path was too long.
			 * Ah well, move onwards to the next one */
			continue;
		}
#ifdef SOLARIS
		fread(&process_info, sizeof(psinfo_t), 1, f);
		fclose(f);
#endif

		if (VECTOR_RESIZE(proc_state, proc_state_size + 1) < 0) {
			return NULL;
		}
		proc_state_ptr = proc_state+proc_state_size;

#ifdef SOLARIS		
		proc_state_ptr->pid = process_info.pr_pid;
		proc_state_ptr->parent = process_info.pr_ppid;
		proc_state_ptr->pgid = process_info.pr_pgid;
		proc_state_ptr->uid = process_info.pr_uid;
		proc_state_ptr->euid = process_info.pr_euid;
		proc_state_ptr->gid = process_info.pr_gid;
		proc_state_ptr->egid = process_info.pr_egid;
		proc_state_ptr->proc_size = (process_info.pr_size) * 1024;
		proc_state_ptr->proc_resident = (process_info.pr_rssize) * 1024;
		proc_state_ptr->time_spent = process_info.pr_time.tv_sec;
		proc_state_ptr->cpu_percent = (process_info.pr_pctcpu * 100.0) / 0x8000;
		proc_state_ptr->nice = (int)process_info.pr_lwp.pr_nice - 20;
		if (sg_update_string(&proc_state_ptr->process_name,
				     process_info.pr_fname) < 0) {
			return NULL;
		}
		if (sg_update_string(&proc_state_ptr->proctitle,
				     process_info.pr_psargs) < 0) {
			return NULL;
		}

		if(process_info.pr_lwp.pr_state==1) proc_state_ptr->state = SG_PROCESS_STATE_SLEEPING;
		if(process_info.pr_lwp.pr_state==2) proc_state_ptr->state = SG_PROCESS_STATE_RUNNING; 
		if(process_info.pr_lwp.pr_state==3) proc_state_ptr->state = SG_PROCESS_STATE_ZOMBIE; 
		if(process_info.pr_lwp.pr_state==4) proc_state_ptr->state = SG_PROCESS_STATE_STOPPED; 
		if(process_info.pr_lwp.pr_state==6) proc_state_ptr->state = SG_PROCESS_STATE_RUNNING; 
#endif
#ifdef LINUX
		x = fscanf(f, "%d %4096s %c %d %d %*d %*d %*d %*u %*u %*u %*u %*u %lu %lu %*d %*d %*d %d %*d %*d %lu %llu %llu %*u %*u %*u %*u %*u %*u %*u %*u %*u %*u %*u %*u %*u %*d %*d\n", &(proc_state_ptr->pid), ps_name, &s, &(proc_state_ptr->parent), &(proc_state_ptr->pgid), &utime, &stime, &(proc_state_ptr->nice), &starttime, &(proc_state_ptr->proc_size), &(proc_state_ptr->proc_resident));
		/* +3 becuase man page says "Resident  Set Size: number of pages the process has in real memory, minus 3 for administrative purposes." */
		proc_state_ptr->proc_resident = (proc_state_ptr->proc_resident + 3) * getpagesize();
		if(s == 'S') proc_state_ptr->state = SG_PROCESS_STATE_SLEEPING;
		if(s == 'R') proc_state_ptr->state = SG_PROCESS_STATE_RUNNING;
		if(s == 'Z') proc_state_ptr->state = SG_PROCESS_STATE_ZOMBIE;
		if(s == 'T') proc_state_ptr->state = SG_PROCESS_STATE_STOPPED;
		if(s == 'D') proc_state_ptr->state = SG_PROCESS_STATE_STOPPED;
	
		/* pa_name[0] should = '(' */
		ptr = strchr(&ps_name[1], ')');	
		if(ptr !=NULL) *ptr='\0';

		if (sg_update_string(&proc_state_ptr->process_name,
				     &ps_name[1]) < 0) {
			return NULL;
		}

		/* cpu */
		proc_state_ptr->cpu_percent = (100.0 * (utime + stime)) / ((uptime * 100.0) - starttime);

		fclose(f);

		/* uid / gid */
		snprintf(filename, MAX_FILE_LENGTH, "/proc/%s/status", dir_entry->d_name);
		if ((f=fopen(filename, "r")) == NULL) {
			/* Open failed.. Process since vanished, or the path was too long.
			 * Ah well, move onwards to the next one */
			continue;
		}

		if((ptr=sg_f_read_line(f, "Uid:"))==NULL){
			fclose(f);
			continue;
		}
		sscanf(ptr, "Uid:\t%d\t%d\t%*d\t%*d\n", &(proc_state_ptr->uid), &(proc_state_ptr->euid));

		if((ptr=sg_f_read_line(f, "Gid:"))==NULL){
			fclose(f);
			continue;
		}
		sscanf(ptr, "Gid:\t%d\t%d\t%*d\t%*d\n", &(proc_state_ptr->gid), &(proc_state_ptr->egid));

		fclose(f);

		/* proctitle */	
		snprintf(filename, MAX_FILE_LENGTH, "/proc/%s/cmdline", dir_entry->d_name);

		if((fn=open(filename, O_RDONLY)) == -1){
			/* Open failed.. Process since vanished, or the path was too long.
			 * Ah well, move onwards to the next one */
			continue;
		}

#define READ_BLOCK_SIZE 128
		len = 0;
		do {
			if (VECTOR_RESIZE(psargs, len + READ_BLOCK_SIZE) < 0) {
				return NULL;
			}
			rc = read(fn, psargs + len, READ_BLOCK_SIZE);
			if (rc > 0) {
				len += rc;
			}
		} while (rc == READ_BLOCK_SIZE);
		close(fn);

		if (rc == -1) {
			/* Read failed; move on. */
			continue;
		}

		/* Turn \0s into spaces within the command line. */
		ptr = psargs;
		for(x = 0; x < len; x++) {
			if (*ptr == '\0') *ptr = ' ';
			ptr++;
		}

		if (len == 0) {
			/* We want psargs to be NULL. */
			if (VECTOR_RESIZE(psargs, 0) < 0) {
				return NULL;
			}
		} else {
			/* Not empty, so append a \0. */
			if (VECTOR_RESIZE(psargs, len + 1) < 0) {
				return NULL;
			}
			psargs[len] = '\0';
		}

		if (sg_update_string(&proc_state_ptr->proctitle, psargs) < 0) {
			return NULL;
		}
#endif

		proc_state_size++;
	}
	closedir(proc_dir);
#endif

#ifdef ALLBSD
	mib[0] = CTL_KERN;
	mib[1] = KERN_PROC;
	mib[2] = KERN_PROC_ALL;

	if(sysctl(mib, 3, NULL, &size, NULL, 0) < 0) {
		sg_set_error_with_errno(SG_ERROR_SYSCTL,
		                        "CTL_KERN.KERN_PROC.KERN_PROC_ALL");
		return NULL;
	}

	procs = size / sizeof(struct kinfo_proc);

	kp_stats = sg_malloc(size);
	if(kp_stats == NULL) {
		return NULL;
	}
	memset(kp_stats, 0, size);

	if(sysctl(mib, 3, kp_stats, &size, NULL, 0) < 0) {
		sg_set_error_with_errno(SG_ERROR_SYSCTL,
		                        "CTL_KERN.KERN_PROC.KERN_PROC_ALL");
		free(kp_stats);
		return NULL;
	}

#if (defined(FREEBSD) && !defined(FREEBSD5)) || defined(DFBSD)
	kvmd = sg_get_kvm2();
#endif

	for (i = 0; i < procs; i++) {
		const char *name;

#ifdef FREEBSD5
		if (kp_stats[i].ki_stat == 0) {
#else
		if (kp_stats[i].kp_proc.p_stat == 0) {
#endif
			/* FreeBSD 5 deliberately overallocates the array that
			 * the sysctl returns, so we'll get a few junk
			 * processes on the end that we have to ignore. (Search
			 * for "overestimate by 5 procs" in
			 * src/sys/kern/kern_proc.c for more details.) */
			continue;
		}

		if (VECTOR_RESIZE(proc_state, proc_state_size + 1) < 0) {
			return NULL;
		}
		proc_state_ptr = proc_state+proc_state_size;

#ifdef FREEBSD5
		name = kp_stats[i].ki_comm;
#elif defined(DFBSD)
		name = kp_stats[i].kp_thread.td_comm;
#else
		name = kp_stats[i].kp_proc.p_comm;
#endif
		if (sg_update_string(&proc_state_ptr->process_name, name) < 0) {
			return NULL;
		}

#if defined(FREEBSD5) || defined(NETBSD) || defined(OPENBSD)

#ifdef FREEBSD5
		mib[2] = KERN_PROC_ARGS;
		mib[3] = kp_stats[i].ki_pid;
#else
		mib[1] = KERN_PROC_ARGS;
		mib[2] = kp_stats[i].kp_proc.p_pid;
		mib[3] = KERN_PROC_ARGV;
#endif

		free(proc_state_ptr->proctitle);
		proc_state_ptr->proctitle = NULL;

/* Starting size - we'll double this straight away */
#define PROCTITLE_START_SIZE 64
		buflen = PROCTITLE_START_SIZE;
		size = buflen;
		proctitle = NULL;

		do {
			if(size >= buflen) {
				buflen *= 2;
				size = buflen;
				proctitletmp = sg_realloc(proctitle, buflen);
				if(proctitletmp == NULL) {
					free(proctitle);
					proctitle = NULL;
					proc_state_ptr->proctitle = NULL;
					size = 0;
					break;
				}
				proctitle = proctitletmp;
				bzero(proctitle, buflen);
			}

			if(sysctl(mib, 4, proctitle, &size, NULL, 0) < 0) {
				free(proctitle);
				proctitle = NULL;
				proc_state_ptr->proctitle = NULL;
				size = 0;
				break;
			}
		} while(size >= buflen);

		if(size > 0) {
			proc_state_ptr->proctitle = sg_malloc(size+1);
			if(proc_state_ptr->proctitle == NULL) {
				return NULL;
			}
			p = proctitle;
#ifdef OPENBSD
			/* On OpenBSD, this value has the argv pointers (which
			 * are terminated by a NULL) at the front, so we have
			 * to skip over them to get to the strings. */
			while (*(char ***)p != NULL) {
				p += sizeof(char **);
			}
			p += sizeof(char **);
#endif
			proc_state_ptr->proctitle[0] = '\0';
			do {
				sg_strlcat(proc_state_ptr->proctitle, p, size+1);
				sg_strlcat(proc_state_ptr->proctitle, " ", size+1);
				p += strlen(p) + 1;
			} while (p < proctitle + size);
			free(proctitle);
			proctitle = NULL;
			/* remove trailing space */
			proc_state_ptr->proctitle[strlen(proc_state_ptr->proctitle)-1] = '\0';
		}
		else {
			if(proctitle != NULL) {
				free(proctitle);
				proctitle = NULL;
			}
			proc_state_ptr->proctitle = NULL;
		}
#else
		free(proc_state_ptr->proctitle);
		proc_state_ptr->proctitle = NULL;
		if(kvmd != NULL) {
			args = kvm_getargv(kvmd, &(kp_stats[i]), 0);
			if(args != NULL) {
				argsp = args;
				while(*argsp != NULL) {
					argslen += strlen(*argsp) + 1;
					argsp++;
				}
				proctitle = sg_malloc(argslen + 1);
				proctitle[0] = '\0';
				if(proctitle == NULL) {
					return NULL;
				}
				while(*args != NULL) {
					sg_strlcat(proctitle, *args, argslen + 1);
					sg_strlcat(proctitle, " ", argslen + 1);
					args++;
				}
				/* remove trailing space */
				proctitle[strlen(proctitle)-1] = '\0';
				proc_state_ptr->proctitle = proctitle;
			}
			else {
				proc_state_ptr->proctitle = NULL;
			}
		}
		else {
			proc_state_ptr->proctitle = NULL;
		}
#endif

#ifdef FREEBSD5
		proc_state_ptr->pid = kp_stats[i].ki_pid;
		proc_state_ptr->parent = kp_stats[i].ki_ppid;
		proc_state_ptr->pgid = kp_stats[i].ki_pgid;
#else
		proc_state_ptr->pid = kp_stats[i].kp_proc.p_pid;
		proc_state_ptr->parent = kp_stats[i].kp_eproc.e_ppid;
		proc_state_ptr->pgid = kp_stats[i].kp_eproc.e_pgid;
#endif

#ifdef FREEBSD5
		proc_state_ptr->uid = kp_stats[i].ki_ruid;
		proc_state_ptr->euid = kp_stats[i].ki_uid;
		proc_state_ptr->gid = kp_stats[i].ki_rgid;
		proc_state_ptr->egid = kp_stats[i].ki_svgid;
#elif defined(DFBSD)
		proc_state_ptr->uid = kp_stats[i].kp_eproc.e_ucred.cr_ruid;
		proc_state_ptr->euid = kp_stats[i].kp_eproc.e_ucred.cr_svuid;
		proc_state_ptr->gid = kp_stats[i].kp_eproc.e_ucred.cr_rgid;
		proc_state_ptr->egid = kp_stats[i].kp_eproc.e_ucred.cr_svgid;
#else
		proc_state_ptr->uid = kp_stats[i].kp_eproc.e_pcred.p_ruid;
		proc_state_ptr->euid = kp_stats[i].kp_eproc.e_pcred.p_svuid;
		proc_state_ptr->gid = kp_stats[i].kp_eproc.e_pcred.p_rgid;
		proc_state_ptr->egid = kp_stats[i].kp_eproc.e_pcred.p_svgid;
#endif

#ifdef FREEBSD5
		proc_state_ptr->proc_size = kp_stats[i].ki_size;
		/* This is in pages */
		proc_state_ptr->proc_resident =
			kp_stats[i].ki_rssize * getpagesize();
		/* This is in microseconds */
		proc_state_ptr->time_spent = kp_stats[i].ki_runtime / 1000000;
		proc_state_ptr->cpu_percent =
			((double)kp_stats[i].ki_pctcpu / FSCALE) * 100.0;
		proc_state_ptr->nice = kp_stats[i].ki_nice;
#else
		proc_state_ptr->proc_size =
			kp_stats[i].kp_eproc.e_vm.vm_map.size;
		/* This is in pages */
		proc_state_ptr->proc_resident =
			kp_stats[i].kp_eproc.e_vm.vm_rssize * getpagesize();
#if defined(NETBSD) || defined(OPENBSD)
		proc_state_ptr->time_spent =
			kp_stats[i].kp_proc.p_rtime.tv_sec;
#elif defined(DFBSD)
		proc_state_ptr->time_spent = 
			( kp_stats[i].kp_thread.td_uticks +
			kp_stats[i].kp_thread.td_sticks +
			kp_stats[i].kp_thread.td_iticks ) / 1000000;
#else
		/* This is in microseconds */
		proc_state_ptr->time_spent =
			kp_stats[i].kp_proc.p_runtime / 1000000;
#endif
		proc_state_ptr->cpu_percent =
			((double)kp_stats[i].kp_proc.p_pctcpu / FSCALE) * 100.0;
		proc_state_ptr->nice = kp_stats[i].kp_proc.p_nice;
#endif

#ifdef NETBSD2
		{
			size_t size;
			int mib[5];

			mib[0] = CTL_KERN;
			mib[1] = KERN_LWP;
			mib[2] = kp_stats[i].kp_proc.p_pid;
			mib[3] = sizeof(struct kinfo_lwp);
			mib[4] = 0;

			if(sysctl(mib, 5, NULL, &size, NULL, 0) < 0) {
				sg_set_error_with_errno(SG_ERROR_SYSCTL, "CTL_KERN.KERN_LWP.pid.structsize.0");
				return NULL;
			}

			lwps = size / sizeof(struct kinfo_lwp);
			mib[4] = lwps;

			kl_stats = sg_malloc(size);
			if(kl_stats == NULL) {
				return NULL;
			}

			if(sysctl(mib, 5, kl_stats, &size, NULL, 0) < 0) {
				sg_set_error_with_errno(SG_ERROR_SYSCTL, "CTL_KERN.KERN_LWP.pid.structsize.buffersize");
				return NULL;
			}
		}

		switch(kp_stats[i].kp_proc.p_stat) {
		case SIDL:
			proc_state_ptr->state = SG_PROCESS_STATE_RUNNING;
			break;
		case SACTIVE:
			{
				int i;

				for(i = 0; i < lwps; i++) {
					switch(kl_stats[i].l_stat) {
					case LSONPROC:
					case LSRUN:
						proc_state_ptr->state = SG_PROCESS_STATE_RUNNING;
						goto end;
					case LSSLEEP:
						proc_state_ptr->state = SG_PROCESS_STATE_SLEEPING;
						goto end;
					case LSSTOP:
					case LSSUSPENDED:
						proc_state_ptr->state = SG_PROCESS_STATE_STOPPED;
						goto end;
					}
					proc_state_ptr->state = SG_PROCESS_STATE_UNKNOWN;
				}
				end: ;
			}
			break;
		case SSTOP:
			proc_state_ptr->state = SG_PROCESS_STATE_STOPPED;
			break;
		case SZOMB:
			proc_state_ptr->state = SG_PROCESS_STATE_ZOMBIE;
			break;
		default:
			proc_state_ptr->state = SG_PROCESS_STATE_UNKNOWN;
			break;
		}

		free(kl_stats);
#else
#ifdef FREEBSD5
		switch (kp_stats[i].ki_stat) {
#else
		switch (kp_stats[i].kp_proc.p_stat) {
#endif
		case SIDL:
		case SRUN:
#ifdef SONPROC
		case SONPROC: /* NetBSD */
#endif
			proc_state_ptr->state = SG_PROCESS_STATE_RUNNING;
			break;
		case SSLEEP:
#ifdef SWAIT
		case SWAIT: /* FreeBSD 5 */
#endif
#ifdef SLOCK
		case SLOCK: /* FreeBSD 5 */
#endif
			proc_state_ptr->state = SG_PROCESS_STATE_SLEEPING;
			break;
		case SSTOP:
			proc_state_ptr->state = SG_PROCESS_STATE_STOPPED;
			break;
		case SZOMB:
#ifdef SDEAD
		case SDEAD: /* OpenBSD & NetBSD */
#endif
			proc_state_ptr->state = SG_PROCESS_STATE_ZOMBIE;
			break;
		default:
			proc_state_ptr->state = SG_PROCESS_STATE_UNKNOWN;
			break;
		}
#endif
		proc_state_size++;
	}

	free(kp_stats);
#endif

#ifdef CYGWIN
	sg_set_error(SG_ERROR_UNSUPPORTED, "Cygwin");
	return NULL;
#endif

	*entries = proc_state_size;
	return proc_state;
}

sg_process_count *sg_get_process_count() {
	static sg_process_count process_stat;
	sg_process_stats *ps;
	int ps_size, x;

	process_stat.sleeping = 0;
	process_stat.running = 0;
	process_stat.zombie = 0;
	process_stat.stopped = 0;
	process_stat.total = 0;

	ps = sg_get_process_stats(&ps_size);
	if (ps == NULL) {
		return NULL;
	}

	for(x = 0; x < ps_size; x++) {
		switch (ps->state) {
		case SG_PROCESS_STATE_RUNNING:
			process_stat.running++;
			break;
		case SG_PROCESS_STATE_SLEEPING:
			process_stat.sleeping++;
			break;
		case SG_PROCESS_STATE_STOPPED:
			process_stat.stopped++;
			break;
		case SG_PROCESS_STATE_ZOMBIE:
			process_stat.zombie++;
			break;
		default:
			/* currently no mapping for SG_PROCESS_STATE_UNKNOWN in
			 * sg_process_count */
			break;
		}
		ps++;
	}

	process_stat.total = ps_size;

	return &process_stat;
}

int sg_process_compare_name(const void *va, const void *vb) {
	const sg_process_stats *a = (sg_process_stats *)va;
	const sg_process_stats *b = (sg_process_stats *)vb;

	return strcmp(a->process_name, b->process_name);
}

int sg_process_compare_pid(const void *va, const void *vb) {
	const sg_process_stats *a = (sg_process_stats *)va;
	const sg_process_stats *b = (sg_process_stats *)vb;

	if (a->pid < b->pid) {
		return -1;
	} else if (a->pid == b->pid) {
		return 0;
	} else {
		return 1;
	}
}

int sg_process_compare_uid(const void *va, const void *vb) {
	const sg_process_stats *a = (sg_process_stats *)va;
	const sg_process_stats *b = (sg_process_stats *)vb;

	if (a->uid < b->uid) {
		return -1;
	} else if (a->uid == b->uid) {
		return 0;
	} else {
		return 1;
	}
}

int sg_process_compare_gid(const void *va, const void *vb) {
	const sg_process_stats *a = (sg_process_stats *)va;
	const sg_process_stats *b = (sg_process_stats *)vb;

	if (a->gid < b->gid) {
		return -1;
	} else if (a->gid == b->gid) {
		return 0;
	} else {
		return 1;
	}
}

int sg_process_compare_size(const void *va, const void *vb) {
	const sg_process_stats *a = (sg_process_stats *)va;
	const sg_process_stats *b = (sg_process_stats *)vb;

	if (a->proc_size < b->proc_size) {
		return -1;
	} else if (a->proc_size == b->proc_size) {
		return 0;
	} else {
		return 1;
	}
}

int sg_process_compare_res(const void *va, const void *vb) {
	const sg_process_stats *a = (sg_process_stats *)va;
	const sg_process_stats *b = (sg_process_stats *)vb;

	if (a->proc_resident < b->proc_resident) {
		return -1;
	} else if (a->proc_resident == b->proc_resident) {
		return 0;
	} else {
		return 1;
	}
}

int sg_process_compare_cpu(const void *va, const void *vb) {
	const sg_process_stats *a = (sg_process_stats *)va;
	const sg_process_stats *b = (sg_process_stats *)vb;

	if (a->cpu_percent < b->cpu_percent) {
		return -1;
	} else if (a->cpu_percent == b->cpu_percent) {
		return 0;
	} else {
		return 1;
	}
}

int sg_process_compare_time(const void *va, const void *vb) {
	const sg_process_stats *a = (sg_process_stats *)va;
	const sg_process_stats *b = (sg_process_stats *)vb;

	if (a->time_spent < b->time_spent) {
		return -1;
	} else if (a->time_spent == b->time_spent) {
		return 0;
	} else {
		return 1;
	}
}
Beispiel #15
0
//FreeBSD has this
DWORD
CTGetPidOfCmdLine(
    PCSTR programName,
    PCSTR programFilename,
    PCSTR cmdLine,
    uid_t owner,
    pid_t *pid,
    size_t *count
    )
{
    DWORD ceError = ERROR_NOT_SUPPORTED;
    size_t fillCount = 0;
    size_t foundCount = 0;
    struct stat findStat;
    //FreeBSD has this
    char pathBuffer[MAXPATHLEN];
    size_t len;
    int unfilteredCount;
    kvm_t *kd = NULL;
    struct kinfo_proc *procs;
    int i;
    struct kinfo_proc *pos;
    int sysctlName[4] = {
        CTL_KERN,
        KERN_PROC,
        KERN_PROC_PATHNAME,
        0 };

    if(count)
    {
        fillCount = *count;
        *count = 0;
    }
    else if(pid != NULL)
        fillCount = 1;

    if(programFilename != NULL)
    {
        while(stat(programFilename, &findStat) < 0)
        {
            if(errno == EINTR)
                continue;
            GCE(ceError = LwMapErrnoToLwError(errno));
        }
    }

    kd = kvm_open(NULL, "/dev/null", NULL, O_RDONLY, NULL);
    if (kd == NULL)
        GCE(ceError = DWORD_ACCESS_DENIED);

    procs = kvm_getprocs(kd, KERN_PROC_PROC, 0, &unfilteredCount);
    if (procs == NULL)
        GCE(ceError = DWORD_ACCESS_DENIED);

    pos = procs;
    for(i = 0; i < unfilteredCount; i++,
        pos = (struct kinfo_proc *)((char *)pos + pos->ki_structsize))
    {
        if (owner != (uid_t)-1 && owner != pos->ki_uid)
        {
            continue;
        }
        if (programName != NULL && strcmp(pos->ki_comm, programName))
        {
            continue;
        }
        if (cmdLine != NULL)
        {
            char **args = kvm_getargv(kd, pos, 0);
            char **argPos = args;
            PCSTR cmdLinePos = cmdLine;

            while (*cmdLinePos != '\0')
            {
                if (argPos == NULL || *argPos == NULL)
                    break;

                if (strncmp(cmdLinePos, *argPos, strlen(*argPos)))
                    break;

                cmdLinePos += strlen(*argPos);
                argPos++;

                if(cmdLinePos[0] == ' ')
                    cmdLinePos++;
            }

            if(*cmdLinePos != '\0' || (argPos != NULL && *argPos != NULL))
            {
                //not a match
                continue;
            }
        }
        if (programFilename != NULL)
        {
            pathBuffer[0] = '\0';
            if (pos->ki_textvp != NULL)
            {
                sysctlName[3] = pos->ki_pid;
                len = sizeof(pathBuffer);
                if( sysctl(sysctlName, 4, pathBuffer, &len, NULL, 0) < 0)
                {
		    /* If the executable path does not exist
		       (e.g. because the file was deleted after
		       the program started), move on */
		    if (errno == ENOENT)
			continue;
                    GCE(ceError = LwMapErrnoToLwError(errno));
                }
            }
            if(strcmp(programFilename, pathBuffer))
                continue;
        }

        //This is a match
        if(foundCount < fillCount)
            pid[foundCount] = pos->ki_pid;
        foundCount++;
    }
    ceError = ERROR_SUCCESS;

    if(count)
        *count = foundCount;
    else if(!ceError && foundCount == 0)
        ceError = ERROR_PROC_NOT_FOUND;

cleanup:
    if(kd != NULL)
    {
        kvm_close(kd);
    }

    return ceError;
}
Beispiel #16
0
/**
 * Read all processes to initialize the information tree.
 * @param reference  reference of ProcessTree
 * @return treesize > 0 if succeeded otherwise = 0.
 */
int initprocesstree_sysdep(ProcessTree_T **reference) {
    int                       treesize;
    char                      buf[_POSIX2_LINE_MAX];
    size_t                    size = sizeof(maxslp);
    int                       mib_proc[6] = {CTL_KERN, KERN_PROC, KERN_PROC_KTHREAD, 0, sizeof(struct kinfo_proc), 0};
    static int                mib_maxslp[] = {CTL_VM, VM_MAXSLP};
    ProcessTree_T            *pt;
    kvm_t                    *kvm_handle;
    static struct kinfo_proc *pinfo;

    if (sysctl(mib_maxslp, 2, &maxslp, &size, NULL, 0) < 0) {
        LogError("system statistic error -- vm.maxslp failed");
        return FALSE;
    }

    if (sysctl(mib_proc, 6, NULL, &size, NULL, 0) == -1) {
        LogError("system statistic error -- kern.proc #1 failed");
        return FALSE;
    }

    size *= 2; // Add reserve for new processes which were created between calls of sysctl
    pinfo = CALLOC(1, size);
    mib_proc[5] = (int)(size / sizeof(struct kinfo_proc));
    if (sysctl(mib_proc, 6, pinfo, &size, NULL, 0) == -1) {
        FREE(pinfo);
        LogError("system statistic error -- kern.proc #2 failed");
        return FALSE;
    }

    treesize = (int)(size / sizeof(struct kinfo_proc));

    pt = CALLOC(sizeof(ProcessTree_T), treesize);

    if (! (kvm_handle = kvm_openfiles(NULL, NULL, NULL, KVM_NO_FILES, buf))) {
        LogError("system statistic error -- kvm_openfiles failed: %s", buf);
        return FALSE;
    }

    for (int i = 0; i < treesize; i++) {
        pt[i].pid         = pinfo[i].p_pid;
        pt[i].ppid        = pinfo[i].p_ppid;
        pt[i].starttime   = pinfo[i].p_ustart_sec;
        pt[i].cputime     = (long)((pinfo[i].p_rtime_sec * 10) + (pinfo[i].p_rtime_usec / 100000));
        pt[i].cpu_percent = 0;
        pt[i].mem_kbyte   = (unsigned long)(pinfo[i].p_vm_rssize * pagesize_kbyte);
        if (pinfo[i].p_stat == SZOMB)
            pt[i].status_flag |= PROCESS_ZOMBIE; //FIXME: save system service flag too (kernel threads)
        pt[i].time = get_float_time();
        char **args;
        if ((args = kvm_getargv(kvm_handle, &pinfo[i], 0))) {
            StringBuffer_T cmdline = StringBuffer_create(64);;
            for (int j = 0; args[j]; j++)
                StringBuffer_append(cmdline, args[j + 1] ? "%s " : "%s", args[j]);
            pt[i].cmdline = Str_dup(StringBuffer_toString(StringBuffer_trim(cmdline)));
            StringBuffer_free(&cmdline);
        }
        if (! pt[i].cmdline || ! *pt[i].cmdline)
            pt[i].cmdline = Str_dup(pinfo[i].p_comm);
    }
    FREE(pinfo);
    kvm_close(kvm_handle);

    *reference = pt;

    return treesize;
}
Beispiel #17
0
GSList *
tracker_process_find_all (void)
{
#ifndef __OpenBSD__
    GSList *pids, *l;
    GSList *found_pids = NULL;
    guint32 own_pid;
    guint32 own_uid;
    gchar *own_pid_str;

    /* Unless we are stopping processes or listing processes,
     * don't iterate them.
     */
    pids = tracker_process_get_pids ();

    /* Establish own uid/pid */
    own_pid = (guint32) getpid ();
    own_pid_str = g_strdup_printf ("%d", own_pid);
    own_uid = tracker_process_get_uid_for_pid (own_pid_str, NULL);
    g_free (own_pid_str);

    for (l = pids; l; l = l->next) {
        GError *error = NULL;
        gchar *filename;
#ifdef __sun /* Solaris */
        psinfo_t psinfo = { 0 };
#endif
        gchar *contents = NULL;
        gchar **strv;
        guint uid;
        pid_t pid;

        uid = tracker_process_get_uid_for_pid (l->data, &filename);

        /* Stat the file and make sure current user == file owner */
        if (uid != own_uid) {
            continue;
        }

        pid = atoi (l->data);

        /* Don't return our own PID */
        if (pid == own_pid) {
            continue;
        }

        /* Get contents to determine basename */
        if (!g_file_get_contents (filename, &contents, NULL, &error)) {
            gchar *str;

            str = g_strdup_printf (_("Could not open “%s”"), filename);
            g_printerr ("%s: %s\n",
                        str,
                        error ? error->message : _("No error given"));
            g_free (str);
            g_clear_error (&error);
            g_free (contents);
            g_free (filename);

            continue;
        }
#ifdef __sun /* Solaris */
        memcpy (&psinfo, contents, sizeof (psinfo));

        /* won't work with paths containing spaces :( */
        strv = g_strsplit (psinfo.pr_psargs, " ", 2);
#else
        strv = g_strsplit (contents, "^@", 2);
#endif
        if (strv && strv[0]) {
            gchar *basename;

            basename = g_path_get_basename (strv[0]);

            if ((g_str_has_prefix (basename, "tracker") ||
                    g_str_has_prefix (basename, "lt-tracker"))) {
                found_pids = g_slist_prepend (found_pids, process_data_new (basename, pid));
            } else {
                g_free (basename);
            }
        }

        g_strfreev (strv);
        g_free (contents);
        g_free (filename);
    }

    g_slist_foreach (pids, (GFunc) g_free, NULL);
    g_slist_free (pids);

    return g_slist_reverse (found_pids);
#else /* ! __OpenBSD__ */
    GSList *found_pids = NULL;
    gchar **strv;
    gchar *basename;
    pid_t pid;
    gint i, nproc;
    gchar buf[_POSIX2_LINE_MAX];
    struct kinfo_proc *plist, *kp;
    kvm_t *kd;

    if ((kd = kvm_openfiles (NULL, NULL, NULL, KVM_NO_FILES, buf)) == NULL)
        return NULL;

    if ((plist = kvm_getprocs (kd, KERN_PROC_ALL, 0, sizeof (*plist), &nproc)) == NULL)
        return NULL;

    for (i = 0, kp = plist; i < nproc; i++, kp++) {
        if ((kp->p_flag & P_SYSTEM) != 0)
            continue;
        if ((strv = kvm_getargv (kd, kp, 0)) == NULL)
            continue;

        pid = kp->p_pid;

        /* Don't return our own PID */
        if (pid == getpid ())
            continue;

        /* Don't return PID we don't own */
        if (kp->p_uid != getuid ())
            continue;

        basename = g_path_get_basename (strv[0]);

        if ((g_str_has_prefix (basename, "tracker") ||
                g_str_has_prefix (basename, "lt-tracker"))) {
            found_pids = g_slist_prepend (found_pids, process_data_new (basename, pid));
        } else {
            g_free (basename);
        }
    }

    return g_slist_reverse (found_pids);
#endif
}
Beispiel #18
0
/**
 * Make an SNMP table entry from a kernel one.
 */
static void
kinfo_proc_to_swrun_entry(const struct kinfo_proc *kp,
    struct swrun_entry *entry)
{
	char **argv = NULL;
	uint64_t cpu_time = 0;
	size_t pname_len;

	pname_len = strlen(kp->ki_comm) + 1;
	entry->name = reallocf(entry->name, pname_len);
	if (entry->name != NULL)
		strlcpy(entry->name, kp->ki_comm, pname_len);

	entry->id = &oid_zeroDotZero; /* unknown id - FIXME */

	assert(hr_kd != NULL);

	argv = kvm_getargv(hr_kd, kp, SWR_PARAM_MLEN - 1);
	if(argv != NULL){
		u_char param[SWR_PARAM_MLEN];

		memset(param, '\0', sizeof(param));

		/*
		 * FIXME
		 * Path seems to not be available.
		 * Try to hack the info in argv[0];
		 * this argv is under control of the program so this info
		 * is not realiable
		 */
		if(*argv != NULL && (*argv)[0] == '/') {
			size_t path_len;

			path_len = strlen(*argv) + 1;
			if (path_len > SWR_PATH_MLEN)
				path_len = SWR_PATH_MLEN;

			entry->path = reallocf(entry->path, path_len);
			if (entry->path != NULL) {
				memset(entry->path, '\0', path_len);
				strlcpy((char*)entry->path, *argv, path_len);
			}
		}

		argv++; /* skip the first one which was used for path */

		while (argv != NULL && *argv != NULL ) {
			if (param[0] != 0)  {
				/*
				 * add a space between parameters,
				 * except before the first one
				 */
				strlcat((char *)param, " ", sizeof(param));
			}
			strlcat((char *)param, *argv, sizeof(param));
			argv++;
		}
		/* reuse pname_len */
		pname_len = strlen(param) + 1;
		if (pname_len > SWR_PARAM_MLEN)
			pname_len = SWR_PARAM_MLEN;

		entry->parameters = reallocf(entry->parameters, pname_len);
		strlcpy(entry->parameters, param, pname_len);
	}

	entry->type = (int32_t)(IS_KERNPROC(kp) ? SRT_OPERATING_SYSTEM :
	    SRT_APPLICATION);

	entry->status = (int32_t)swrun_OS_get_proc_status(kp);
	cpu_time = kp->ki_runtime / 100000; /* centi-seconds */

	/* may overflow the snmp type */
	entry->perfCPU = (cpu_time > (uint64_t)INT_MAX ? INT_MAX : cpu_time);
	entry->perfMemory = kp->ki_size / 1024; /* in kilo-bytes */
	entry->r_tick = get_ticks();
}
Beispiel #19
0
void
command(const struct kinfo_proc *kp, VARENT *ve)
{
	VAR *v;
	int left, wantspace = 0;
	char **argv, **p;

	/*
	 * Determine the available number of display columns.
	 * Always decrement and check after writing.
	 * No check is needed before mbswprint()
	 * and after writing the last data, though.
	 */

	v = ve->var;
	if (ve->next != NULL || termwidth != UNLIMITED) {
		if (ve->next == NULL) {
			left = termwidth - (totwidth - v->width);
			if (left < 1) /* already wrapped, just use std width */
				left = v->width;
		} else
			left = v->width;
	} else
		left = INT_MAX;

	if (needenv && kd != NULL) {
		argv = kvm_getenvv(kd, kp, termwidth);
		if ((p = argv) != NULL) {
			while (*p) {
				if (wantspace) {
					putchar(' ');
					left--;
				}
				left -= mbswprint(*p, left, 0);
				if (left == 0)
					return;
				p++;
				wantspace = 1;
			}
		}
	} else
		argv = NULL;

	if (needcomm) {
		if (!commandonly) {
			if (kd != NULL) {
				argv = kvm_getargv(kd, kp, termwidth);
				if ((p = argv) != NULL) {
					while (*p) {
						if (wantspace) {
							putchar(' ');
							left--;
						}
						left -= mbswprint(*p, left, 0);
						if (left == 0)
							return;
						p++;
						wantspace = 1;
					}
				}
			}
			if (argv == NULL || argv[0] == '\0' ||
			    strcmp(cmdpart(argv[0]), kp->p_comm)) {
				if (wantspace) {
					putchar(' ');
					if (--left == 0)
						return;
				}
				putchar('(');
				left--;
				left -= mbswprint(kp->p_comm, left, 0);
				if (left == 0)
					return;
				putchar(')');
				left--;
			}
		} else {
			if (wantspace) {
				putchar(' ');
				left--;
			}
			left -= mbswprint(kp->p_comm, left, 0);
		}
	}
	if (ve->next != NULL)
		while (left-- > 0)
			putchar(' ');
}
Beispiel #20
0
DWORD
CTGetPidOfCmdLine(
    PCSTR programName,
    PCSTR programFilename,
    PCSTR cmdLine,
    uid_t owner,
    pid_t *pid,
    size_t *count
    )
{
    DWORD ceError = ERROR_NOT_SUPPORTED;
    size_t fillCount = 0;
    size_t foundCount = 0;
    struct stat findStat;
#if HAVE_DECL_PSTAT_GETPROC
    //HPUX should have this
    struct pst_status mystatus;
    struct pst_status status[10];
    int inBuffer;
    int i;
#endif
#ifdef HAVE_STRUCT_PSINFO
    //Solaris and AIX should have this
    DIR *dir = NULL;
    struct dirent *dirEntry = NULL;
    PSTR filePath = NULL;
    struct psinfo infoStruct;
    FILE *infoFile = NULL;
    struct stat compareStat;
    BOOLEAN bFileExists;
#endif
#if defined(HAVE_KVM_GETPROCS) && HAVE_DECL_KERN_PROC_PATHNAME
    //FreeBSD has this
    char pathBuffer[MAXPATHLEN];
    size_t len;
    int unfilteredCount;
    kvm_t *kd = NULL;
    struct kinfo_proc *procs;
    int i;
    struct kinfo_proc *pos;
    int sysctlName[4] = {
        CTL_KERN,
        KERN_PROC,
        KERN_PROC_PATHNAME,
        0 };
#endif

    if(count)
    {
        fillCount = *count;
        *count = 0;
    }
    else if(pid != NULL)
        fillCount = 1;

    if(programFilename != NULL)
    {
        while(stat(programFilename, &findStat) < 0)
        {
            if(errno == EINTR)
                continue;
            GCE(ceError = LwMapErrnoToLwError(errno));
        }
    }
    
#if HAVE_DECL_PSTAT_GETPROC
    //First get the process info for this process
    inBuffer = pstat_getproc(&mystatus, sizeof(mystatus), 0,
            getpid());
    if(inBuffer != 1)
        GCE(ceError = LwMapErrnoToLwError(errno));

    //Now look at all processes
    inBuffer = pstat_getproc(status, sizeof(status[0]),
            sizeof(status)/sizeof(status[0]), 0);
    if(inBuffer < 0)
        GCE(ceError = LwMapErrnoToLwError(errno));
    while(inBuffer > 0)
    {
        for(i = 0; i < inBuffer; i++)
        {
            if(memcmp(&mystatus.pst_rdir, &status[i].pst_rdir,
                        sizeof(mystatus.pst_rdir)))
            {
                /* This process has a different root directory (it is being run
                   via a chroot). Let's not count this process as a match. */
                continue;
            }
            if (owner != (uid_t)-1 && owner != status[i].pst_euid)
            {
                continue;
            }
            if (programName != NULL && strcmp(status[i].pst_ucomm, programName))
            {
                continue;
            }
            if (cmdLine != NULL && strcmp(status[i].pst_cmd, cmdLine))
            {
                continue;
            }
            if(programFilename != NULL && (
                    status[i].pst_text.psf_fileid != findStat.st_ino ||
                    status[i].pst_text.psf_fsid.psfs_id != findStat.st_dev ||
                    status[i].pst_text.psf_fsid.psfs_type != findStat.st_fstype
                    ))
            {
                continue;
            }
 
            //This is a match
            if(foundCount < fillCount)
                pid[foundCount] = status[i].pst_pid;
            foundCount++;
        }
        //Continue looking at the process list where we left off
        inBuffer = pstat_getproc(status, sizeof(status[0]),
                sizeof(status)/sizeof(status[0]),
                status[inBuffer - 1].pst_idx + 1);
        if(inBuffer < 0)
            GCE(ceError = LwMapErrnoToLwError(errno));
    }
    ceError = ERROR_SUCCESS;
#endif

#ifdef HAVE_STRUCT_PSINFO
    if ((dir = opendir("/proc")) == NULL) {
        GCE(ceError = LwMapErrnoToLwError(errno));
    }

    while(1)
    {
        errno = 0;
        dirEntry = readdir(dir);
        if(dirEntry == NULL)
        {
            if(errno != 0)
                GCE(ceError = LwMapErrnoToLwError(errno));
            else
            {
                //No error here. We simply read the last entry
                break;
            }
        }
        if(dirEntry->d_name[0] == '.')
            continue;
        // On AIX, there is a /proc/sys which does not contain a psinfo
        if(!isdigit((int)dirEntry->d_name[0]))
            continue;
        CT_SAFE_FREE_STRING(filePath);
        GCE(ceError = CTAllocateStringPrintf(&filePath, "/proc/%s/psinfo",
                    dirEntry->d_name));
        GCE(ceError = CTCheckFileOrLinkExists(filePath, &bFileExists));
        if(!bFileExists)
        {
            // On AIX 6.1, a defunct process can lack a psinfo file.
            continue;
        }
        GCE(ceError = CTSafeCloseFile(&infoFile));
        GCE(ceError = CTOpenFile(filePath, "r", &infoFile));
        if(fread(&infoStruct, sizeof(infoStruct), 1, infoFile) != 1)
        {
            GCE(ceError = LwMapErrnoToLwError(errno));
        }

        if (owner != (uid_t)-1 && owner != infoStruct.pr_euid)
        {
            continue;
        }
        if (programName != NULL && strcmp(infoStruct.pr_fname, programName))
        {
            continue;
        }
        if (cmdLine != NULL && strcmp(infoStruct.pr_psargs, cmdLine))
        {
            continue;
        }
        if(programFilename != NULL)
        {
            CT_SAFE_FREE_STRING(filePath);
            GCE(ceError = CTAllocateStringPrintf(&filePath,
                        "/proc/%s/object/a.out",
                        dirEntry->d_name));

            while(stat(filePath, &compareStat) < 0)
            {
                if(errno == EINTR)
                    continue;
                if(errno == ENOENT || errno == ENOTDIR)
                {
                    //This process wasn't executed from a file?
                    goto not_match;
                }
                GCE(ceError = LwMapErrnoToLwError(errno));
            }
            if(findStat.st_ino != compareStat.st_ino)
                continue;
            if(findStat.st_dev != compareStat.st_dev)
                continue;
            if(findStat.st_rdev != compareStat.st_rdev)
                continue;
        }
 
        //This is a match
        if(foundCount < fillCount)
            pid[foundCount] = infoStruct.pr_pid;
        foundCount++;
not_match:
        ;
    }
#endif

#if defined(HAVE_KVM_GETPROCS) && HAVE_DECL_KERN_PROC_PATHNAME
    kd = kvm_open(NULL, "/dev/null", NULL, O_RDONLY, NULL);
    if (kd == NULL)
        GCE(ceError = DWORD_ACCESS_DENIED);

    procs = kvm_getprocs(kd, KERN_PROC_PROC, 0, &unfilteredCount);
    if (procs == NULL)
        GCE(ceError = DWORD_ACCESS_DENIED);

    pos = procs;
    for(i = 0; i < unfilteredCount; i++,
        pos = (struct kinfo_proc *)((char *)pos + pos->ki_structsize))
    {
        if (owner != (uid_t)-1 && owner != pos->ki_uid)
        {
            continue;
        }
        if (programName != NULL && strcmp(pos->ki_comm, programName))
        {
            continue;
        }
        if (cmdLine != NULL)
        {
            char **args = kvm_getargv(kd, pos, 0);
            char **argPos = args;
            PCSTR cmdLinePos = cmdLine;

            while (*cmdLinePos != '\0')
            {
                if (argPos == NULL || *argPos == NULL)
                    break;

                if (strncmp(cmdLinePos, *argPos, strlen(*argPos)))
                    break;

                cmdLinePos += strlen(*argPos);
                argPos++;

                if(cmdLinePos[0] == ' ')
                    cmdLinePos++;
            }

            if(*cmdLinePos != '\0' || (argPos != NULL && *argPos != NULL))
            {
                //not a match
                continue;
            }
        }
        if (programFilename != NULL)
        {
            pathBuffer[0] = '\0';
            if (pos->ki_textvp != NULL)
            {
                sysctlName[3] = pos->ki_pid;
                len = sizeof(pathBuffer);
                if( sysctl(sysctlName, 4, pathBuffer, &len, NULL, 0) < 0)
                {
		    /* If the executable path does not exist
		       (e.g. because the file was deleted after
		       the program started), move on */
		    if (errno == ENOENT)
			continue;
                    GCE(ceError = LwMapErrnoToLwError(errno));
                }
            }
            if(strcmp(programFilename, pathBuffer))
                continue;
        }

        //This is a match
        if(foundCount < fillCount)
            pid[foundCount] = pos->ki_pid;
        foundCount++;
    }
    ceError = ERROR_SUCCESS;
#endif

    if(count)
        *count = foundCount;
    else if(!ceError && foundCount == 0)
        ceError = ERROR_PROC_NOT_FOUND;

cleanup:
#ifdef HAVE_STRUCT_PSINFO
    if(dir != NULL)
        closedir(dir);
    CT_SAFE_FREE_STRING(filePath);
    CTSafeCloseFile(&infoFile);
#endif
#if defined(HAVE_KVM_GETPROCS) && HAVE_DECL_KERN_PROC_PATHNAME
    if(kd != NULL)
    {
        kvm_close(kd);
    }
#endif

    return ceError;
}