diff --git a/solaris/Makefile b/solaris/Makefile new file mode 100644 index 0000000..0a8b52d --- /dev/null +++ b/solaris/Makefile @@ -0,0 +1,9 @@ +CC = gcc +BIN = restartable +CFLAGS = -Wall -O2 + +$(BIN): *.c + $(CC) -o $@ $(CFLAGS) *.c $(LDFLAGS) + +clean: + @rm -f $(BIN) diff --git a/solaris/restartable.c b/solaris/restartable.c new file mode 100644 index 0000000..2ee56f9 --- /dev/null +++ b/solaris/restartable.c @@ -0,0 +1,107 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#define _KERNEL +#include + +static int verbose; + +static void +parse_psinfo(const char *pid, int procFd) { + struct passwd *pwd; + char *user = "-"; + psinfo_t psinfo; + int fd; + + if ((fd = openat(procFd, "psinfo", O_RDONLY)) == -1) { + warn("%s", pid); + return; + } + + if (read(fd, &psinfo, sizeof(psinfo_t)) == sizeof(psinfo_t)) { + if ((pwd = getpwuid(psinfo.pr_uid)) != NULL) + user = pwd->pw_name; + printf("%d\t%d\t%d\t%s\t%s\n", psinfo.pr_pid, psinfo.pr_ppid, psinfo.pr_uid, user, psinfo.pr_fname); + if (verbose) + printf("\t%s\n", psinfo.pr_psargs); + } + + (void) close(fd); +} + +static void +print_proc(const char *pid) { + char linkPath[PATH_MAX]; + char link[PATH_MAX]; + char procPid[256]; + int procFd, mapFd; + prmap_t entry; + + (void) snprintf(procPid, sizeof(procPid), "/proc/%s", pid); + if ((procFd = open(procPid, O_RDONLY | O_DIRECTORY)) == -1) + return; + + if ((mapFd = openat(procFd, "map", O_RDONLY)) == -1) { + warn("%s", pid); + close(procFd); + return; + } + + while (read(mapFd, &entry, sizeof(entry)) == sizeof(entry)) { + /* Skip anonymous mappings */ + if (entry.pr_mflags & MA_ANON) + continue; + /* Skip non-executable mappings */ + if (!(entry.pr_mflags & MA_EXEC)) + continue; + /* Solaris doesn't have w^x, so skip writable to avoid duplicate entries */ + if (entry.pr_mflags & MA_WRITE) + continue; + + (void) snprintf(linkPath, sizeof(linkPath), "path/%s", entry.pr_mapname); + if (readlinkat(procFd, linkPath, link, sizeof(link)) == -1) { + parse_psinfo(pid, procFd); + break; + } + } + + (void) close(mapFd); + (void) close(procFd); +} + +static void +print_all(void) { + DIR *dir; + struct dirent *entry; + + dir = opendir("/proc"); + if (dir == NULL) + err(1, "/proc"); + + while ((entry = readdir(dir)) != NULL) + if (isdigit(entry->d_name[0])) + print_proc(entry->d_name); + + (void) closedir(dir); +} + +int +main(int argc, char *argv[]) { + if (argc > 2) + errx(1, "Usage: %s [-v]\n", argv[0]); + if (argc > 1 && !strcmp(argv[1], "-v")) + verbose = 1; + + printf("PID\tPPID\tUID\tUser\tCommand\n"); + print_all(); + + return 0; +}