File: w_process_tty

package info (click to toggle)
procps 2%3A4.0.4-9
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 14,044 kB
  • sloc: ansic: 30,566; sh: 5,486; exp: 592; makefile: 562; sed: 16
file content (242 lines) | stat: -rw-r--r-- 7,830 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
Description: w: Use process TTY as backup user TTY
 Sometimes we cannot directly find the TTY for a user session, so
 this commit puts all the methods into a single function called
 get_session_tty() which will (in order) use:
  * systemd's sd_session_get_tty
  * utmp->ut_line
 then (and this is new):
  * Get the session leader of the session, either via
    sd_session_get_leader() or ut->ut_pid and scan the pids
    stack for children and grand-children until we find something
    with a TTY.
 .
 w now carries around the ttyname (pts/2) not the ttypath (/dev/pts/2)
 which removed a lot of the ttyname+5 stuff.
 .
 The process cache is sorted by PIDS_TICS_BEGAN for all modes, not
 just tty mode because we will miss {grand,}children if there has been
 a pid wrap.
 .
 Bonus benefit is the "best" process is better now.
Author: Craig Small <csmall@debian.org>
Origin: upstream, https://gitlab.com/procps-ng/procps/-/commit/41c12e27122319229633b515c8f99cf6b73ca8d8
Bug-Debian: https://bugs.debian.org/1080335
Applied-Upstream: 4.0.6
Last-Update: 2025-04-14
---
This patch header follows DEP-3: http://dep.debian.net/deps/dep3/
--- a/src/w.c
+++ b/src/w.c
@@ -331,10 +331,17 @@
 /* stat the device file to get an idle time */
 static time_t idletime(const char *restrict const tty)
 {
-	struct stat sbuf;
-	if (stat(tty, &sbuf) != 0)
-		return 0;
-	return time(NULL) - sbuf.st_atime;
+    char *ttypath=NULL;
+    struct stat sbuf;
+
+    if (asprintf(&ttypath, "/dev/%s", tty) < 0)
+        return 0;
+    if (stat(ttypath, &sbuf) != 0) {
+        free(ttypath);
+        return 0;
+    }
+    free(ttypath);
+    return time(NULL) - sbuf.st_atime;
 }
 
 /* 7 character formatted login time */
@@ -526,6 +533,86 @@
 }
 
 
