after.c (2981B)
1 #include <sys/types.h> 2 #include <sys/sysctl.h> 3 4 #include <err.h> 5 #include <fcntl.h> 6 #include <kvm.h> 7 #include <limits.h> 8 #include <stdio.h> 9 #include <stdlib.h> 10 #include <string.h> 11 #include <unistd.h> 12 13 int verbose; 14 15 void 16 usage(void) 17 { 18 fprintf(stderr, "usage: %s [-h] [-v] [-p pid | -n process_name] -e string\n", 19 getprogname()); 20 } 21 22 void 23 debug_print(const char *message) 24 { 25 if (verbose) 26 fprintf(stderr, "%s: %s\n", getprogname(), message); 27 } 28 29 30 int 31 pid_is_in(int pid, struct kinfo_proc **kinfo, int entries) 32 { 33 int i; 34 for (i = 0; i < entries; i++) { 35 if (kinfo[i]->p_pid == pid) 36 return 1; 37 } 38 return 0; 39 } 40 41 int 42 pname_is_in(char *pname, struct kinfo_proc **kinfo, int entries) 43 { 44 int i; 45 for (i = 0; i < entries; i++) { 46 if (strcmp(kinfo[i]->p_comm, pname) == 0) 47 return 1; 48 } 49 return 0; 50 } 51 52 void 53 update_proc_list(struct kinfo_proc ***kinfo, kvm_t *kd, int *entries) 54 { 55 int i; 56 struct kinfo_proc *kp; 57 58 kp = kvm_getprocs(kd, KERN_PROC_ALL, 0, sizeof(*kp), entries); 59 if (kp == NULL) 60 errx(1, "%s", kvm_geterr(kd)); 61 62 if (((*kinfo) = reallocarray((*kinfo), *entries, sizeof(*(*kinfo)))) == NULL) 63 err(1, "failed to allocate memory for proc pointers"); 64 65 for (i = 0; i < *entries; i++) 66 (*kinfo)[i] = &kp[i]; 67 } 68 69 int 70 main(int argc, char **argv) 71 { 72 int i, ch, entries; 73 int pid = 0; 74 int found = 0; 75 char *pname = NULL, *string = NULL; 76 char errbuf[_POSIX2_LINE_MAX]; 77 78 kvm_t *kd; 79 struct kinfo_proc **kinfo = NULL; 80 81 verbose = 0; 82 83 if (pledge("stdio ps", NULL) == -1) 84 err(1, "pledge"); 85 86 // argument parsing... 87 while((ch = getopt(argc, argv, "e:hn:p:v")) != -1) 88 switch(ch) { 89 case 'e': 90 string = optarg; 91 break; 92 case 'n': 93 pname = optarg; 94 break; 95 case 'p': 96 sscanf(optarg, "%d", &pid); 97 break; 98 case 'v': 99 verbose = 1; 100 break; 101 case 'h': 102 usage(); 103 return 0; 104 default: 105 usage(); 106 exit(1); 107 } 108 109 // argument checking... 110 // show usage if neither a pid nor a pname are given 111 if (!(pname != NULL || pid != 0)) { 112 usage(); 113 exit(1); 114 } 115 // show usage if no output string is given 116 if (string == NULL) { 117 usage(); 118 exit(1); 119 } 120 121 // initialise virtual memory access 122 kd = kvm_openfiles(NULL, NULL, NULL, KVM_NO_FILES, errbuf); 123 if (kd == NULL) 124 errx(1, "%s", errbuf); 125 126 // get initial process list 127 update_proc_list(&kinfo, kd, &entries); 128 129 // if a process name is given use that function, otherwise use pid function 130 while ( 131 (pname != NULL) 132 ? pname_is_in(pname, kinfo, entries) 133 : pid_is_in(pid, kinfo, entries) 134 ) { 135 found = 1; // mark the process as existing 136 update_proc_list(&kinfo, kd, &entries); 137 debug_print("waiting..."); 138 sleep(1); 139 } 140 141 // free kinfo and close off access to kernel vmem 142 free(kinfo); 143 int kd_error; 144 if ((kd_error = kvm_close(kd)) < 0) { 145 errx(1, "failed to close kernel memory descriptor (%d)", kd_error); 146 } 147 148 // if the process existed at some stage 149 if (found) { 150 debug_print("process died."); 151 printf("%s\n", string); 152 } else { 153 errx(1, "process not in process list."); 154 } 155 156 return 0; 157 }