Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 31701d60 authored by Elliott Hughes's avatar Elliott Hughes Committed by Gerrit Code Review
Browse files

Merge "Lose ps to toybox."

parents ad717d65 eea3c0e6
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -36,7 +36,6 @@ OUR_TOOLS := \
    log \
    nandread \
    newfs_msdos \
    ps \
    sendevent \
    start \
    stop \

toolbox/ps.c

deleted100644 → 0
+0 −340
Original line number Diff line number Diff line
#include <ctype.h>
#include <dirent.h>
#include <fcntl.h>
#include <inttypes.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

#include <cutils/sched_policy.h>

static char *nexttoksep(char **strp, char *sep)
{
    char *p = strsep(strp,sep);
    return (p == 0) ? "" : p;
}
static char *nexttok(char **strp)
{
    return nexttoksep(strp, " ");
}

#define SHOW_PRIO 1
#define SHOW_TIME 2
#define SHOW_POLICY 4
#define SHOW_CPU  8
#define SHOW_MACLABEL 16
#define SHOW_NUMERIC_UID 32
#define SHOW_ABI 64

#if __LP64__
#define PC_WIDTH 10 /* Realistically, the top bits will be 0, so don't waste space. */
#else
#define PC_WIDTH (2*sizeof(uintptr_t))
#endif

static int display_flags = 0;
static int ppid_filter = 0;

static void print_exe_abi(int pid);

static int ps_line(int pid, int tid)
{
    char statline[1024];
    char cmdline[1024];
    char macline[1024];
    char user[32];
    struct stat stats;
    int r;
    char *ptr, *name, *state;
    int ppid;
    unsigned rss, vss;
    uintptr_t eip;
    unsigned utime, stime;
    int prio, nice, rtprio, sched, psr;
    struct passwd *pw;

    snprintf(statline, sizeof(statline), "/proc/%d", tid ? tid : pid);
    stat(statline, &stats);

    if (tid) {
        snprintf(statline, sizeof(statline), "/proc/%d/task/%d/stat", pid, tid);
        cmdline[0] = 0;
        snprintf(macline, sizeof(macline), "/proc/%d/task/%d/attr/current", pid, tid);
    } else {
        snprintf(statline, sizeof(statline), "/proc/%d/stat", pid);
        snprintf(cmdline, sizeof(cmdline), "/proc/%d/cmdline", pid);
        snprintf(macline, sizeof(macline), "/proc/%d/attr/current", pid);
        int fd = open(cmdline, O_RDONLY);
        if (fd == 0) {
            r = 0;
        } else {
            r = read(fd, cmdline, 1023);
            close(fd);
            if (r < 0) r = 0;
        }
        cmdline[r] = 0;
    }

    int fd = open(statline, O_RDONLY);
    if (fd == 0) return -1;
    r = read(fd, statline, 1023);
    close(fd);
    if (r < 0) return -1;
    statline[r] = 0;

    ptr = statline;
    nexttok(&ptr); // skip pid
    ptr++;          // skip "("

    name = ptr;
    ptr = strrchr(ptr, ')'); // Skip to *last* occurence of ')',
    *ptr++ = '\0';           // and null-terminate name.

    ptr++;          // skip " "
    state = nexttok(&ptr);
    ppid = atoi(nexttok(&ptr));
    nexttok(&ptr); // pgrp
    nexttok(&ptr); // sid
    nexttok(&ptr); // tty
    nexttok(&ptr); // tpgid
    nexttok(&ptr); // flags
    nexttok(&ptr); // minflt
    nexttok(&ptr); // cminflt
    nexttok(&ptr); // majflt
    nexttok(&ptr); // cmajflt
#if 1
    utime = atoi(nexttok(&ptr));
    stime = atoi(nexttok(&ptr));
#else
    nexttok(&ptr); // utime
    nexttok(&ptr); // stime
#endif
    nexttok(&ptr); // cutime
    nexttok(&ptr); // cstime
    prio = atoi(nexttok(&ptr));
    nice = atoi(nexttok(&ptr));
    nexttok(&ptr); // threads
    nexttok(&ptr); // itrealvalue
    nexttok(&ptr); // starttime
    vss = strtoul(nexttok(&ptr), 0, 10); // vsize
    rss = strtoul(nexttok(&ptr), 0, 10); // rss
    nexttok(&ptr); // rlim
    nexttok(&ptr); // startcode
    nexttok(&ptr); // endcode
    nexttok(&ptr); // startstack
    nexttok(&ptr); // kstkesp
    eip = strtoul(nexttok(&ptr), 0, 10); // kstkeip
    nexttok(&ptr); // signal
    nexttok(&ptr); // blocked
    nexttok(&ptr); // sigignore
    nexttok(&ptr); // sigcatch
    nexttok(&ptr); // wchan
    nexttok(&ptr); // nswap
    nexttok(&ptr); // cnswap
    nexttok(&ptr); // exit signal
    psr = atoi(nexttok(&ptr)); // processor
    rtprio = atoi(nexttok(&ptr)); // rt_priority
    sched = atoi(nexttok(&ptr)); // scheduling policy

    nexttok(&ptr); // tty

    if (tid != 0) {
        ppid = pid;
        pid = tid;
    }

    pw = getpwuid(stats.st_uid);
    if (pw == 0 || (display_flags & SHOW_NUMERIC_UID)) {
        snprintf(user, sizeof(user), "%d", (int)stats.st_uid);
    } else {
        snprintf(user, sizeof(user), "%s", pw->pw_name);
    }

    if (ppid_filter != 0 && ppid != ppid_filter) {
        return 0;
    }

    if (display_flags & SHOW_MACLABEL) {
        fd = open(macline, O_RDONLY);
        strcpy(macline, "-");
        if (fd >= 0) {
            r = read(fd, macline, sizeof(macline)-1);
            close(fd);
            if (r > 0)
                macline[r] = 0;
        }
        printf("%-30s ", macline);
    }

    printf("%-9s %-5d %-5d %-6d %-5d", user, pid, ppid, vss / 1024, rss * 4);
    if (display_flags & SHOW_CPU)
        printf(" %-2d", psr);
    if (display_flags & SHOW_PRIO)
        printf(" %-5d %-5d %-5d %-5d", prio, nice, rtprio, sched);
    if (display_flags & SHOW_POLICY) {
        SchedPolicy p;
        if (get_sched_policy(pid, &p) < 0)
            printf(" un ");
        else
            printf(" %.2s ", get_sched_policy_name(p));
    }
    char path[PATH_MAX];
    snprintf(path, sizeof(path), "/proc/%d/wchan", pid);
    char wchan[10];
    fd = open(path, O_RDONLY);
    ssize_t wchan_len = read(fd, wchan, sizeof(wchan));
    if (wchan_len == -1) {
        wchan[wchan_len = 0] = '\0';
    }
    close(fd);
    printf(" %10.*s %0*" PRIxPTR " %s ", (int) wchan_len, wchan, (int) PC_WIDTH, eip, state);
    if (display_flags & SHOW_ABI) {
        print_exe_abi(pid);
    }
    printf("%s", cmdline[0] ? cmdline : name);
    if (display_flags & SHOW_TIME)
        printf(" (u:%d, s:%d)", utime, stime);

    printf("\n");
    return 0;
}

