psvstat.c (3642B)
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 10 struct 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 20 void 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 130 int 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 }