forked from bobrippling/utop
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Rob Pilling
committed
Jul 6, 2011
0 parents
commit ae5b540
Showing
9 changed files
with
393 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
*.o | ||
utop |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
CFLAGS = -g -Wall -Wextra -pedantic | ||
LDFLAGS = -g -lncurses | ||
|
||
.PHONY: clean | ||
|
||
utop: main.o proc.o gui.o util.o | ||
${CC} ${LDFLAGS} -o $@ $^ | ||
|
||
clean: | ||
@rm -f *.o utop | ||
|
||
gui.o: gui.c proc.h gui.h util.h | ||
main.o: main.c proc.h gui.h | ||
proc.o: proc.c proc.h | ||
util.o: util.c |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
#include <ncurses.h> | ||
#include <sys/types.h> | ||
|
||
#include "proc.h" | ||
#include "gui.h" | ||
#include "util.h" | ||
|
||
int pos_y = 0; | ||
|
||
void gui_init() | ||
{ | ||
initscr(); | ||
noecho(); | ||
cbreak(); | ||
raw(); | ||
|
||
nonl(); | ||
intrflush(stdscr, FALSE); | ||
keypad(stdscr, TRUE); | ||
|
||
halfdelay(2); /* x/10s of a second wait */ | ||
|
||
if(has_colors()){ | ||
start_color(); | ||
use_default_colors(); | ||
init_pair(COLOR_BLACK, -1, -1); | ||
init_pair(COLOR_GREEN, COLOR_GREEN, -1); | ||
init_pair(COLOR_WHITE, COLOR_WHITE, -1); | ||
init_pair(COLOR_RED, COLOR_RED, -1); | ||
init_pair(COLOR_CYAN, COLOR_CYAN, -1); | ||
init_pair(COLOR_MAGENTA, COLOR_MAGENTA, -1); | ||
init_pair(COLOR_BLUE, COLOR_BLUE, -1); | ||
init_pair(COLOR_YELLOW, COLOR_YELLOW, -1); | ||
} | ||
} | ||
|
||
void gui_term() | ||
{ | ||
endwin(); | ||
} | ||
|
||
void showprocs(struct proc **procs) | ||
{ | ||
struct proc *p = proc_to_list(procs); | ||
char buf[256]; | ||
int y; | ||
|
||
y = pos_y; | ||
|
||
while(p->next && y --> 0) | ||
p = p->next; | ||
|
||
for(y = 0; y < LINES && p; y++, p = p->next){ | ||
snprintf(buf, sizeof buf, "%s - %d", p->cmd, p->pc_cpu); | ||
mvaddnstr(y, 0, buf, COLS - 1); | ||
} | ||
|
||
move(0, 0); | ||
} | ||
|
||
void gui_run(struct proc **procs) | ||
{ | ||
long last_update = 0; | ||
int fin = 0; | ||
|
||
do{ | ||
const long now = mstime(); | ||
int ch, nprocs; | ||
|
||
if(last_update + 500 < now){ | ||
last_update = now; | ||
proc_update(procs, &nprocs); | ||
fprintf(stderr, "proc_update: %d, pos_y: %d\n", nprocs, pos_y); | ||
} | ||
|
||
clear(); | ||
showprocs(procs); | ||
|
||
ch = getch(); | ||
switch(ch){ | ||
case 'q': fin = 1; break; | ||
|
||
case 'k': if(pos_y > 0) pos_y--; break; | ||
case 'j': if(pos_y < nprocs-1) pos_y++; break; | ||
} | ||
}while(!fin); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
#ifndef GUI_H | ||
#define GUI_H | ||
|
||
void gui_init(); | ||
void gui_term(); | ||
void gui_run(struct proc **); | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
#include <stdio.h> | ||
#include <unistd.h> | ||
#include <sys/select.h> | ||
|
||
#include "proc.h" | ||
#include "gui.h" | ||
|
||
#define MS_TO_US(n) ((n) * 1000) | ||
|
||
int main(void) | ||
{ | ||
struct proc **proclist; | ||
|
||
gui_init(); | ||
|
||
proclist = proc_init(); | ||
|
||
gui_run(proclist); | ||
|
||
gui_term(); | ||
|
||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,203 @@ | ||
#include <stdio.h> | ||
#include <stdlib.h> | ||
#include <string.h> | ||
#include <sys/types.h> | ||
#include <sys/stat.h> | ||
#include <dirent.h> | ||
#include <unistd.h> | ||
#include <errno.h> | ||
#include <alloca.h> | ||
|
||
#include "proc.h" | ||
|
||
/*#define PHONY 1*/ | ||
|
||
struct proc *proc_to_list(struct proc **procs) | ||
{ | ||
struct proc *first, **next = &first; | ||
int i; | ||
|
||
for(i = 0; i < NPROCS; i++){ | ||
struct proc *p; | ||
for(p = procs[i]; p; p = p->hash_next){ | ||
*next = p; | ||
next = &p->next; | ||
} | ||
} | ||
*next = NULL; | ||
return first; | ||
} | ||
|
||
void proc_free(struct proc *p) | ||
{ | ||
free(p->argv0); | ||
free(p->proc_path); | ||
free(p->cmd); | ||
free(p); | ||
} | ||
|
||
struct proc *proc_frompid(pid_t pid) | ||
{ | ||
struct proc *this = NULL; | ||
FILE *f; | ||
char cmdln[32]; | ||
|
||
snprintf(cmdln, sizeof cmdln, "/proc/%d/cmdline", pid); | ||
|
||
f = fopen(cmdln, "r"); | ||
if(f){ | ||
char buffer[256]; | ||
|
||
if(fgets(buffer, sizeof buffer, f)){ | ||
char *p; | ||
|
||
this = malloc(sizeof *this); | ||
if(!this){ | ||
perror("malloc()"); | ||
exit(1); | ||
} | ||
memset(this, 0, sizeof *this); | ||
|
||
this->pid = pid; | ||
this->argv0 = strdup(buffer); | ||
this->proc_path = strdup(cmdln); | ||
this->cmd = strdup(buffer); | ||
|
||
if(!this->argv0 || !this->proc_path || !this->cmd){ | ||
perror("malloc()"); | ||
exit(1); | ||
} | ||
|
||
p = strchr(this->cmd, ' '); | ||
if(p) | ||
*p = '\0'; | ||
} | ||
|
||
fclose(f); | ||
} | ||
|
||
return this; | ||
} | ||
|
||
int proc_listcontains(struct proc **list, pid_t pid) | ||
{ | ||
struct proc *p; | ||
|
||
for(p = list[pid % NPROCS]; p; p = p->hash_next) | ||
if(p->pid == pid) | ||
return 1; | ||
|
||
return 0; | ||
} | ||
|
||
void proc_addto(struct proc **list, struct proc *p) | ||
{ | ||
struct proc *last; | ||
|
||
last = list[p->pid % NPROCS]; | ||
if(last){ | ||
while(last->hash_next) | ||
last = last->hash_next; | ||
last->hash_next = p; | ||
}else{ | ||
list[p->pid % NPROCS] = p; | ||
} | ||
} | ||
|
||
struct proc **proc_init() | ||
{ | ||
int n = sizeof(struct proc *) * NPROCS; | ||
struct proc **p = malloc(n); | ||
memset(p, 0, n); | ||
#ifdef PHONY | ||
p[0] = proc_frompid(1); | ||
p[1 % NPROCS] = proc_frompid(getpid()); | ||
#endif | ||
return p; | ||
} | ||
|
||
void proc_listall(struct proc **list, int *np) | ||
{ | ||
/* TODO: kernel threads */ | ||
DIR *d = opendir("/proc"); | ||
struct dirent *ent; | ||
int n = *np; | ||
|
||
if(!d){ | ||
perror("opendir()"); | ||
exit(1); | ||
} | ||
|
||
errno = 0; | ||
while((errno = 0, ent = readdir(d))){ | ||
int pid; | ||
|
||
if(sscanf(ent->d_name, "%d", &pid) && !proc_listcontains(list, pid)){ | ||
struct proc *p = proc_frompid(pid); | ||
|
||
if(p){ | ||
proc_addto(list, p); | ||
n++; | ||
} | ||
} | ||
} | ||
|
||
if(errno){ | ||
fprintf(stderr, "readdir(): %s\n", strerror(errno)); | ||
exit(1); | ||
} | ||
|
||
*np = n; | ||
closedir(d); | ||
} | ||
|
||
void proc_update_single(struct proc *proc) | ||
{ | ||
/* | ||
char buf[256]; | ||
char path[32]; | ||
snprintf(path, sizeof path, "%s/stat", proc->proc_path); | ||
if(!fline(path, buf, sizeof buf)){ | ||
char *start = strrchr(buf, ')') + 2; | ||
} | ||
*/ | ||
|
||
proc->pc_cpu = rand(); | ||
} | ||
|
||
void proc_update(struct proc **list, int *np) | ||
{ | ||
int i; | ||
int n; | ||
|
||
#ifdef PHONY | ||
*np = 2; | ||
return; | ||
#endif | ||
|
||
for(i = n = 0; i < NPROCS; i++){ | ||
struct proc *p; | ||
struct proc **changeme = &list[i]; | ||
|
||
for(p = list[i]; p; p = p->hash_next){ | ||
struct stat st; | ||
|
||
if(stat(p->proc_path, &st)){ | ||
*changeme = p->hash_next; | ||
|
||
proc_free(p); | ||
}else{ | ||
proc_update_single(p); | ||
n++; | ||
} | ||
|
||
changeme = &p->hash_next; | ||
} | ||
} | ||
|
||
*np = n; | ||
proc_listall(list, np); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
#ifndef PROC_H | ||
#define PROC_H | ||
|
||
struct proc | ||
{ | ||
char *proc_path; | ||
char *cmd, *argv0; | ||
pid_t pid; | ||
|
||
int pc_cpu; | ||
|
||
struct proc *hash_next, *next; /* hash list */ | ||
}; | ||
|
||
struct proc **proc_init(); | ||
struct proc *proc_to_list(struct proc **); | ||
void proc_update(struct proc **list, int *); | ||
|
||
#define NPROCS 128 | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
#include <stdio.h> | ||
#include <stdlib.h> | ||
#include <sys/time.h> | ||
|
||
#include "util.h" | ||
|
||
long mstime() | ||
{ | ||
struct timeval t; | ||
gettimeofday(&t, NULL); | ||
return t.tv_sec * 1000 + t.tv_usec / 1000; | ||
} | ||
|
||
int fline(const char *path, char *buf, int len) | ||
{ | ||
FILE *f = fopen(path, "r"); | ||
int ret = 0; | ||
|
||
if(!f) | ||
return 1; | ||
|
||
if(fgets(buf, len, f) == NULL) | ||
ret = 1; | ||
|
||
fclose(f); | ||
return ret; | ||
} |
Oops, something went wrong.