xref: /openbsd-src/usr.bin/tmux/procname.c (revision 4ec73a122782516ae2bc361388b0dd1a22baff3a)
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