Fixed up copyright notices and such
[platform/upstream/busybox.git] / procps / ps.c
1 /*
2  * Mini ps implementation for busybox
3  *
4  *
5  * Copyright (C) 1999 by Lineo, inc.
6  * Written by Erik Andersen <andersen@lineo.com>, <andersee@debian.org>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21  *
22  */
23
24 #include "internal.h"
25 #include <unistd.h>
26 #include <dirent.h>
27 #include <stdio.h>
28 #include <fcntl.h>
29 #include <ctype.h>
30
31
32 typedef struct proc_s {
33     char
34         cmd[16];        /* basename of executable file in call to exec(2) */
35     int
36         ruid, rgid,     /* real only (sorry) */
37         pid,            /* process id */
38         ppid;           /* pid of parent process */
39     char
40         state;          /* single-char code for process state (S=sleeping) */
41 } proc_t;
42
43
44
45 static int file2str(char *filename, char *ret, int cap) 
46 {
47     int fd, num_read;
48
49     if ( (fd       = open(filename, O_RDONLY, 0)) == -1 ) return -1;
50     if ( (num_read = read(fd, ret, cap - 1))      <= 0 ) return -1;
51     ret[num_read] = 0;
52     close(fd);
53     return num_read;
54 }
55
56
57 static void parse_proc_status(char* S, proc_t* P) 
58 {
59     char* tmp;
60     memset(P->cmd, 0, sizeof P->cmd);
61     sscanf (S, "Name:\t%15c", P->cmd);
62     tmp = strchr(P->cmd,'\n');
63     if (tmp)
64         *tmp='\0';
65     tmp = strstr (S,"State");
66     sscanf (tmp, "State:\t%c", &P->state);
67
68     tmp = strstr (S,"Pid:");
69     if(tmp) sscanf (tmp,
70         "Pid:\t%d\n"
71         "PPid:\t%d\n",
72         &P->pid,
73         &P->ppid
74     );
75     else fprintf(stderr, "Internal error!\n");
76
77     /* For busybox, ignoring effecting, saved, etc */
78     tmp = strstr (S,"Uid:");
79     if(tmp) sscanf (tmp,
80         "Uid:\t%d", &P->ruid);
81     else fprintf(stderr, "Internal error!\n");
82
83     tmp = strstr (S,"Gid:");
84     if(tmp) sscanf (tmp,
85         "Gid:\t%d", &P->rgid);
86     else fprintf(stderr, "Internal error!\n");
87
88 }
89
90
91 extern int ps_main(int argc, char **argv)
92 {
93     proc_t p;
94     DIR *dir;
95     FILE *file;
96     struct dirent *entry;
97     char path[32], sbuf[512];
98     char uidName[10]="";
99     char groupName[10]="";
100     int i, c;
101
102     if ( argc>1 && **(argv+1) == '-' ) {
103         usage ("ps - report process status\nThis version of ps accepts no options.\n");
104     }
105     
106     dir = opendir("/proc");
107     if (!dir) {
108         perror("Can't open /proc");
109         exit(FALSE);
110     }
111
112     fprintf(stdout, "%5s  %-8s %-3s %5s %s\n", "PID", "Uid", "Gid", "State", "Command");
113     while ((entry = readdir(dir)) != NULL) {
114         uidName[0]='\0';
115         groupName[0]='\0';
116                 
117         if (! isdigit(*entry->d_name))
118             continue;
119         sprintf(path, "/proc/%s/status", entry->d_name);
120         if ((file2str(path, sbuf, sizeof sbuf)) != -1 ) {
121             parse_proc_status(sbuf, &p);
122         }
123
124         /* Make some adjustments as needed */
125         my_getpwuid( uidName, p.ruid);
126         my_getgrgid( groupName, p.rgid);
127         if (*uidName == '\0')
128             sprintf( uidName, "%d", p.ruid);
129         if (*groupName == '\0')
130             sprintf( groupName, "%d", p.rgid);
131
132         fprintf(stdout, "%5d %-8s %-8s %c ", p.pid, uidName, groupName, p.state);
133         sprintf(path, "/proc/%s/cmdline", entry->d_name);
134         file = fopen(path, "r");
135         if (file == NULL) {
136             perror(path);
137             exit(FALSE);
138         }
139         i=0;
140         while (((c = getc(file)) != EOF) && (i < 53)) {
141             i++;
142             if (c == '\0')
143                 c = ' ';
144             putc(c, stdout);
145         }
146         if (i==0)
147             fprintf(stdout, "%s", p.cmd);
148         fprintf(stdout, "\n");
149     }
150     closedir(dir);
151     exit(TRUE);
152 }