951ff58436905546cd32a149798bfadcdaf6d15c
[openafs.git] / src / procmgmt / afskill.c
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
18
19 #include <afs/stds.h>
20
21 #include <stddef.h>
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <errno.h>
25 #include <string.h>
26
27 #include "procmgmt.h"
28
29
30 /* Define NULL-terminated array of signal name/number pairs */
31 typedef struct {
32     char *name;
33     int number;
34 } signal_map_t;
35
36 static signal_map_t signalMap[] = {
37     {"HUP", SIGHUP},
38     {"INT", SIGINT},
39     {"QUIT", SIGQUIT},
40     {"ILL", SIGILL},
41     {"ABRT", SIGABRT},
42     {"FPE", SIGFPE},
43     {"KILL", SIGKILL},
44     {"SEGV", SIGSEGV},
45     {"TERM", SIGTERM},
46     {"USR1", SIGUSR1},
47     {"USR2", SIGUSR2},
48     {"CLD", SIGCLD},
49     {"CHLD", SIGCHLD},
50     {"TSTP", SIGTSTP},
51     {NULL, 0}
52 };
53
54
55 static void
56 PrintSignalList(void)
57 {
58     int i;
59
60     for (i = 0; signalMap[i].name; i++) {
61         printf("%s ", signalMap[i].name);
62     }
63     printf("\n");
64 }
65
66 static int
67 SignalArgToNumber(const char *sigargp)
68 {
69     long signo;
70     char *endp;
71     int i;
72
73     /* check for numeric signal arg */
74     errno = 0;
75     signo = strtol(sigargp, &endp, 0);
76
77     if (errno == 0 && *endp == '\0') {
78         return (int)signo;
79     }
80
81     /* check for named signal arg */
82     for (i = 0; signalMap[i].name; i++) {
83         if (!strcasecmp(signalMap[i].name, sigargp)) {
84             return signalMap[i].number;
85         }
86     }
87
88     return -1;                  /* invalid signal argument */
89 }
90
91
92 static void
93 PrintUsage(const char *whoami)
94 {
95     printf("usage: %s [-signal] [pid] ...\n", whoami);
96     printf("       %s -l\n", whoami);
97 }
98
99
100
101 int
102 main(int argc, char *argv[])
103 {
104     int status = 0;
105     char *whoami;
106
107     /* set whoami to last component of argv[0] */
108     if ((whoami = strrchr(argv[0], '/')) != NULL) {
109         whoami++;
110     } else if ((whoami = strrchr(argv[0], '\\')) != NULL) {
111         whoami++;
112     } else {
113         whoami = argv[0];
114     }
115
116     /* parse command arguments */
117     if (argc <= 1) {
118         /* no arguments; print usage statement */
119         PrintUsage(whoami);
120
121     } else if (!strcmp(argv[1], "-l")) {
122         /* request to print a list of valid signals */
123         PrintSignalList();
124
125     } else {
126         /* request to send a signal */
127         int i;
128         int signo = SIGTERM;    /* SIGTERM is default if no signal specified */
129
130         for (i = 1; i < argc; i++) {
131             char *curargp = argv[i];
132
133             if (i == 1 && *curargp == '-') {
134                 /* signal argument specified; translate to a number */
135                 curargp++;      /* advance past signal flag indicator ('-') */
136
137                 if ((signo = SignalArgToNumber(curargp)) == -1) {
138                     printf("%s: unknown signal %s.\n", whoami, curargp);
139                     PrintUsage(whoami);
140                     status = 1;
141                     break;
142                 }
143             } else {
144                 /* pid specified; send signal */
145                 long pid;
146                 char *endp;
147
148                 errno = 0;
149                 pid = strtol(curargp, &endp, 0);
150
151                 if (errno != 0 || *endp != '\0' || pid <= 0) {
152                     printf("%s: invalid pid value %s.\n", whoami, curargp);
153                     status = 1;
154                 } else {
155                     if (kill((pid_t) pid, signo)) {
156                         if (errno == EINVAL) {
157                             printf("%s: invalid signal number %d.\n", whoami,
158                                    signo);
159                             status = 1;
160                             break;
161
162                         } else if (errno == ESRCH) {
163                             printf("%s: no such process %d.\n", whoami,
164                                    (int)pid);
165                             status = 1;
166
167                         } else if (errno == EPERM) {
168                             printf("%s: no privilege to signal %d.\n", whoami,
169                                    (int)pid);
170                             status = 1;
171
172                         } else {
173                             printf("%s: failed to signal %d (errno = %d).\n",
174                                    whoami, (int)pid, (int)errno);
175                             status = 1;
176                         }
177                     }
178                 }
179             }
180         }
181     }
182
183     return status;
184 }