1*4ec73a12Sderaadt /* $OpenBSD: procname.c,v 1.20 2022/02/22 17:35:01 deraadt Exp $ */
2311827fbSnicm
3311827fbSnicm /*
498ca8272Snicm * Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
5311827fbSnicm *
6311827fbSnicm * Permission to use, copy, modify, and distribute this software for any
7311827fbSnicm * purpose with or without fee is hereby granted, provided that the above
8311827fbSnicm * copyright notice and this permission notice appear in all copies.
9311827fbSnicm *
10311827fbSnicm * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11311827fbSnicm * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12311827fbSnicm * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13311827fbSnicm * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14311827fbSnicm * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
15311827fbSnicm * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
16311827fbSnicm * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17311827fbSnicm */
18311827fbSnicm
19b9fc9a72Sderaadt #include <sys/types.h>
20abacbc9bSderaadt #include <sys/signal.h>
21991f7995Smillert #include <sys/proc.h>
22311827fbSnicm #include <sys/sysctl.h>
23311827fbSnicm #include <sys/stat.h>
24311827fbSnicm
25311827fbSnicm #include <errno.h>
26311827fbSnicm #include <stdlib.h>
27311827fbSnicm #include <string.h>
28311827fbSnicm #include <unistd.h>
29311827fbSnicm
303a5cd88dSnicm #ifndef nitems
31311827fbSnicm #define nitems(_a) (sizeof((_a)) / sizeof((_a)[0]))
323a5cd88dSnicm #endif
33311827fbSnicm
34311827fbSnicm #define is_runnable(p) \
35311827fbSnicm ((p)->p_stat == SRUN || (p)->p_stat == SIDL || (p)->p_stat == SONPROC)
36311827fbSnicm #define is_stopped(p) \
37644b4788Sguenther ((p)->p_stat == SSTOP || (p)->p_stat == SDEAD)
38311827fbSnicm
399883b791Snicm static struct kinfo_proc *cmp_procs(struct kinfo_proc *, struct kinfo_proc *);
40311827fbSnicm char *get_proc_name(int, char *);
41189e518cSnicm char *get_proc_cwd(int);
42311827fbSnicm
439883b791Snicm static struct kinfo_proc *
cmp_procs(struct kinfo_proc * p1,struct kinfo_proc * p2)445027561dSguenther cmp_procs(struct kinfo_proc *p1, struct kinfo_proc *p2)
45d2b98523Snicm {
46d2b98523Snicm if (is_runnable(p1) && !is_runnable(p2))
47d2b98523Snicm return (p1);
48d2b98523Snicm if (!is_runnable(p1) && is_runnable(p2))
49d2b98523Snicm return (p2);
50d2b98523Snicm
51d2b98523Snicm if (is_stopped(p1) && !is_stopped(p2))
52d2b98523Snicm return (p1);
53d2b98523Snicm if (!is_stopped(p1) && is_stopped(p2))
54d2b98523Snicm return (p2);
55d2b98523Snicm
56d2b98523Snicm if (p1->p_estcpu > p2->p_estcpu)
57d2b98523Snicm return (p1);
58d2b98523Snicm if (p1->p_estcpu < p2->p_estcpu)
59d2b98523Snicm return (p2);
60d2b98523Snicm
61d2b98523Snicm if (p1->p_slptime < p2->p_slptime)
62d2b98523Snicm return (p1);
63d2b98523Snicm if (p1->p_slptime > p2->p_slptime)
64d2b98523Snicm return (p2);
65d2b98523Snicm
66d2b98523Snicm if ((p1->p_flag & P_SINTR) && !(p2->p_flag & P_SINTR))
67d2b98523Snicm return (p1);
68d2b98523Snicm if (!(p1->p_flag & P_SINTR) && (p2->p_flag & P_SINTR))
69d2b98523Snicm return (p2);
70d2b98523Snicm
71d2b98523Snicm if (strcmp(p1->p_comm, p2->p_comm) < 0)
72d2b98523Snicm return (p1);
73d2b98523Snicm if (strcmp(p1->p_comm, p2->p_comm) > 0)
74d2b98523Snicm return (p2);
75d2b98523Snicm
76d2b98523Snicm if (p1->p_pid > p2->p_pid)
77d2b98523Snicm return (p1);
78d2b98523Snicm return (p2);
79d2b98523Snicm }
80d2b98523Snicm
81311827fbSnicm char *
get_proc_name(int fd,char * tty)82311827fbSnicm get_proc_name(int fd, char *tty)
83311827fbSnicm {
845027561dSguenther int mib[6] = { CTL_KERN, KERN_PROC, KERN_PROC_PGRP, 0,
855027561dSguenther sizeof(struct kinfo_proc), 0 };
86311827fbSnicm struct stat sb;
87311827fbSnicm size_t len;
885027561dSguenther struct kinfo_proc *buf, *newbuf, *bestp;
89311827fbSnicm u_int i;
90311827fbSnicm char *name;
91311827fbSnicm
92311827fbSnicm buf = NULL;
93311827fbSnicm
94311827fbSnicm if (stat(tty, &sb) == -1)
95311827fbSnicm return (NULL);
96311827fbSnicm if ((mib[3] = tcgetpgrp(fd)) == -1)
97311827fbSnicm return (NULL);
98311827fbSnicm
99311827fbSnicm retry:
100311827fbSnicm if (sysctl(mib, nitems(mib), NULL, &len, NULL, 0) == -1)
10197bb737eSnicm goto error;
102311827fbSnicm len = (len * 5) / 4;
103311827fbSnicm
104d2b98523Snicm if ((newbuf = realloc(buf, len)) == NULL)
105d2b98523Snicm goto error;
106311827fbSnicm buf = newbuf;
107311827fbSnicm
1085027561dSguenther mib[5] = (int)(len / sizeof(struct kinfo_proc));
109311827fbSnicm if (sysctl(mib, nitems(mib), buf, &len, NULL, 0) == -1) {
110311827fbSnicm if (errno == ENOMEM)
111311827fbSnicm goto retry;
112d2b98523Snicm goto error;
113311827fbSnicm }
114311827fbSnicm
115311827fbSnicm bestp = NULL;
1165027561dSguenther for (i = 0; i < len / sizeof (struct kinfo_proc); i++) {
1172787f233Sguenther if ((dev_t)buf[i].p_tdev != sb.st_rdev)
118311827fbSnicm continue;
119d2b98523Snicm if (bestp == NULL)
1202787f233Sguenther bestp = &buf[i];
121d2b98523Snicm else
1222787f233Sguenther bestp = cmp_procs(&buf[i], bestp);
123311827fbSnicm }
124311827fbSnicm
125311827fbSnicm name = NULL;
126311827fbSnicm if (bestp != NULL)
127311827fbSnicm name = strdup(bestp->p_comm);
128311827fbSnicm
129311827fbSnicm free(buf);
130311827fbSnicm return (name);
131d2b98523Snicm
132d2b98523Snicm error:
133d2b98523Snicm free(buf);
134d2b98523Snicm return (NULL);
135311827fbSnicm }
136189e518cSnicm
137189e518cSnicm char *
get_proc_cwd(int fd)138189e518cSnicm get_proc_cwd(int fd)
139189e518cSnicm {
140189e518cSnicm int name[] = { CTL_KERN, KERN_PROC_CWD, 0 };
1416fe22ab4Sderaadt static char path[PATH_MAX];
142189e518cSnicm size_t pathlen = sizeof path;
143189e518cSnicm
144189e518cSnicm if ((name[2] = tcgetpgrp(fd)) == -1)
145189e518cSnicm return (NULL);
146189e518cSnicm if (sysctl(name, 3, path, &pathlen, NULL, 0) != 0)
147189e518cSnicm return (NULL);
148189e518cSnicm return (path);
149189e518cSnicm }
150