procfs extensions and ps command

This commit is contained in:
Kevin Lange 2013-03-18 21:52:45 -07:00
parent ff429a7d07
commit 6f94ce2296
7 changed files with 313 additions and 16 deletions

View File

@ -1,8 +1,17 @@
#include <system.h>
#include <logging.h>
#include <fs.h>
#include <version.h>
#include <process.h>
#define PROCFS_STANDARD_ENTRIES 5
#define PROCFS_PROCDIR_ENTRIES 2
struct procfs_entry {
int id;
char * name;
read_type_t func;
};
static fs_node_t * procfs_generic_create(char * name, read_type_t read_func) {
fs_node_t * fnode = malloc(sizeof(fs_node_t));
@ -21,12 +30,113 @@ static fs_node_t * procfs_generic_create(char * name, read_type_t read_func) {
return fnode;
}
struct procfs_entry {
int id;
char * name;
read_type_t func;
uint32_t proc_cmdline_func(fs_node_t *node, uint32_t offset, uint32_t size, uint8_t *buffer) {
char buf[1024];
process_t * proc = process_from_pid(node->inode);
if (!proc) {
/* wat */
return 0;
}
buf[0] = '\0';
char * _buf = buf;
char ** args = proc->cmdline;
while (*args) {
strcpy(_buf, *args);
_buf += strlen(_buf);
if (*(args+1)) {
strcpy(_buf, "\036");
_buf += strlen(_buf);
}
args++;
}
size_t _bsize = strlen(buf);
if (offset > _bsize) return 0;
if (size > _bsize - offset) size = _bsize - offset;
memcpy(buffer, buf + offset, size);
return size;
}
uint32_t proc_status_func(fs_node_t *node, uint32_t offset, uint32_t size, uint8_t *buffer) {
char buf[2048];
process_t * proc = process_from_pid(node->inode);
if (!proc) {
/* wat */
return 0;
}
char state = process_is_ready(proc) ? 'R' : 'S';
sprintf(buf,
"Name:\t%s\n" /* name */
"State:\t%c\n" /* yeah, do this at some point */
"Tgid:\t%d\n" /* group ? group : pid */
"Pid:\t%d\n" /* pid */
"Uid:\t%d\n"
, proc->name, state, proc->group ? proc->group : proc->id, proc->id, proc->user);
size_t _bsize = strlen(buf);
if (offset > _bsize) return 0;
if (size > _bsize - offset) size = _bsize - offset;
memcpy(buffer, buf + offset, size);
return size;
}
static struct procfs_entry procdir_entries[] = {
{1, "cmdline", proc_cmdline_func},
{2, "status", proc_status_func},
};
static struct dirent * readdir_procfs_procdir(fs_node_t *node, uint32_t index) {
if (index < PROCFS_PROCDIR_ENTRIES) {
struct dirent * out = malloc(sizeof(struct dirent));
memset(out, 0x00, sizeof(struct dirent));
out->ino = procdir_entries[index].id;
strcpy(out->name, procdir_entries[index].name);
return out;
}
return NULL;
}
static fs_node_t * finddir_procfs_procdir(fs_node_t * node, char * name) {
if (!name) return NULL;
for (int i = 0; i < PROCFS_PROCDIR_ENTRIES; ++i) {
if (!strcmp(name, procdir_entries[i].name)) {
fs_node_t * out = procfs_generic_create(procdir_entries[i].name, procdir_entries[i].func);
out->inode = node->inode;
return out;
}
}
return NULL;
}
static fs_node_t * procfs_procdir_create(pid_t pid) {
fs_node_t * fnode = malloc(sizeof(fs_node_t));
memset(fnode, 0x00, sizeof(fs_node_t));
fnode->inode = pid;
sprintf(fnode->name, "%d", pid);
fnode->uid = 0;
fnode->gid = 0;
fnode->flags = FS_DIRECTORY;
fnode->read = NULL;
fnode->write = NULL;
fnode->open = NULL;
fnode->close = NULL;
fnode->readdir = readdir_procfs_procdir;
fnode->finddir = finddir_procfs_procdir;
return fnode;
}
uint32_t cpuinfo_func(fs_node_t *node, uint32_t offset, uint32_t size, uint8_t *buffer) {
return 0;
}
@ -94,13 +204,12 @@ uint32_t version_func(fs_node_t *node, uint32_t offset, uint32_t size, uint8_t *
return size;
}
static struct procfs_entry std_entries[] = {
{0, "cpuinfo", cpuinfo_func},
{1, "meminfo", meminfo_func},
{2, "uptime", uptime_func},
{3, "cmdline", cmdline_func},
{4, "version", version_func},
{-1, "cpuinfo", cpuinfo_func},
{-2, "meminfo", meminfo_func},
{-3, "uptime", uptime_func},
{-4, "cmdline", cmdline_func},
{-5, "version", version_func},
};
static struct dirent * readdir_procfs_root(fs_node_t *node, uint32_t index) {
@ -111,8 +220,31 @@ static struct dirent * readdir_procfs_root(fs_node_t *node, uint32_t index) {
strcpy(out->name, std_entries[index].name);
return out;
}
/* XXX process entries */
return NULL;
int i = index - PROCFS_STANDARD_ENTRIES + 1;
debug_print(WARNING, "%d %d %d", i, index, PROCFS_STANDARD_ENTRIES);
pid_t pid = 0;
foreach(lnode, process_list) {
i--;
if (i == 0) {
process_t * proc = (process_t *)lnode->value;
pid = proc->id;
break;
}
}
if (pid == 0) {
return NULL;
}
struct dirent * out = malloc(sizeof(struct dirent));
memset(out, 0x00, sizeof(struct dirent));
out->ino = pid;
sprintf(out->name, "%d", pid);
return out;
}
static fs_node_t * finddir_procfs_root(fs_node_t * node, char * name) {
@ -121,7 +253,13 @@ static fs_node_t * finddir_procfs_root(fs_node_t * node, char * name) {
if (name[0] >= '0' && name[0] <= '9') {
/* XXX process entries */
return NULL;
pid_t pid = atoi(name);
process_t * proc = process_from_pid(pid);
if (!proc) {
return NULL;
}
fs_node_t * out = procfs_procdir_create(pid);
return out;
}
for (int i = 0; i < PROCFS_STANDARD_ENTRIES; ++i) {

View File

@ -72,6 +72,8 @@ typedef struct process {
char * description; /* Process description */
user_t user; /* Effective user */
char ** cmdline;
pid_t group; /* Process thread group */
pid_t job; /* Process job group */
pid_t session; /* Session group */
@ -124,4 +126,6 @@ void sleep_until(process_t * process, unsigned long seconds, unsigned long subse
volatile process_t * current_process;
list_t * process_list;
#endif

View File

@ -55,6 +55,8 @@ exec(
current_process->name = malloc(strlen(path) + 1);
memcpy(current_process->name, path, strlen(path) + 1);
current_process->cmdline = argv;
/* Alright, we've read the binary, time to load the loadable sections */
/* Verify the magic */
if ( header->e_ident[0] != ELFMAG0 ||

View File

@ -12,6 +12,7 @@
#include <logging.h>
tree_t * process_tree; /* Parent->Children tree */
list_t * process_list; /* Flat storage */
list_t * process_queue; /* Ready queue */
list_t * reap_queue; /* Processes to reap */
list_t * sleep_queue;
@ -28,6 +29,7 @@ char * default_name = "[unnamed]";
*/
void initialize_process_tree() {
process_tree = tree_create();
process_list = list_create();
process_queue = list_create();
reap_queue = list_create();
sleep_queue = list_create();
@ -126,6 +128,7 @@ void delete_process(process_t * proc) {
/* Remove the entry. */
spin_lock(&tree_lock);
tree_remove(process_tree, entry);
list_delete(process_list, list_find(process_list, proc));
spin_unlock(&tree_lock);
free(proc);
@ -150,6 +153,7 @@ process_t * spawn_init() {
init->id = 0; /* Init is PID 1 */
init->group = 0;
init->name = strdup("init"); /* Um, duh. */
init->cmdline = NULL;
init->user = 0; /* UID 0 */
init->group = 0; /* Task group 0 */
init->status = 0; /* Run status */
@ -237,6 +241,7 @@ process_t * spawn_process(volatile process_t * parent) {
proc->group = proc->id; /* Set the GID */
proc->name = strdup(default_name); /* Use the default name */
proc->description = NULL; /* No description */
proc->cmdline = parent->cmdline;
/* Copy permissions */
proc->user = parent->user;
@ -303,6 +308,7 @@ process_t * spawn_process(volatile process_t * parent) {
proc->tree_entry = entry;
spin_lock(&tree_lock);
tree_node_insert_child_node(process_tree, parent->tree_entry, entry);
list_insert(process_list, (void *)proc);
spin_unlock(&tree_lock);
/* Return the new process */
@ -454,7 +460,7 @@ int sleep_on(list_t * queue) {
}
int process_is_ready(process_t * proc) {
if (proc->sched_node.prev != NULL || proc->sched_node.next != NULL) return 1;
if (proc->sched_node.prev != NULL || proc->sched_node.next != NULL || process_queue->head == &proc->sched_node) return 1;
return 0;
}

View File

@ -203,11 +203,12 @@ static int execve(const char * filename, char *const argv[], char *const envp[])
while (envp[envc]) { ++envc; }
}
debug_print(INFO, "Allocating space for arguments...");
char ** argv_ = malloc(sizeof(char *) * argc);
char ** argv_ = malloc(sizeof(char *) * (argc + 1));
for (int j = 0; j < argc; ++j) {
argv_[j] = malloc((strlen(argv[j]) + 1) * sizeof(char));
memcpy(argv_[j], argv[j], strlen(argv[j]) + 1);
}
argv_[argc] = 0;
char ** envp_;
if (envp && envc) {
envp_ = malloc(sizeof(char *) * (envc + 1));

View File

@ -237,7 +237,6 @@ int main (int argc, char * argv[]) {
qsort(ents_array, numents, sizeof(struct dirent *), entcmp);
if (long_mode) {
printf("printing listing\n");
for (int i = 0; i < numents; i++) {
print_entry_long(ents_array[i]->d_name, p);
}

147
userspace/core/ps.c Normal file
View File

@ -0,0 +1,147 @@
/*
* ps
*
* print a list of running processes
*/
#include <sys/stat.h>
#include <fcntl.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <syscall.h>
#include <unistd.h>
#include <dirent.h>
#include "lib/list.h"
#define LINE_LEN 4096
void print_username(int uid) {
FILE * passwd = fopen("/etc/passwd", "r");
char line[LINE_LEN];
while (fgets(line, LINE_LEN, passwd) != NULL) {
line[strlen(line)-1] = '\0';
char *p, *tokens[10], *last;
int i = 0;
for ((p = strtok_r(line, ":", &last)); p; (p = strtok_r(NULL, ":", &last)), i++) {
if (i < 511) tokens[i] = p;
}
tokens[i] = NULL;
if (atoi(tokens[2]) == uid) {
printf("%-8s", tokens[0]);
fclose(passwd);
return;
}
}
printf("%-8d", uid);
fclose(passwd);
}
void print_entry(struct dirent * dent) {
char tmp[256], buf[4096];
FILE * f;
int read = 1;
char line[LINE_LEN];
int pid, uid;
snprintf(tmp, 256, "/proc/%s/status", dent->d_name);
f = fopen(tmp, "r");
while (fgets(line, LINE_LEN, f) != NULL) {
if (strstr(line, "Pid:") == line) {
sscanf(line, "%s %d", &buf, &pid);
} else if (strstr(line, "Uid:") == line) {
sscanf(line, "%s %d", &buf, &uid);
}
}
fclose(f);
print_username(uid);
printf(" %5d ", pid);
snprintf(tmp, 256, "/proc/%s/cmdline", dent->d_name);
f = fopen(tmp, "r");
memset(buf, 0x00, 4096);
read = fread(buf, 1, 4096, f);
fclose(f);
buf[read] = '\0';
for (int i = 0; i < read; ++i) {
if (buf[i] == '\036') {
buf[i] = ' ';
}
}
printf("%s\n", buf);
}
void show_usage(int argc, char * argv[]) {
printf(
"ps - list running processes\n"
"\n"
"usage: %s [-A] [format]\n"
"\n"
" -A \033[3mignored\033[0m\n"
" -? \033[3mshow this help text\033[0m\n"
"\n", argv[0]);
}
int main (int argc, char * argv[]) {
/* Parse arguments */
int show_all = 0;
if (argc > 1) {
int index, c;
while ((c = getopt(argc, argv, "A?")) != -1) {
switch (c) {
case 'A':
show_all = 1;
break;
case '?':
show_usage(argc, argv);
return 0;
}
}
}
/* Open the directory */
DIR * dirp = opendir("/proc");
/* Read the entries in the directory */
list_t * ents_list = list_create();
struct dirent * ent = readdir(dirp);
while (ent != NULL) {
if (ent->d_name[0] >= '0' && ent->d_name[0] <= '9') {
struct dirent * entcpy = malloc(sizeof(struct dirent));
memcpy(entcpy, ent, sizeof(struct dirent));
list_insert(ents_list, (void *)entcpy);
}
ent = readdir(dirp);
}
closedir(dirp);
foreach(entry, ents_list) {
print_entry(entry->value);
}
return 0;
}
/*
* vim: tabstop=4
* vim: shiftwidth=4
* vim: noexpandtab
*/