psvstat.c (3642B) download
1#include <fcntl.h>
2#include <limits.h>
3#include <stdint.h>
4#include <stdio.h>
5#include <stdlib.h>
6#include <string.h>
7#include <time.h>
8#include <unistd.h>
9
10struct service_serial {
11 uint8_t status_change[8];
12 uint8_t status_change_ms[4];
13 uint8_t pid[4];
14 uint8_t paused;
15 uint8_t wantsup;
16 uint8_t terminated;
17 uint8_t state;
18};
19
20void printstatus(const char* path, struct service_serial* buffer) {
21 const char* name;
22 if ((name = strrchr(path, '/'))) {
23 if (!strcmp(name, "/log")) {
24 while (--name > path) {
25 if (*name == '/')
26 break;
27 }
28 name++;
29 } else {
30 name++;
31 }
32 } else
33 name = path;
34
35 char* home = getenv("HOME");
36 int isuser = home != NULL && strncmp(home, path, strlen(home)) == 0;
37
38 if (isuser) {
39 printf("user ");
40 } else {
41 printf("sys ");
42 }
43
44 printf("%-20s ", name);
45
46 // wants up and is up
47 // wants down and is down
48 if ((buffer->wantsup == 'd') == (buffer->state == 0))
49 printf("= ");
50 // wants down and is up
51 else if (buffer->wantsup == 'd')
52 printf("v ");
53 // wants up and is down
54 else if (buffer->state == 0)
55 printf("^ ");
56
57 if (buffer->paused)
58 printf("paus ");
59 else if (buffer->state == 0)
60 printf("down ");
61 else if (buffer->state == 1)
62 printf("run ");
63 else if (buffer->state == 2)
64 printf("fin ");
65 else
66 printf("??? ");
67
68 uint64_t tai = ((uint64_t) buffer->status_change[0] << 56) |
69 ((uint64_t) buffer->status_change[1] << 48) |
70 ((uint64_t) buffer->status_change[2] << 40) |
71 ((uint64_t) buffer->status_change[3] << 32) |
72 ((uint64_t) buffer->status_change[4] << 24) |
73 ((uint64_t) buffer->status_change[5] << 16) |
74 ((uint64_t) buffer->status_change[6] << 8) |
75 ((uint64_t) buffer->status_change[7] << 0);
76
77 time_t timediff = time(NULL) - tai + 4611686018427387914ULL;
78 const char* timediffu = timediff == 1 ? "second" : "seconds";
79 if (timediff >= 60) {
80 timediff /= 60;
81 timediffu = timediff == 1 ? "minute" : "minutes";
82 if (timediff >= 60) {
83 timediff /= 60;
84 timediffu = timediff == 1 ? "hour" : "hours";
85 if (timediff >= 24) {
86 timediff /= 24;
87 timediffu = timediff == 1 ? "day" : "days";
88 }
89 }
90 }
91 char timediffstr[20];
92 snprintf(timediffstr, sizeof timediffstr, "%ld %s", timediff, timediffu);
93
94 printf("%-11s ", timediffstr);
95
96 if (buffer->state == 1) {
97 pid_t pid = (buffer->pid[0] << 0) |
98 (buffer->pid[1] << 8) |
99 (buffer->pid[2] << 16) |
100 (buffer->pid[3] << 24);
101
102 printf("%-5d ", pid);
103
104 int procfd;
105 char procpath[PATH_MAX];
106 char cmdline[1024];
107 int nread;
108 snprintf(procpath, sizeof procpath, "/proc/%d/comm", pid);
109
110 if ((procfd = open(procpath, O_RDONLY)) != -1) {
111 nread = read(procfd, cmdline, sizeof cmdline);
112 if (nread < 0) nread = 0;
113 if (nread == sizeof cmdline) {
114 strcpy(&cmdline[sizeof cmdline - 4], "...");
115 } else {
116 nread--;
117 cmdline[nread] = '\0';
118 }
119 close(procfd);
120 printf("%s", cmdline);
121 } else {
122 printf("---");
123 }
124 } else {
125 printf("--- ---");
126 }
127 printf("\n");
128}
129
130int main(int argc, char** argv) {
131 char path[PATH_MAX];
132 int fd;
133 char* basename;
134
135 struct service_serial statusbuf;
136
137 for (int i = 1; i < argc; i++) {
138 snprintf(path, sizeof path, "%s/supervise/status", argv[i]);
139 if ((fd = open(path, O_RDONLY)) == -1) {
140 fprintf(stderr, "%s: unable to open supervise/status\n", argv[i]);
141 continue;
142 }
143 if (read(fd, &statusbuf, sizeof statusbuf) != sizeof statusbuf) {
144 fprintf(stderr, "%s: unable to read status\n", argv[i]);
145 continue;
146 }
147 close(fd);
148
149 printstatus(argv[i], &statusbuf);
150 }
151}