diff options
Diffstat (limited to 'src/libps/s6ps_statparse.c')
-rw-r--r-- | src/libps/s6ps_statparse.c | 186 |
1 files changed, 186 insertions, 0 deletions
diff --git a/src/libps/s6ps_statparse.c b/src/libps/s6ps_statparse.c new file mode 100644 index 0000000..ea46d70 --- /dev/null +++ b/src/libps/s6ps_statparse.c @@ -0,0 +1,186 @@ +/* ISC license. */ + +#include <stdint.h> +#include <sys/types.h> +#include <errno.h> + +#include <skalibs/uint64.h> +#include <skalibs/types.h> +#include <skalibs/stralloc.h> +#include <skalibs/tai.h> + +#include "s6-ps.h" + + + /* + going to great lengths to avoid scanf(), but all this code + is still smaller than scanf (no floating point parsing etc.) + */ + +#define STATVARS 49 + +typedef size_t pscan_func (char const *, void *) ; +typedef pscan_func *pscan_func_ref ; + +static size_t f64 (char const *s, void *u64) +{ + uint64_t *u = u64 ; + return uint64_scan(s, u) ; +} + +#define DEFUNU(name, type) \ +static size_t name (char const *s, void *p) \ +{ \ + uint64_t u ; \ + size_t len = uint64_scan(s, &u) ; \ + *(type *)p = u ; \ + return len ; \ +} \ + +#define DEFUNS(name, type) \ +static size_t name (char const *s, void *p) \ +{ \ + int64_t d ; \ + size_t len = int64_scan(s, &d) ; \ + *(type *)p = d ; \ + return len ; \ +} \ + +DEFUNS(fint, int) +DEFUNS(fpid, pid_t) +DEFUNU(fdev, dev_t) + +static pscan_func_ref scanfuncs[STATVARS] = +{ + &fpid, /* ppid */ + &fpid, /* pgrp */ + &fpid, /* session */ + &fdev, /* tty_nr */ + &fpid, /* tpgid */ + &f64, /* flags */ + &f64, /* minflt */ + &f64, /* cminflt */ + &f64, /* majflt */ + &f64, /* cmajflt */ + &f64, /* utime */ + &f64, /* stime */ + &f64, /* cutime */ + &f64, /* cstime */ + &fint, /* priority */ + &fint, /* nice */ + &f64, /* num_threads */ + &f64, /* itrealvalue */ + &f64, /* starttime */ + &f64, /* vsize */ + &f64, /* rss */ + &f64, /* rsslim */ + &f64, /* startcode */ + &f64, /* endcode */ + &f64, /* startstack */ + &f64, /* kstkesp */ + &f64, /* kstkeip */ + &f64, /* signal */ + &f64, /* blocked */ + &f64, /* sigignore */ + &f64, /* sigcatch */ + &f64, /* wchan */ + &f64, /* nswap */ + &f64, /* cnswap */ + &fint, /* exit_signal */ + &f64, /* processor */ + &f64, /* rt_priority */ + &f64, /* policy */ + &f64, /* delayacct_blkio_ticks */ + &f64, /* guest_time */ + &f64, /* cguest_time */ + &f64, /* start_data */ + &f64, /* end_data */ + &f64, /* start_brk */ + &f64, /* arg_start */ + &f64, /* arg_end */ + &f64, /* env_start */ + &f64, /* env_end */ + &fint /* exit_code */ +} ; + +int s6ps_statparse (pscan_t *p) +{ + uint64_t dummy64 ; + int dummyint ; + size_t pos = 0 ; + void *scanresults[STATVARS] = + { + &p->ppid, + &p->pgrp, + &p->session, + &p->ttynr, + &p->tpgid, + &dummy64, + &dummy64, + &dummy64, + &dummy64, + &dummy64, + &p->utime, + &p->stime, + &p->cutime, + &p->cstime, + &p->prio, + &p->nice, + &p->threads, + &dummy64, + &p->start, + &p->vsize, + &p->rss, + &p->rsslim, + &dummy64, + &dummy64, + &dummy64, + &dummy64, + &dummy64, + &dummy64, + &dummy64, + &dummy64, + &dummy64, + &p->wchan, + &dummy64, + &dummy64, + &dummy64, + &p->cpuno, + &p->rtprio, + &p->policy, + &dummy64, + &dummy64, + &dummy64, + &dummy64, + &dummy64, + &dummy64, + &dummy64, + &dummy64, + &dummy64, + &dummy64, + &dummyint + } ; + unsigned int i = 0 ; + + if (!p->statlen) return 0 ; + pos = uint64_scan(p->data.s, &dummy64) ; + if (!pos) return 0 ; + if (dummy64 != p->pid) return 0 ; + if (pos + 5 + p->commlen > p->statlen) return 0 ; + if (p->data.s[pos++] != ' ') return 0 ; + if (p->data.s[pos++] != '(') return 0 ; + pos += p->commlen ; + if (p->data.s[pos++] != ')') return 0 ; + if (p->data.s[pos++] != ' ') return 0 ; + p->state = pos++ ; + for (; i < STATVARS ; i++) + { + size_t w ; + if (pos + 1 > p->statlen) return 0 ; + if (p->data.s[pos++] != ' ') return 0 ; + w = (*scanfuncs[i])(p->data.s + pos, scanresults[i]) ; + if (!w) return 0 ; + pos += w ; + } + return 1 ; +} |