static void print_exe_abi(int pid)
{
    int fd, r;
    char exeline[1024];

    snprintf(exeline, sizeof(exeline), "/proc/%d/exe", pid);
    fd = open(exeline, O_RDONLY);
    if (fd == 0) {
        printf("    ");
        return;
    }
    r = read(fd, exeline, 5 /* 4 byte ELFMAG + 1 byte EI_CLASS */);
    close(fd);
    if (r < 0) {
        printf("    ");
        return;
    }
    if (memcmp("\177ELF", exeline, 4) != 0) {
        printf("??  ");
        return;
    }
    switch (exeline[4]) {
        case 1:
            printf("32  ");
            return;
        case 2:
            printf("64  ");
            return;
        default:
            printf("??  ");
            return;
    }
}

void ps_threads(int pid)
{
    char tmp[128];
    DIR *d;
    struct dirent *de;

    snprintf(tmp,sizeof(tmp),"/proc/%d/task",pid);
    d = opendir(tmp);
    if (d == 0) return;

    while ((de = readdir(d)) != 0) {
        if (isdigit(de->d_name[0])) {
            int tid = atoi(de->d_name);
            if (tid == pid) continue;
            ps_line(pid, tid);
        }
    }
    closedir(d);
}

int ps_main(int argc, char **argv)
{
    DIR *d;
    struct dirent *de;
    int pidfilter = 0;
    int threads = 0;

    while (argc > 1) {
        if (!strcmp(argv[1], "-t")) {
            threads = 1;
        } else if (!strcmp(argv[1], "-n")) {
            display_flags |= SHOW_NUMERIC_UID;
        } else if (!strcmp(argv[1], "-x")) {
            display_flags |= SHOW_TIME;
        } else if (!strcmp(argv[1], "-Z")) {
            display_flags |= SHOW_MACLABEL;
        } else if (!strcmp(argv[1], "-P")) {
            display_flags |= SHOW_POLICY;
        } else if (!strcmp(argv[1], "-p")) {
            display_flags |= SHOW_PRIO;
        } else if (!strcmp(argv[1], "-c")) {
            display_flags |= SHOW_CPU;
        } else if (!strcmp(argv[1], "--abi")) {
            display_flags |= SHOW_ABI;
        } else if (!strcmp(argv[1], "--ppid")) {
            if (argc < 3) {
                /* Bug 26554285: Use printf because some apps require at least
                 * one line of output to stdout even for errors.
                 */
                printf("no ppid\n");
                return 1;
            }
            ppid_filter = atoi(argv[2]);
            if (ppid_filter == 0) {
                /* Bug 26554285: Use printf because some apps require at least
                 * one line of output to stdout even for errors.
                 */
                printf("bad ppid '%s'\n", argv[2]);
                return 1;
            }
            argc--;
            argv++;
        } else {
            pidfilter = atoi(argv[1]);
            if (pidfilter == 0) {
                /* Bug 26554285: Use printf because some apps require at least
                 * one line of output to stdout even for errors.
                 */
                printf("bad pid '%s'\n", argv[1]);
                return 1;
            }
        }
        argc--;
        argv++;
    }

    if (display_flags & SHOW_MACLABEL) {
        printf("LABEL                          ");
    }
    printf("USER      PID   PPID  VSIZE  RSS  %s%s %sWCHAN      %*s  %sNAME\n",
           (display_flags&SHOW_CPU)?"CPU ":"",
           (display_flags&SHOW_PRIO)?"PRIO  NICE  RTPRI SCHED ":"",
           (display_flags&SHOW_POLICY)?"PCY " : "",
           (int) PC_WIDTH, "PC",
           (display_flags&SHOW_ABI)?"ABI " : "");

    d = opendir("/proc");
    if (d == 0) return -1;

    while ((de = readdir(d)) != 0) {
        if (isdigit(de->d_name[0])) {
            int pid = atoi(de->d_name);
            if (!pidfilter || (pidfilter == pid)) {
                ps_line(pid, 0);
                if (threads) ps_threads(pid);
            }
        }
    }
    closedir(d);
    return 0;
}