Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
Rob Pilling committed Jul 6, 2011
0 parents commit ae5b540
Show file tree
Hide file tree
Showing 9 changed files with 393 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
*.o
utop
15 changes: 15 additions & 0 deletions Makefile
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
87 changes: 87 additions & 0 deletions gui.c
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);
}
8 changes: 8 additions & 0 deletions gui.h
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
23 changes: 23 additions & 0 deletions main.c
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;
}
203 changes: 203 additions & 0 deletions proc.c
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);
}
21 changes: 21 additions & 0 deletions proc.h
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
27 changes: 27 additions & 0 deletions util.c
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;
}
Loading

0 comments on commit ae5b540

Please sign in to comment.