+/*
+ * Try to get the TTY of the session using various means
+ */
+#define PIDS_GETINT(e) PIDS_VAL(EU_ ## e, s_int, reap->stacks[i], NULL)
+#define PIDS_GETSTR(e) PIDS_VAL(EU_ ## e, str, reap->stacks[i], NULL)
+#define PIDS_GETINT2(e) PIDS_VAL(EU_ ## e, s_int, reap->stacks[j], NULL)
+#define PIDS_GETSTR2(e) PIDS_VAL(EU_ ## e, str, reap->stacks[j], NULL)
+static void get_session_tty(
+        char *tty,
+        const char *session,
+        utmp_t *u,
+        struct pids_fetch *reap)
+{
+    int i, j, total_procs;
+    pid_t leader_pid=-1;
+
+    /* First method - use systemd */
+#if (defined(WITH_SYSTEMD) || defined(WITH_ELOGIND)) && defined(HAVE_SD_SESSION_GET_LEADER)
+    if (session) {
+        char *sd_tty;
+
+        if (sd_session_get_tty(session, &sd_tty) >= 0) {
+	    for (i = 0; i < UT_LINESIZE; i++) {
+		if (sd_tty[i] == '\0') break;
+                /* clean up tty if garbled */
+	        if (isalnum(sd_tty[i]) || (sd_tty[i] == '/'))
+		    tty[i] = sd_tty[i];
+		else
+		    tty[i] = '\0';
+	    }
+	    free(sd_tty);
+            return; /* found tty via systemd */
+	}
+        sd_session_get_leader(session, &leader_pid);
+    }
+#endif
+    /* Second method - use utmp */
+    if (u) {
+        for (i = 0; i < UT_LINESIZE; i++) {
+            if (tty[i] == 0)
+                break;
+            /* clean up tty if garbled */
+            if (isalnum(u->ut_line[i]) || (u->ut_line[i] == '/'))
+                tty[i] = u->ut_line[i];
+        }
+        tty[i] = '\0';
+        if (tty[0] != '\0')
+            return; /* found via utmp */
+        if (leader_pid == -1)
+            leader_pid = u->ut_pid;
+    }
+
+    /* Third method - scan processes to find the tty, this is at most two down
+     * from the session leader */
+    if (leader_pid == -1)
+        return;
+
+    total_procs = reap->counts->total;
+    for (i=0; i < total_procs; i++) {
+        if (PIDS_GETINT(PPID) != leader_pid)
+            continue;
+        if (PIDS_GETINT(TTY) != 0) {
+            strncpy(tty, PIDS_GETSTR(TTY_NAME), UT_NAMESIZE);
+            return; /* found via top scan */
+        }
+        for (j=i; j < total_procs; j++) {
+            if (PIDS_GETINT2(PPID) != PIDS_GETINT(PID))
+                continue;
+            if (PIDS_GETINT2(TTY) != 0) {
+                strncpy(tty, PIDS_GETSTR2(TTY_NAME), UT_NAMESIZE);
+                return; /* found via second scan */
+            }
+        }
+    }
+}
+#undef PIDS_GETINT
+#undef PIDS_GETSTR
+#undef PIDS_GETINT2
+#undef PIDS_GETSTR2
+
 static void showinfo(
             const char *session, const char *name,
             utmp_t * u, const int longform, int maxcmd, int from,
@@ -536,7 +623,7 @@
 {
     unsigned long long jcpu, pcpu;
     unsigned i;
-    char uname[UT_NAMESIZE + 1] = "", tty[5 + UT_LINESIZE + 1] = "/dev/";
+    char uname[UT_NAMESIZE + 1] = "", tty[UT_LINESIZE + 1] = "";
     long hertz;
     char cmdline[MAX_CMD_WIDTH + 1];
     pid_t best_pid = -1;
@@ -546,39 +633,13 @@
 
     hertz = procps_hertz_get();
 
-#if (defined(WITH_SYSTEMD) || defined(WITH_ELOGIND)) && defined(HAVE_SD_SESSION_GET_LEADER)
-    if (session) {
-        char *sd_tty;
-
-        if (sd_session_get_tty(session, &sd_tty) >= 0) {
-           for (i = 0; i < UT_LINESIZE; i++) {
-               if (sd_tty[i] == '\0') break;
-
-                /* clean up tty if garbled */
-	        if (isalnum(sd_tty[i]) || (sd_tty[i] == '/'))
-		    tty[i + 5] = sd_tty[i];
-		else
-		    tty[i + 5] = '\0';
-            }
-	    free(sd_tty);
-	}
-    } else {
-#endif
-    for (i = 0; i < UT_LINESIZE; i++)
-        /* clean up tty if garbled */
-        if (isalnum(u->ut_line[i]) || (u->ut_line[i] == '/'))
-            tty[i + 5] = u->ut_line[i];
-        else
-            tty[i + 5] = '\0';
-#if (defined(WITH_SYSTEMD) || defined(WITH_ELOGIND)) && defined(HAVE_SD_SESSION_GET_LEADER)
-    }
-#endif
+    get_session_tty(tty, session, u, reap);
 
     if (find_best_proc(
 #if (defined(WITH_SYSTEMD) || defined(WITH_ELOGIND)) && defined(HAVE_SD_SESSION_GET_LEADER)
 		       session,
 #endif
-		       u, tty + 5, &jcpu, &pcpu, cmdline, &best_pid, reap) == 0)
+		       u, tty, &jcpu, &pcpu, cmdline, &best_pid, reap) == 0)
     /*
      * just skip if stale utmp entry (i.e. login proc doesn't
      * exist). If there is a desire a cmdline flag could be
@@ -592,7 +653,7 @@
     /* force NUL term for printf */
     uname[UT_NAMESIZE] = '\0';
 
-    printf("%-*.*s%-9.8s", userlen + 1, userlen, uname, tty + 5);
+    printf("%-*.*s%-9.8s", userlen + 1, userlen, uname, tty);
     if (from)
         print_from(session, u, ip_addresses, fromlen);
 
@@ -620,7 +681,7 @@
     if (u && *u->ut_line == ':')
         /* idle unknown for xdm logins */
         printf(" ?xdm? ");
-    else if (tty[5])
+    else if (tty[0])
         print_time_ival7(idletime(tty), 0, stdout);
     else
         printf("       ");
@@ -789,7 +850,7 @@
         }
 #endif
     }
-    print_time_ival7(idletime(ttypath), 0, stdout);
+    print_time_ival7(idletime(ttyname), 0, stdout);
     /* jpcpu/pcpu */
     if (longform) {
         print_time_ival7(jcpu / hertz, (jcpu % hertz) * (100. / hertz), stdout);
@@ -854,12 +915,8 @@
 
     if (!procps_pids_sort(pids_info,
                 reap->stacks, total_procs,
-                PIDS_TICS_BEGAN, PIDS_SORT_ASCEND))
-        xerrx(EXIT_FAILURE, _("Unable to sort pids"));
-    if (!procps_pids_sort(pids_info,
-                reap->stacks, total_procs,
                 PIDS_TTY, PIDS_SORT_ASCEND))
-        xerrx(EXIT_FAILURE, _("Unable to sort pids"));
+        xerrx(EXIT_FAILURE, _("Unable to sort processes by TTY"));
 
     for (i=0; i < total_procs; i++) {
         /* Skip if:
@@ -1035,6 +1092,11 @@
             return(EXIT_FAILURE);
         }
 
+        if (!procps_pids_sort(info,
+                    pids_cache->stacks, pids_cache->counts->total,
+                    PIDS_TICS_BEGAN, PIDS_SORT_ASCEND))
+             xerrx(EXIT_FAILURE, _("Unable to sort processes by PID"));
+
 	if (header) {
 		/* print uptime and headers */
 		printf("%s\n", procps_uptime_sprint());