vfs: check userland buffers before reading them.
[haiku.git] / src / bin / ps.c
blob7d35c95c03c78f58629b94a8afe2ccef67191e05
1 /*
2 * Copyright 2002-2008, Haiku Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
5 * Authors:
6 * Francois Revol (mmu_man)
7 * Salvatore Benedetto <salvatore.benedetto@gmail.com>
8 * Bjoern Herzig (xRaich[o]2x)
9 * Thomas Schmidt <thomas.compix@googlemail.com>
11 #include <stdio.h>
12 #include <unistd.h>
13 #include <string.h>
15 #include <OS.h>
18 enum {
19 Team = 0,
20 Id,
21 Threads,
22 Gid,
23 Uid
26 struct ColumnIndo {
27 const char* name;
28 const char* header;
29 const char* format;
30 } Infos[] = {
31 { "Team", "%-50s", "%-50s" },
32 { "Id", "%5s", "%5" B_PRId32 },
33 { "Threads", "#%7s", "%8" B_PRId32 },
34 { "Gid", "%4s", "%4d" },
35 { "Uid", "%4s", "%4d" }
38 #define maxColumns 10
39 int Columns[maxColumns] = { Team, Id, Threads, Gid, Uid, 0 };
40 int ColumnsCount = 5;
42 const char* sStates[] = {"run", "rdy", "msg", "zzz", "sus", "wait"};
44 static void printTeamThreads(team_info* teamInfo, bool printSemaphoreInfo);
45 static void printTeamInfo(team_info* teamInfo, bool printHeader);
48 static void
49 printTeamInfo(team_info* teamInfo, bool printHeader)
51 int i = 0;
52 if (printHeader) {
53 for (i = 0; i < ColumnsCount; i++) {
54 printf(Infos[Columns[i]].header, Infos[Columns[i]].name);
55 putchar(' ');
57 puts("");
61 for (i = 0; i < ColumnsCount; i++) {
62 switch (Columns[i]) {
63 case Team:
64 printf(Infos[Team].format, teamInfo->args);
65 break;
66 case Id:
67 printf(Infos[Id].format, teamInfo->team);
68 break;
69 case Threads:
70 printf(Infos[Threads].format, teamInfo->thread_count);
71 break;
72 case Gid:
73 printf(Infos[Gid].format, teamInfo->gid);
74 break;
75 case Uid:
76 printf(Infos[Uid].format, teamInfo->uid);
77 break;
79 putchar(' ');
81 puts("");
85 static void
86 printTeamThreads(team_info* teamInfo, bool printSemaphoreInfo)
88 const char* threadState;
89 int32 threadCookie = 0;
90 sem_info semaphoreInfo;
91 thread_info threadInfo;
93 // Print all info about its threads too
94 while (get_next_thread_info(teamInfo->team, &threadCookie, &threadInfo)
95 >= B_OK) {
96 if (threadInfo.state < B_THREAD_RUNNING
97 || threadInfo.state > B_THREAD_WAITING)
98 // This should never happen
99 threadState = "???";
100 else
101 threadState = sStates[threadInfo.state - 1];
103 printf("%-37s %5" B_PRId32 " %8s %4" B_PRId32 " %8" B_PRIu64 " %8"
104 B_PRId64 " ", threadInfo.name, threadInfo.thread, threadState,
105 threadInfo.priority, (threadInfo.user_time / 1000),
106 (threadInfo.kernel_time / 1000));
108 if (printSemaphoreInfo) {
109 if (threadInfo.state == B_THREAD_WAITING && threadInfo.sem != -1) {
110 status_t status = get_sem_info(threadInfo.sem, &semaphoreInfo);
111 if (status == B_OK) {
112 printf("%s(%" B_PRId32 ")\n", semaphoreInfo.name,
113 semaphoreInfo.sem);
114 } else {
115 printf("%s(%" B_PRId32 ")\n", strerror(status),
116 threadInfo.sem);
118 } else
119 puts("");
120 } else
121 puts("");
127 main(int argc, char** argv)
129 team_info teamInfo;
130 int32 teamCookie = 0;
131 system_info systemInfo;
132 bool printSystemInfo = false;
133 bool printThreads = false;
134 bool printHeader = true;
135 bool printSemaphoreInfo = false;
136 bool customizeColumns = false;
137 // match this in team name
138 char* string_to_match;
140 int c;
142 while ((c = getopt(argc, argv, "-ihaso:")) != EOF) {
143 switch (c) {
144 case 'i':
145 printSystemInfo = true;
146 break;
147 case 'h':
148 printf( "usage: ps [-hais] [-o columns list] [team]\n"
149 "-h : show help\n"
150 "-i : show system info\n"
151 "-s : show semaphore info\n"
152 "-o : display team info associated with the list\n"
153 "-a : show threads too (by default only teams are "
154 "displayed)\n");
155 return 0;
156 break;
157 case 'a':
158 printThreads = true;
159 break;
160 case 's':
161 printSemaphoreInfo = true;
162 break;
163 case 'o':
164 if (!customizeColumns)
165 ColumnsCount = 0;
166 customizeColumns = true;
167 /* fallthrough */
168 case 1:
170 size_t i = 0;
171 if (c == 1 && !customizeColumns)
172 break;
173 for (i = 0; i < sizeof(Infos) / sizeof(Infos[0]); i++)
174 if (strcmp(optarg, Infos[i].name) == 0
175 && ColumnsCount < maxColumns) {
176 Columns[ColumnsCount++] = i;
177 continue;
179 break;
184 // TODO: parse command line
185 // Possible command line options:
186 // -t pstree like output
188 if (argc == 2 && (printSystemInfo || printThreads))
189 string_to_match = NULL;
190 else
191 string_to_match = (argc >= 2 && !customizeColumns)
192 ? argv[argc - 1] : NULL;
194 if (!string_to_match) {
195 while (get_next_team_info(&teamCookie, &teamInfo) >= B_OK) {
196 printTeamInfo(&teamInfo, printHeader);
197 printHeader = false;
198 if (printThreads) {
199 printf("\n%-37s %5s %8s %4s %8s %8s\n", "Thread", "Id", \
200 "State", "Prio", "UTime", "KTime");
201 printTeamThreads(&teamInfo, printSemaphoreInfo);
202 printf("----------------------------------------------" \
203 "-----------------------------\n");
204 printHeader = true;
207 } else {
208 while (get_next_team_info(&teamCookie, &teamInfo) >= B_OK) {
209 char* p = teamInfo.args;
210 if ((p = strchr(p, ' ')))
211 *p = '\0'; /* remove arguments, keep only argv[0] */
212 p = strrchr(teamInfo.args, '/'); /* forget the path */
213 if (p == NULL)
214 p = teamInfo.args;
215 if (strstr(p, string_to_match) == NULL)
216 continue;
217 printTeamInfo(&teamInfo, true);
218 printf("\n%-37s %5s %8s %4s %8s %8s\n", "Thread", "Id", "State", \
219 "Prio", "UTime", "KTime");
220 printTeamThreads(&teamInfo, printSemaphoreInfo);
224 if (printSystemInfo) {
225 // system stats
226 get_system_info(&systemInfo);
227 printf("\nSystem Info\n");
228 printf("%" B_PRIu64 "k (%" B_PRIu64 " bytes) total memory\n",
229 (systemInfo.max_pages * B_PAGE_SIZE / 1024),
230 (systemInfo.max_pages * B_PAGE_SIZE));
231 printf("%" B_PRIu64 "k (%" B_PRIu64 " bytes) currently committed\n",
232 (systemInfo.used_pages * B_PAGE_SIZE / 1024),
233 (systemInfo.used_pages * B_PAGE_SIZE));
234 printf("%" B_PRIu64 "k (%" B_PRIu64 " bytes) currently available\n",
235 (systemInfo.max_pages - systemInfo.used_pages) * B_PAGE_SIZE / 1024,
236 (systemInfo.max_pages - systemInfo.used_pages) * B_PAGE_SIZE);
237 printf("%2.1f%% memory utilisation\n",
238 (float)100 * systemInfo.used_pages / systemInfo.max_pages);
240 return 0;