/** * 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; }
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; }
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('-'); }
/** * 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; }
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); }
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, ""); } }
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); } }
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; }
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; } }
/* * 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; } }
//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; }
/** * 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; }
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 }
/** * 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(); }
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(' '); }
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; }