A missing securetty file is not an error.
[oweals/busybox.git] / procps / ps.c
1 /* vi: set sw=4 ts=4: */
2 /*
3  * Mini ps implementation(s) for busybox
4  *
5  * Copyright (C) 1999,2000 by Lineo, inc. and Erik Andersen  
6  * Copyright (C) 1999,2000,2001 by Erik Andersen <andersee@debian.org>
7  *
8  * This program is free software; you can redistribute it and/or modify it
9  * under the terms of the GNU General Public License as published by the Free
10  * Software Foundation; either version 2 of the License, or (at your option)
11  * any later version.
12  *
13  * This program is distributed in the hope that it will be useful, but WITHOUT
14  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16  * more details.
17  *
18  * You should have received a copy of the GNU General Public License along with
19  * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
20  * Place, Suite 330, Boston, MA 02111-1307 USA
21  */
22
23 /*
24  * This contains _two_ implementations of ps for Linux.  One uses the
25  * traditional /proc virtual filesystem, and the other use the devps kernel
26  * driver (written by Erik Andersen to avoid using /proc thereby saving 100k+).
27  */
28
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <unistd.h>
32 #include <dirent.h>
33 #include <errno.h>
34 #include <fcntl.h>
35 #include <ctype.h>
36 #include <string.h>
37 #include <termios.h>
38 #include <sys/ioctl.h>
39 #include "busybox.h"
40
41 static const int TERMINAL_WIDTH = 79;      /* not 80 in case terminal has linefold bug */
42
43
44
45 #if ! defined CONFIG_FEATURE_USE_DEVPS_PATCH
46
47 extern int ps_main(int argc, char **argv)
48 {
49         procps_status_t * p;
50         int i, len;
51 #ifdef CONFIG_FEATURE_AUTOWIDTH
52         struct winsize win = { 0, 0, 0, 0 };
53         int terminal_width = TERMINAL_WIDTH;
54 #else
55 #define terminal_width  TERMINAL_WIDTH
56 #endif
57
58
59 #ifdef CONFIG_FEATURE_AUTOWIDTH
60                 ioctl(fileno(stdout), TIOCGWINSZ, &win);
61                 if (win.ws_col > 0)
62                         terminal_width = win.ws_col - 1;
63 #endif
64
65         printf("  PID  Uid     VmSize Stat Command\n");
66         while ((p = procps_scan(1)) != 0) {
67                 char *namecmd = p->cmd;
68
69                 if(p->rss == 0)
70                         len = printf("%5d %-8s        %s ", p->pid, p->user, p->state);
71                 else
72                         len = printf("%5d %-8s %6ld %s ", p->pid, p->user, p->rss, p->state);
73                 i = terminal_width-len;
74
75                 if(namecmd != 0 && namecmd[0] != 0) {
76                         if(i < 0)
77                 i = 0;
78                         if(strlen(namecmd) > i)
79                                 namecmd[i] = 0;
80                         printf("%s\n", namecmd);
81                 } else {
82                         namecmd = p->short_cmd;
83                         if(i < 2)
84                                 i = 2;
85                         if(strlen(namecmd) > (i-2))
86                                 namecmd[i-2] = 0;
87                         printf("[%s]\n", namecmd);
88                 }
89                 free(p->cmd);
90         }
91         return EXIT_SUCCESS;
92 }
93
94
95 #else /* CONFIG_FEATURE_USE_DEVPS_PATCH */
96
97
98 /* The following is the second ps implementation --
99  * this one uses the nifty new devps kernel device.
100  */
101
102 #include <linux/devps.h> /* For Erik's nifty devps device driver */
103
104
105 extern int ps_main(int argc, char **argv)
106 {
107         char device[] = "/dev/ps";
108         int i, j, len, fd;
109         pid_t num_pids;
110         pid_t* pid_array = NULL;
111         struct pid_info info;
112         char uidName[9];
113 #ifdef CONFIG_FEATURE_AUTOWIDTH
114         struct winsize win = { 0, 0, 0, 0 };
115         int terminal_width = TERMINAL_WIDTH;
116 #else
117 #define terminal_width  TERMINAL_WIDTH
118 #endif
119
120         if (argc > 1 && **(argv + 1) == '-') 
121                 show_usage();
122
123         /* open device */ 
124         fd = open(device, O_RDONLY);
125         if (fd < 0) 
126                 perror_msg_and_die( "open failed for `%s'", device);
127
128         /* Find out how many processes there are */
129         if (ioctl (fd, DEVPS_GET_NUM_PIDS, &num_pids)<0) 
130                 perror_msg_and_die( "\nDEVPS_GET_PID_LIST");
131         
132         /* Allocate some memory -- grab a few extras just in case 
133          * some new processes start up while we wait. The kernel will
134          * just ignore any extras if we give it too many, and will trunc.
135          * the list if we give it too few.  */
136         pid_array = (pid_t*) xcalloc( num_pids+10, sizeof(pid_t));
137         pid_array[0] = num_pids+10;
138
139         /* Now grab the pid list */
140         if (ioctl (fd, DEVPS_GET_PID_LIST, pid_array)<0) 
141                 perror_msg_and_die("\nDEVPS_GET_PID_LIST");
142
143 #ifdef CONFIG_FEATURE_AUTOWIDTH
144                 ioctl(fileno(stdout), TIOCGWINSZ, &win);
145                 if (win.ws_col > 0)
146                         terminal_width = win.ws_col - 1;
147 #endif
148
149         /* Print up a ps listing */
150         printf("  PID  Uid     Stat Command\n");
151
152         for (i=1; i<pid_array[0] ; i++) {
153             info.pid = pid_array[i];
154
155             if (ioctl (fd, DEVPS_GET_PID_INFO, &info)<0)
156                         perror_msg_and_die("\nDEVPS_GET_PID_INFO");
157             
158                 /* Make some adjustments as needed */
159                 my_getpwuid(uidName, info.euid);
160
161                 if(p.vmsize == 0)
162                         len = printf("%5d %-8s        %c    ", p.pid, uidName, p.state);
163                 else
164                         len = printf("%5d %-8s %6d %c    ", p.pid, uidName, p.vmsize, p.state);
165                 if (strlen(info.command_line) > 1) {
166                         for( j=0; j<(sizeof(info.command_line)-1) && j < (terminal_width-len); j++) {
167                                 if (*(info.command_line+j) == '\0' && *(info.command_line+j+1) != '\0') {
168                                         *(info.command_line+j) = ' ';
169                                 }
170                         }
171                         *(info.command_line+j) = '\0';
172                         puts(info.command_line);
173                 } else {
174                         printf("[%s]\n", info.name);
175                 }
176         }
177
178         /* Free memory */
179         free( pid_array);
180
181         /* close device */
182         if (close (fd) != 0) 
183                 perror_msg_and_die("close failed for `%s'", device);
184  
185         exit (0);
186 }
187
188 #endif /* CONFIG_FEATURE_USE_DEVPS_PATCH */
189