| 1 | /* |
| 2 | * Copyright 2000, International Business Machines Corporation and others. |
| 3 | * All Rights Reserved. |
| 4 | * |
| 5 | * This software has been released under the terms of the IBM Public |
| 6 | * License. For details, see the LICENSE file in the top-level source |
| 7 | * directory or online at http://www.openafs.org/dl/license10.html |
| 8 | */ |
| 9 | |
| 10 | /* Kill command based on process management library (procmgmt.h). |
| 11 | * Intended for use on Windows NT, where it will only signal processes |
| 12 | * linked with the process management library (except SIGKILL). |
| 13 | */ |
| 14 | |
| 15 | #include <afsconfig.h> |
| 16 | #include <afs/param.h> |
| 17 | #include <afs/stds.h> |
| 18 | |
| 19 | #include "procmgmt.h" |
| 20 | |
| 21 | #include <roken.h> |
| 22 | |
| 23 | /* Define NULL-terminated array of signal name/number pairs */ |
| 24 | typedef struct { |
| 25 | char *name; |
| 26 | int number; |
| 27 | } signal_map_t; |
| 28 | |
| 29 | static signal_map_t signalMap[] = { |
| 30 | {"HUP", SIGHUP}, |
| 31 | {"INT", SIGINT}, |
| 32 | {"QUIT", SIGQUIT}, |
| 33 | {"ILL", SIGILL}, |
| 34 | {"ABRT", SIGABRT}, |
| 35 | {"FPE", SIGFPE}, |
| 36 | {"KILL", SIGKILL}, |
| 37 | {"SEGV", SIGSEGV}, |
| 38 | {"TERM", SIGTERM}, |
| 39 | {"USR1", SIGUSR1}, |
| 40 | {"USR2", SIGUSR2}, |
| 41 | {"CLD", SIGCLD}, |
| 42 | {"CHLD", SIGCHLD}, |
| 43 | {"TSTP", SIGTSTP}, |
| 44 | {NULL, 0} |
| 45 | }; |
| 46 | |
| 47 | |
| 48 | static void |
| 49 | PrintSignalList(void) |
| 50 | { |
| 51 | int i; |
| 52 | |
| 53 | for (i = 0; signalMap[i].name; i++) { |
| 54 | printf("%s ", signalMap[i].name); |
| 55 | } |
| 56 | printf("\n"); |
| 57 | } |
| 58 | |
| 59 | static int |
| 60 | SignalArgToNumber(const char *sigargp) |
| 61 | { |
| 62 | long signo; |
| 63 | char *endp; |
| 64 | int i; |
| 65 | |
| 66 | /* check for numeric signal arg */ |
| 67 | errno = 0; |
| 68 | signo = strtol(sigargp, &endp, 0); |
| 69 | |
| 70 | if (errno == 0 && *endp == '\0') { |
| 71 | return (int)signo; |
| 72 | } |
| 73 | |
| 74 | /* check for named signal arg */ |
| 75 | for (i = 0; signalMap[i].name; i++) { |
| 76 | if (!strcasecmp(signalMap[i].name, sigargp)) { |
| 77 | return signalMap[i].number; |
| 78 | } |
| 79 | } |
| 80 | |
| 81 | return -1; /* invalid signal argument */ |
| 82 | } |
| 83 | |
| 84 | |
| 85 | static void |
| 86 | PrintUsage(const char *whoami) |
| 87 | { |
| 88 | printf("usage: %s [-signal] [pid] ...\n", whoami); |
| 89 | printf(" %s -l\n", whoami); |
| 90 | } |
| 91 | |
| 92 | |
| 93 | |
| 94 | int |
| 95 | main(int argc, char *argv[]) |
| 96 | { |
| 97 | int status = 0; |
| 98 | char *whoami; |
| 99 | |
| 100 | /* set whoami to last component of argv[0] */ |
| 101 | if ((whoami = strrchr(argv[0], '/')) != NULL) { |
| 102 | whoami++; |
| 103 | } else if ((whoami = strrchr(argv[0], '\\')) != NULL) { |
| 104 | whoami++; |
| 105 | } else { |
| 106 | whoami = argv[0]; |
| 107 | } |
| 108 | |
| 109 | /* parse command arguments */ |
| 110 | if (argc <= 1) { |
| 111 | /* no arguments; print usage statement */ |
| 112 | PrintUsage(whoami); |
| 113 | |
| 114 | } else if (!strcmp(argv[1], "-l")) { |
| 115 | /* request to print a list of valid signals */ |
| 116 | PrintSignalList(); |
| 117 | |
| 118 | } else { |
| 119 | /* request to send a signal */ |
| 120 | int i; |
| 121 | int signo = SIGTERM; /* SIGTERM is default if no signal specified */ |
| 122 | |
| 123 | for (i = 1; i < argc; i++) { |
| 124 | char *curargp = argv[i]; |
| 125 | |
| 126 | if (i == 1 && *curargp == '-') { |
| 127 | /* signal argument specified; translate to a number */ |
| 128 | curargp++; /* advance past signal flag indicator ('-') */ |
| 129 | |
| 130 | if ((signo = SignalArgToNumber(curargp)) == -1) { |
| 131 | printf("%s: unknown signal %s.\n", whoami, curargp); |
| 132 | PrintUsage(whoami); |
| 133 | status = 1; |
| 134 | break; |
| 135 | } |
| 136 | } else { |
| 137 | /* pid specified; send signal */ |
| 138 | long pid; |
| 139 | char *endp; |
| 140 | |
| 141 | errno = 0; |
| 142 | pid = strtol(curargp, &endp, 0); |
| 143 | |
| 144 | if (errno != 0 || *endp != '\0' || pid <= 0) { |
| 145 | printf("%s: invalid pid value %s.\n", whoami, curargp); |
| 146 | status = 1; |
| 147 | } else { |
| 148 | if (kill((pid_t) pid, signo)) { |
| 149 | if (errno == EINVAL) { |
| 150 | printf("%s: invalid signal number %d.\n", whoami, |
| 151 | signo); |
| 152 | status = 1; |
| 153 | break; |
| 154 | |
| 155 | } else if (errno == ESRCH) { |
| 156 | printf("%s: no such process %d.\n", whoami, |
| 157 | (int)pid); |
| 158 | status = 1; |
| 159 | |
| 160 | } else if (errno == EPERM) { |
| 161 | printf("%s: no privilege to signal %d.\n", whoami, |
| 162 | (int)pid); |
| 163 | status = 1; |
| 164 | |
| 165 | } else { |
| 166 | printf("%s: failed to signal %d (errno = %d).\n", |
| 167 | whoami, (int)pid, (int)errno); |
| 168 | status = 1; |
| 169 | } |
| 170 | } |
| 171 | } |
| 172 | } |
| 173 | } |
| 174 | } |
| 175 | |
| 176 | return status; |
| 177 | } |