add ps, pstree, fix terminal unicode
This commit is contained in:
parent
61a3ab6017
commit
c74a28dfca
8
Makefile
8
Makefile
@ -1,4 +1,4 @@
|
||||
APPS=init hello sh ls terminal uname compositor drawlines background session kdebug cat yutani-test sysinfo hostname yutani-query env mount date echo nyancat kill
|
||||
APPS=init hello sh ls terminal uname compositor drawlines background session kdebug cat yutani-test sysinfo hostname yutani-query env mount date echo nyancat kill ps pstree
|
||||
|
||||
CC=i686-pc-toaru-gcc
|
||||
AR=i686-pc-toaru-ar
|
||||
@ -110,6 +110,12 @@ base/bin/ls: ls.c base/lib/libnihc.so base/lib/libtoaru_list.so
|
||||
base/bin/nyancat: nyancat/nyancat.c base/lib/libnihc.so
|
||||
$(CC) $(CFLAGS) -o $@ $< $(LIBS)
|
||||
|
||||
base/bin/ps: ps.c base/lib/libnihc.so base/lib/libtoaru_list.so
|
||||
$(CC) $(CFLAGS) -o $@ $< -ltoaru_list $(LIBS)
|
||||
|
||||
base/bin/pstree: pstree.c base/lib/libnihc.so base/lib/libtoaru_tree.so base/lib/libtoaru_list.so
|
||||
$(CC) $(CFLAGS) -o $@ $< -ltoaru_tree -ltoaru_list $(LIBS)
|
||||
|
||||
base/bin/%: %.c base/lib/libnihc.so | dirs
|
||||
$(CC) $(CFLAGS) -o $@ $< $(LIBS)
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
#include <string.h>
|
||||
#include <va_list.h>
|
||||
|
||||
static void print_dec(unsigned int value, unsigned int width, char * buf, int * ptr, int fill_zero) {
|
||||
static void print_dec(unsigned int value, unsigned int width, char * buf, int * ptr, int fill_zero, int align_right) {
|
||||
unsigned int n_width = 1;
|
||||
unsigned int i = 9;
|
||||
while (value > i && i < UINT32_MAX) {
|
||||
@ -12,21 +12,39 @@ static void print_dec(unsigned int value, unsigned int width, char * buf, int *
|
||||
}
|
||||
|
||||
int printed = 0;
|
||||
while (n_width + printed < width) {
|
||||
buf[*ptr] = fill_zero ? '0' : ' ';
|
||||
*ptr += 1;
|
||||
printed += 1;
|
||||
}
|
||||
if (align_right) {
|
||||
while (n_width + printed < width) {
|
||||
buf[*ptr] = fill_zero ? '0' : ' ';
|
||||
*ptr += 1;
|
||||
printed += 1;
|
||||
}
|
||||
|
||||
i = n_width;
|
||||
while (i > 0) {
|
||||
unsigned int n = value / 10;
|
||||
int r = value % 10;
|
||||
buf[*ptr + i - 1] = r + '0';
|
||||
i--;
|
||||
value = n;
|
||||
i = n_width;
|
||||
while (i > 0) {
|
||||
unsigned int n = value / 10;
|
||||
int r = value % 10;
|
||||
buf[*ptr + i - 1] = r + '0';
|
||||
i--;
|
||||
value = n;
|
||||
}
|
||||
*ptr += n_width;
|
||||
} else {
|
||||
i = n_width;
|
||||
while (i > 0) {
|
||||
unsigned int n = value / 10;
|
||||
int r = value % 10;
|
||||
buf[*ptr + i - 1] = r + '0';
|
||||
i--;
|
||||
value = n;
|
||||
printed++;
|
||||
}
|
||||
*ptr += n_width;
|
||||
while (n_width + printed < width) {
|
||||
buf[*ptr] = fill_zero ? '0' : ' ';
|
||||
*ptr += 1;
|
||||
printed += 1;
|
||||
}
|
||||
}
|
||||
*ptr += n_width;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -127,7 +145,7 @@ size_t vasprintf(char * buf, const char * fmt, va_list args) {
|
||||
*b++ = '-';
|
||||
val = -val;
|
||||
}
|
||||
print_dec(val, arg_width, buf, &i, fill_zero);
|
||||
print_dec(val, arg_width, buf, &i, fill_zero, align);
|
||||
}
|
||||
b = buf + i;
|
||||
break;
|
||||
|
@ -142,7 +142,7 @@ _try_again:
|
||||
if (r < 0) {
|
||||
return EOF;
|
||||
} else if (r == 0) {
|
||||
goto _try_again;
|
||||
return EOF;
|
||||
}
|
||||
return buf[0];
|
||||
}
|
||||
|
178
ps.c
Normal file
178
ps.c
Normal file
@ -0,0 +1,178 @@
|
||||
/* vim: tabstop=4 shiftwidth=4 noexpandtab
|
||||
* This file is part of ToaruOS and is released under the terms
|
||||
* of the NCSA / University of Illinois License - see LICENSE.md
|
||||
* Copyright (C) 2013 Kevin Lange
|
||||
*
|
||||
* 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 <pwd.h>
|
||||
|
||||
#include "lib/list.h"
|
||||
|
||||
#define LINE_LEN 4096
|
||||
|
||||
static int show_all = 0;
|
||||
|
||||
void print_username(int uid) {
|
||||
struct passwd * p = getpwuid(uid);
|
||||
|
||||
if (p) {
|
||||
printf("%-8s", p->pw_name);
|
||||
} else {
|
||||
printf("%-8d", uid);
|
||||
}
|
||||
|
||||
endpwent();
|
||||
}
|
||||
|
||||
void print_entry(struct dirent * dent) {
|
||||
char tmp[256], buf[4096];
|
||||
FILE * f;
|
||||
int read = 1;
|
||||
char line[LINE_LEN];
|
||||
|
||||
int pid, uid, tgid;
|
||||
char name[100];
|
||||
|
||||
sprintf(tmp, "/proc/%s/status", dent->d_name);
|
||||
f = fopen(tmp, "r");
|
||||
|
||||
if (!f) {
|
||||
return;
|
||||
}
|
||||
|
||||
line[0] = 0;
|
||||
|
||||
while (fgets(line, LINE_LEN, f) != NULL) {
|
||||
char * n = strstr(line,"\n");
|
||||
if (n) { *n = '\0'; }
|
||||
char * tab = strstr(line,"\t");
|
||||
if (tab) {
|
||||
*tab = '\0';
|
||||
tab++;
|
||||
}
|
||||
if (strstr(line, "Pid:") == line) {
|
||||
pid = atoi(tab);
|
||||
} else if (strstr(line, "Uid:") == line) {
|
||||
uid = atoi(tab);
|
||||
} else if (strstr(line, "Tgid:") == line) {
|
||||
tgid = atoi(tab);
|
||||
} else if (strstr(line, "Name:") == line) {
|
||||
strcpy(name, tab);
|
||||
}
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
|
||||
if ((tgid != pid) && !show_all) {
|
||||
/* Skip threads */
|
||||
return;
|
||||
}
|
||||
|
||||
print_username(uid);
|
||||
if (show_all) {
|
||||
printf("%5d.%-5d", tgid, pid);
|
||||
} else {
|
||||
printf(" %5d", pid);
|
||||
}
|
||||
|
||||
printf(" ");
|
||||
|
||||
sprintf(tmp, "/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] = ' ';
|
||||
}
|
||||
}
|
||||
|
||||
if (tgid != pid) {
|
||||
printf("{%s}\n", buf);
|
||||
} else {
|
||||
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 */
|
||||
|
||||
if (argc > 1) {
|
||||
for (int i = 1; i < argc; ++i) {
|
||||
if (argv[i][0] == '-') {
|
||||
char *c = &argv[i][1];
|
||||
while (*c) {
|
||||
switch (*c) {
|
||||
case 'A':
|
||||
show_all = 1;
|
||||
break;
|
||||
case '?':
|
||||
show_usage(argc, argv);
|
||||
return 0;
|
||||
}
|
||||
c++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 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
|
||||
*/
|
191
pstree.c
Normal file
191
pstree.c
Normal file
@ -0,0 +1,191 @@
|
||||
/* This file is part of ToaruOS and is released under the terms
|
||||
* of the NCSA / University of Illinois License - see LICENSE.md
|
||||
* Copyright (C) 2014 Kevin Lange
|
||||
*/
|
||||
/*
|
||||
* pstree
|
||||
*
|
||||
* Prints running processes as a tree of
|
||||
*/
|
||||
|
||||
|
||||
#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"
|
||||
#include "lib/tree.h"
|
||||
|
||||
typedef struct process {
|
||||
int pid;
|
||||
int ppid;
|
||||
int tgid;
|
||||
char name[100];
|
||||
char path[200];
|
||||
} p_t;
|
||||
|
||||
#define LINE_LEN 4096
|
||||
|
||||
p_t * build_entry(struct dirent * dent) {
|
||||
char tmp[256], buf[4096];
|
||||
FILE * f;
|
||||
int read = 1;
|
||||
char line[LINE_LEN];
|
||||
|
||||
int pid, uid;
|
||||
|
||||
sprintf(tmp, "/proc/%s/status", dent->d_name);
|
||||
f = fopen(tmp, "r");
|
||||
|
||||
p_t * proc = malloc(sizeof(p_t));
|
||||
|
||||
while (fgets(line, LINE_LEN, f) != NULL) {
|
||||
char * n = strstr(line,"\n");
|
||||
if (n) { *n = '\0'; }
|
||||
char * tab = strstr(line,"\t");
|
||||
if (tab) {
|
||||
*tab = '\0';
|
||||
tab++;
|
||||
}
|
||||
if (strstr(line, "Pid:") == line) {
|
||||
proc->pid = atoi(tab);
|
||||
} else if (strstr(line, "PPid:") == line) {
|
||||
proc->ppid = atoi(tab);
|
||||
} else if (strstr(line, "Tgid:") == line) {
|
||||
proc->tgid = atoi(tab);
|
||||
} else if (strstr(line, "Name:") == line) {
|
||||
strcpy(proc->name, tab);
|
||||
} else if (strstr(line, "Path:") == line) {
|
||||
strcpy(proc->path, tab);
|
||||
}
|
||||
}
|
||||
|
||||
if (strstr(proc->name,"python") == proc->name) {
|
||||
char * name = proc->path + strlen(proc->path) - 1;
|
||||
|
||||
while (1) {
|
||||
if (*name == '/') {
|
||||
name++;
|
||||
break;
|
||||
}
|
||||
if (name == proc->name) break;
|
||||
name--;
|
||||
}
|
||||
|
||||
memcpy(proc->name, name, strlen(name)+1);
|
||||
}
|
||||
|
||||
if (proc->tgid != proc->pid) {
|
||||
char tmp[100] = {0};
|
||||
sprintf(tmp, "{%s}", proc->name);
|
||||
memcpy(proc->name, tmp, strlen(tmp)+1);
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
|
||||
return proc;
|
||||
}
|
||||
|
||||
uint8_t find_pid(void * proc_v, void * pid_v) {
|
||||
p_t * p = proc_v;
|
||||
pid_t i = (pid_t)pid_v;
|
||||
|
||||
return (uint8_t)(p->pid == i);
|
||||
}
|
||||
|
||||
void print_process_tree_node(tree_node_t * node, size_t depth, int indented, int more, char lines[]) {
|
||||
|
||||
p_t * proc = node->value;
|
||||
|
||||
for (int i = 0; i < strlen(proc->name)+3; ++i) {
|
||||
lines[depth+i] = 0;
|
||||
}
|
||||
|
||||
if (!indented && depth) {
|
||||
if (more) {
|
||||
printf("─┬─");
|
||||
lines[depth+1] = 1;
|
||||
} else {
|
||||
printf("───");
|
||||
}
|
||||
depth += 3;
|
||||
} else if (depth) {
|
||||
for (int i = 0; i < depth; ++i) {
|
||||
if (lines[i]) {
|
||||
printf("│");
|
||||
} else {
|
||||
printf(" ");
|
||||
}
|
||||
}
|
||||
if (more) {
|
||||
printf(" ├─");
|
||||
lines[depth+1] = 1;
|
||||
} else {
|
||||
printf(" └─");
|
||||
}
|
||||
depth += 3;
|
||||
}
|
||||
|
||||
printf(proc->name);
|
||||
|
||||
if (!node->children->length) {
|
||||
printf("\n");
|
||||
} else {
|
||||
depth += strlen(proc->name);
|
||||
|
||||
int t = 0;
|
||||
foreach(child, node->children) {
|
||||
/* Recursively print the children */
|
||||
print_process_tree_node(child->value, depth, !!(t++), ((t+1)!=node->children->length), lines);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < strlen(proc->name)+3; ++i) {
|
||||
lines[depth+i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int main (int argc, char * argv[]) {
|
||||
|
||||
/* Open the directory */
|
||||
DIR * dirp = opendir("/proc");
|
||||
|
||||
/* Read the entries in the directory */
|
||||
tree_t * procs = tree_create();
|
||||
|
||||
struct dirent * ent = readdir(dirp);
|
||||
while (ent != NULL) {
|
||||
if (ent->d_name[0] >= '0' && ent->d_name[0] <= '9') {
|
||||
p_t * proc = build_entry(ent);
|
||||
|
||||
if (proc->ppid == 0 && proc->pid == 1) {
|
||||
tree_set_root(procs, proc);
|
||||
} else {
|
||||
tree_node_t * parent = tree_find(procs,(void *)proc->ppid,find_pid);
|
||||
if (parent) {
|
||||
tree_node_insert_child(procs, parent, proc);
|
||||
}
|
||||
}
|
||||
}
|
||||
ent = readdir(dirp);
|
||||
}
|
||||
closedir(dirp);
|
||||
|
||||
char lines[500] = {0};
|
||||
print_process_tree_node(procs->root, 0, 0, 0, lines);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* vim: tabstop=4
|
||||
* vim: shiftwidth=4
|
||||
* vim: noexpandtab
|
||||
*/
|
||||
|
168
terminal.c
168
terminal.c
@ -239,6 +239,172 @@ void draw_semi_block(int c, int x, int y, uint32_t fg, uint32_t bg) {
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t ununicode(uint32_t c) {
|
||||
switch (c) {
|
||||
case L'☺': return 1;
|
||||
case L'☻': return 2;
|
||||
case L'♥': return 3;
|
||||
case L'♦': return 4;
|
||||
case L'♣': return 5;
|
||||
case L'♠': return 6;
|
||||
case L'•': return 7;
|
||||
case L'◘': return 8;
|
||||
case L'○': return 9;
|
||||
case L'◙': return 10;
|
||||
case L'♂': return 11;
|
||||
case L'♀': return 12;
|
||||
case L'♪': return 13;
|
||||
case L'♫': return 14;
|
||||
case L'☼': return 15;
|
||||
case L'►': return 16;
|
||||
case L'◄': return 17;
|
||||
case L'↕': return 18;
|
||||
case L'‼': return 19;
|
||||
case L'¶': return 20;
|
||||
case L'§': return 21;
|
||||
case L'▬': return 22;
|
||||
case L'↨': return 23;
|
||||
case L'↑': return 24;
|
||||
case L'↓': return 25;
|
||||
case L'→': return 26;
|
||||
case L'←': return 27;
|
||||
case L'∟': return 28;
|
||||
case L'↔': return 29;
|
||||
case L'▲': return 30;
|
||||
case L'▼': return 31;
|
||||
/* ASCII text */
|
||||
case L'⌂': return 127;
|
||||
case L'Ç': return 128;
|
||||
case L'ü': return 129;
|
||||
case L'é': return 130;
|
||||
case L'â': return 131;
|
||||
case L'ä': return 132;
|
||||
case L'à': return 133;
|
||||
case L'å': return 134;
|
||||
case L'ç': return 135;
|
||||
case L'ê': return 136;
|
||||
case L'ë': return 137;
|
||||
case L'è': return 138;
|
||||
case L'ï': return 139;
|
||||
case L'î': return 140;
|
||||
case L'ì': return 141;
|
||||
case L'Ä': return 142;
|
||||
case L'Å': return 143;
|
||||
case L'É': return 144;
|
||||
case L'æ': return 145;
|
||||
case L'Æ': return 146;
|
||||
case L'ô': return 147;
|
||||
case L'ö': return 148;
|
||||
case L'ò': return 149;
|
||||
case L'û': return 150;
|
||||
case L'ù': return 151;
|
||||
case L'ÿ': return 152;
|
||||
case L'Ö': return 153;
|
||||
case L'Ü': return 154;
|
||||
case L'¢': return 155;
|
||||
case L'£': return 156;
|
||||
case L'¥': return 157;
|
||||
case L'₧': return 158;
|
||||
case L'ƒ': return 159;
|
||||
case L'á': return 160;
|
||||
case L'í': return 161;
|
||||
case L'ó': return 162;
|
||||
case L'ú': return 163;
|
||||
case L'ñ': return 164;
|
||||
case L'Ñ': return 165;
|
||||
case L'ª': return 166;
|
||||
case L'º': return 167;
|
||||
case L'¿': return 168;
|
||||
case L'⌐': return 169;
|
||||
case L'¬': return 170;
|
||||
case L'½': return 171;
|
||||
case L'¼': return 172;
|
||||
case L'¡': return 173;
|
||||
case L'«': return 174;
|
||||
case L'»': return 175;
|
||||
case L'░': return 176;
|
||||
case L'▒': return 177;
|
||||
case L'▓': return 178;
|
||||
case L'│': return 179;
|
||||
case L'┤': return 180;
|
||||
case L'╡': return 181;
|
||||
case L'╢': return 182;
|
||||
case L'╖': return 183;
|
||||
case L'╕': return 184;
|
||||
case L'╣': return 185;
|
||||
case L'║': return 186;
|
||||
case L'╗': return 187;
|
||||
case L'╝': return 188;
|
||||
case L'╜': return 189;
|
||||
case L'╛': return 190;
|
||||
case L'┐': return 191;
|
||||
case L'└': return 192;
|
||||
case L'┴': return 193;
|
||||
case L'┬': return 194;
|
||||
case L'├': return 195;
|
||||
case L'─': return 196;
|
||||
case L'┼': return 197;
|
||||
case L'╞': return 198;
|
||||
case L'╟': return 199;
|
||||
case L'╚': return 200;
|
||||
case L'╔': return 201;
|
||||
case L'╩': return 202;
|
||||
case L'╦': return 203;
|
||||
case L'╠': return 204;
|
||||
case L'═': return 205;
|
||||
case L'╬': return 206;
|
||||
case L'╧': return 207;
|
||||
case L'╨': return 208;
|
||||
case L'╤': return 209;
|
||||
case L'╥': return 210;
|
||||
case L'╙': return 211;
|
||||
case L'╘': return 212;
|
||||
case L'╒': return 213;
|
||||
case L'╓': return 214;
|
||||
case L'╫': return 215;
|
||||
case L'╪': return 216;
|
||||
case L'┘': return 217;
|
||||
case L'┌': return 218;
|
||||
case L'█': return 219;
|
||||
case L'▄': return 220;
|
||||
case L'▌': return 221;
|
||||
case L'▐': return 222;
|
||||
case L'▀': return 223;
|
||||
case L'α': return 224;
|
||||
case L'ß': return 225;
|
||||
case L'Γ': return 226;
|
||||
case L'π': return 227;
|
||||
case L'Σ': return 228;
|
||||
case L'σ': return 229;
|
||||
case L'µ': return 230;
|
||||
case L'τ': return 231;
|
||||
case L'Φ': return 232;
|
||||
case L'Θ': return 233;
|
||||
case L'Ω': return 234;
|
||||
case L'δ': return 235;
|
||||
case L'∞': return 236;
|
||||
case L'φ': return 237;
|
||||
case L'ε': return 238;
|
||||
case L'∩': return 239;
|
||||
case L'≡': return 240;
|
||||
case L'±': return 241;
|
||||
case L'≥': return 242;
|
||||
case L'≤': return 243;
|
||||
case L'⌠': return 244;
|
||||
case L'⌡': return 245;
|
||||
case L'÷': return 246;
|
||||
case L'≈': return 247;
|
||||
case L'°': return 248;
|
||||
case L'∙': return 249;
|
||||
case L'·': return 250;
|
||||
case L'√': return 251;
|
||||
case L'ⁿ': return 252;
|
||||
case L'²': return 253;
|
||||
case L'■': return 254;
|
||||
}
|
||||
return 4;
|
||||
}
|
||||
|
||||
void
|
||||
term_write_char(
|
||||
uint32_t val,
|
||||
@ -346,7 +512,7 @@ term_write_char(
|
||||
goto _extra_stuff;
|
||||
}
|
||||
if (val > 128) {
|
||||
val = 4;
|
||||
val = ununicode(val);
|
||||
}
|
||||
#ifdef number_font
|
||||
uint8_t * c = number_font[val];
|
||||
|
Loading…
Reference in New Issue
Block a user