2013-08-14 14:38:43 +00:00
|
|
|
/* See LICENSE file for copyright and license details. */
|
2013-08-16 13:08:20 +00:00
|
|
|
#include <sys/stat.h>
|
2014-06-30 18:03:41 +00:00
|
|
|
|
2013-08-14 14:38:43 +00:00
|
|
|
#include <errno.h>
|
2014-06-30 18:03:41 +00:00
|
|
|
#include <fcntl.h>
|
|
|
|
#include <limits.h>
|
2013-08-14 14:38:43 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
2014-06-30 18:03:41 +00:00
|
|
|
#include <unistd.h>
|
|
|
|
|
2013-08-14 14:38:43 +00:00
|
|
|
#include "../proc.h"
|
|
|
|
#include "../util.h"
|
|
|
|
|
2013-08-16 13:08:20 +00:00
|
|
|
int
|
|
|
|
parsecmdline(pid_t pid, char *buf, size_t siz)
|
|
|
|
{
|
|
|
|
int fd;
|
|
|
|
char path[PATH_MAX];
|
|
|
|
ssize_t n, i;
|
|
|
|
|
2014-08-20 19:37:12 +00:00
|
|
|
snprintf(path, sizeof(path), "/proc/%ld/cmdline", (long)pid);
|
2013-08-16 13:08:20 +00:00
|
|
|
fd = open(path, O_RDONLY);
|
|
|
|
if (fd < 0)
|
2014-02-13 12:25:29 +00:00
|
|
|
return -1;
|
2014-08-20 19:37:12 +00:00
|
|
|
n = read(fd, buf, siz > 0 ? siz - 1 : 0);
|
|
|
|
if (n < 0) {
|
|
|
|
weprintf("read %s:", path);
|
|
|
|
close(fd);
|
|
|
|
return -1;
|
|
|
|
}
|
2013-08-16 13:08:20 +00:00
|
|
|
if (!n) {
|
|
|
|
close(fd);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
buf[n] = '\0';
|
|
|
|
for (i = 0; i < n; i++)
|
|
|
|
if (buf[i] == '\0')
|
|
|
|
buf[i] = ' ';
|
|
|
|
close(fd);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-08-14 14:38:43 +00:00
|
|
|
int
|
|
|
|
parsestat(pid_t pid, struct procstat *ps)
|
|
|
|
{
|
|
|
|
char path[PATH_MAX];
|
|
|
|
FILE *fp;
|
2014-07-05 12:51:13 +00:00
|
|
|
size_t len;
|
2013-08-14 14:38:43 +00:00
|
|
|
|
|
|
|
snprintf(path, sizeof(path), "/proc/%d/stat", pid);
|
|
|
|
if (!(fp = fopen(path, "r")))
|
2014-02-13 12:25:29 +00:00
|
|
|
return -1;
|
2013-08-14 14:38:43 +00:00
|
|
|
fscanf(fp, "%d %s %c %d %d %d %d %d %u %lu %lu %lu %lu %lu %lu",
|
|
|
|
&ps->pid, ps->comm,
|
|
|
|
&ps->state, &ps->ppid, &ps->pgrp,
|
|
|
|
&ps->sid, &ps->tty_nr, &ps->tpgid, &ps->flags,
|
|
|
|
&ps->minflt, &ps->cminflt, &ps->majflt, &ps->cmajflt,
|
|
|
|
&ps->utime, &ps->stime);
|
2014-02-14 13:52:04 +00:00
|
|
|
fscanf(fp, "%ld %ld %ld %ld %ld %ld %llu %lu %ld %ld",
|
2013-08-14 14:38:43 +00:00
|
|
|
&ps->cutime, &ps->cstime, &ps->priority, &ps->nice,
|
|
|
|
&ps->num_threads, &ps->itrealvalue, &ps->starttime,
|
|
|
|
&ps->vsize, &ps->rss, &ps->rsslim);
|
|
|
|
/* Filter out '(' and ')' from comm */
|
2014-07-09 15:39:32 +00:00
|
|
|
if ((len = strlen(ps->comm)) > 0)
|
2014-07-05 12:51:13 +00:00
|
|
|
len--;
|
|
|
|
ps->comm[len] = '\0';
|
|
|
|
memmove(ps->comm, ps->comm + 1, len);
|
2013-08-14 14:38:43 +00:00
|
|
|
fclose(fp);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-08-16 15:36:52 +00:00
|
|
|
int
|
|
|
|
parsestatus(pid_t pid, struct procstatus *pstatus)
|
|
|
|
{
|
|
|
|
char path[PATH_MAX];
|
|
|
|
char buf[BUFSIZ], *off;
|
|
|
|
int fd;
|
|
|
|
ssize_t n;
|
|
|
|
|
|
|
|
snprintf(path, sizeof(path), "/proc/%d/status", pid);
|
|
|
|
fd = open(path, O_RDONLY);
|
|
|
|
if (fd < 0)
|
2014-02-13 12:25:29 +00:00
|
|
|
return -1;
|
2013-08-16 15:36:52 +00:00
|
|
|
n = read(fd, buf, sizeof(buf) - 1);
|
|
|
|
if (n < 0)
|
|
|
|
eprintf("%s: read error:", path);
|
|
|
|
if (!n) {
|
|
|
|
close(fd);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
buf[n] = '\0';
|
|
|
|
close(fd);
|
|
|
|
off = strstr(buf, "Uid:");
|
|
|
|
if (!off)
|
|
|
|
return -1;
|
|
|
|
sscanf(off, "Uid: %u %u", &pstatus->uid, &pstatus->euid);
|
|
|
|
off = strstr(buf, "Gid:");
|
|
|
|
if (!off)
|
|
|
|
return -1;
|
|
|
|
sscanf(off, "Gid: %u %u", &pstatus->gid, &pstatus->egid);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-08-14 14:38:43 +00:00
|
|
|
int
|
2013-08-16 15:40:29 +00:00
|
|
|
pidfile(const char *file)
|
2013-08-14 14:38:43 +00:00
|
|
|
{
|
|
|
|
char *end;
|
|
|
|
|
|
|
|
errno = 0;
|
2013-08-16 15:40:29 +00:00
|
|
|
strtol(file, &end, 10);
|
2013-08-14 14:38:43 +00:00
|
|
|
if (*end != '\0')
|
|
|
|
return 0;
|
|
|
|
if (errno != 0)
|
|
|
|
return 0;
|
|
|
|
return 1;
|
|
|
|
}
|