diff --git a/include/libmu/proc_parser.h b/include/libmu/proc_parser.h index e3743d5..e39f59d 100644 --- a/include/libmu/proc_parser.h +++ b/include/libmu/proc_parser.h @@ -1,16 +1,132 @@ #ifndef _PROC_PARSER #define _PROC_PARSER +#include #include #include #include #include +#include +#include +#include #include +#include -struct { - char *cmdline; +struct mu_proc { + /* from status */ + uid_t uid; + gid_t gid; + + /* from stat */ + pid_t pid; + char cmdline[PATH_MAX + 1]; char state; + int ppid; + int pgrp; + int sid; + int tty; + int tpgid; + unsigned flags; + unsigned long minflt; + unsigned long cminflt; + unsigned long majflt; + unsigned long cmajflt; + unsigned long utime; + unsigned long stime; + long cutime; + long cstime; + long priority; long nice; -} mu_proc; + long num_threads; + long itrealvalue; + unsigned long long starttime; + unsigned long vsize; + long rss; + long rsslim; +}; + +int mu_proc_status(const char *prog_name, const pid_t pid, struct mu_proc *proc_s) { + proc_s->uid = -1; + proc_s->gid = -1; + + /* Proccess file */ + char path[PATH_MAX + 1]; + snprintf(path, sizeof(path), "/proc/%d/status", pid); + + int fd = open(path, O_RDONLY); + if (fd < 0) { + if (prog_name) + fprintf(stderr, "%s: %s: %s\n", prog_name, path, strerror(errno)); + + return 1; + } + + char status[2048]; + ssize_t n = read(fd, status, sizeof(status) - 1); + status[n] = '\0'; + close(fd); + + char *token = strtok(status, "\n"); + while (token) { + char *val = strchr(token, ':'); + if (val == NULL) { + fprintf(stderr, "ps: incorrect %s file\n", path); + return 1; + } + + *val = '\0'; + val++; + + /* Strip */ + while (isspace(*val)) + val++; + + /* Write values */ + if (!strncmp(token, "Uid", 3)) + proc_s->uid = strtoul(val, 0L, 10); + + else if (!strncmp(token, "Gid", 3)) + proc_s->gid = strtoul(val, 0L, 10); + + token = strtok(NULL, "\n"); + } + + return 0; +} + +int mu_proc_stat(const char *prog_name, const pid_t pid, struct mu_proc *proc_s) { + char path[PATH_MAX + 1]; + snprintf(path, sizeof(path), "/proc/%d/stat", pid); + + FILE *fp = fopen(path, "r"); + if (fp == NULL) { + if (prog_name) + fprintf(stderr, "%s: %s: %s\n", prog_name, path, strerror(errno)); + + return 1; + } + + fscanf(fp, "%d %s %c %d %d %d %d %d %u %lu %lu %lu %lu %lu %lu", &proc_s->pid, proc_s->cmdline, &proc_s->state, &proc_s->ppid, &proc_s->pgrp, &proc_s->sid, &proc_s->tty, &proc_s->tpgid, &proc_s->flags, &proc_s->minflt, &proc_s->cminflt, &proc_s->majflt, &proc_s->cmajflt, &proc_s->utime, &proc_s->stime); + fscanf(fp, "%ld %ld %ld %ld %ld %ld %llu %lu %ld %ld", &proc_s->cutime, &proc_s->cstime, &proc_s->priority, &proc_s->nice, &proc_s->num_threads, &proc_s->itrealvalue, &proc_s->starttime, &proc_s->vsize, &proc_s->rss, &proc_s->rsslim); + fclose(fp); + + return 0; +} + +int mu_proc_parser(const char *prog_name, const pid_t pid, struct mu_proc *proc_s) { + memset(proc_s, 0, sizeof(struct mu_proc)); + + int ret = 0; + + /* STAT */ + if (mu_proc_stat(prog_name, pid, proc_s)) + ret = 1; + + /* STATUS */ + if (mu_proc_status(prog_name, pid, proc_s)) + ret = 1; + + return ret; +} #endif