[BACK]Return to kill.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / bin / kill

Annotation of src/bin/kill/kill.c, Revision 1.30

1.30    ! kre         1: /* $NetBSD: kill.c,v 1.29 2018/10/28 18:26:52 kre Exp $ */
1.10      cgd         2:
1.1       cgd         3: /*
1.7       mycroft     4:  * Copyright (c) 1988, 1993, 1994
                      5:  *     The Regents of the University of California.  All rights reserved.
1.1       cgd         6:  *
                      7:  * Redistribution and use in source and binary forms, with or without
                      8:  * modification, are permitted provided that the following conditions
                      9:  * are met:
                     10:  * 1. Redistributions of source code must retain the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer.
                     12:  * 2. Redistributions in binary form must reproduce the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer in the
                     14:  *    documentation and/or other materials provided with the distribution.
1.23      agc        15:  * 3. Neither the name of the University nor the names of its contributors
1.1       cgd        16:  *    may be used to endorse or promote products derived from this software
                     17:  *    without specific prior written permission.
                     18:  *
                     19:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     20:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     21:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     22:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     23:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     24:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     25:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     26:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     27:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     28:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     29:  * SUCH DAMAGE.
                     30:  */
                     31:
1.13      christos   32: #include <sys/cdefs.h>
1.20      christos   33: #if !defined(lint) && !defined(SHELL)
1.25      lukem      34: __COPYRIGHT("@(#) Copyright (c) 1988, 1993, 1994\
                     35:  The Regents of the University of California.  All rights reserved.");
1.1       cgd        36: #endif /* not lint */
                     37:
                     38: #ifndef lint
1.10      cgd        39: #if 0
1.11      jtc        40: static char sccsid[] = "@(#)kill.c     8.4 (Berkeley) 4/28/95";
1.10      cgd        41: #else
1.30    ! kre        42: __RCSID("$NetBSD: kill.c,v 1.29 2018/10/28 18:26:52 kre Exp $");
1.10      cgd        43: #endif
1.1       cgd        44: #endif /* not lint */
                     45:
1.7       mycroft    46: #include <ctype.h>
                     47: #include <err.h>
                     48: #include <errno.h>
1.1       cgd        49: #include <signal.h>
                     50: #include <stdio.h>
                     51: #include <stdlib.h>
1.26      spz        52: #include <limits.h>
                     53: #include <inttypes.h>
1.1       cgd        54: #include <string.h>
1.20      christos   55: #include <termios.h>
                     56: #include <unistd.h>
                     57: #include <locale.h>
                     58: #include <sys/ioctl.h>
                     59:
                     60: #ifdef SHELL            /* sh (aka ash) builtin */
1.27      joerg      61: int killcmd(int, char *argv[]);
1.20      christos   62: #define main killcmd
                     63: #include "../../bin/sh/bltin/bltin.h"
                     64: #endif /* SHELL */
                     65:
1.28      kre        66: __dead static void nosig(const char *);
1.29      kre        67: void printsignals(FILE *, int);
1.28      kre        68: static int signum(const char *);
                     69: static pid_t processnum(const char *);
1.27      joerg      70: __dead static void usage(void);
1.7       mycroft    71:
                     72: int
1.18      wiz        73: main(int argc, char *argv[])
1.1       cgd        74: {
1.26      spz        75:        int errors;
1.28      kre        76:        int numsig;
                     77:        pid_t pid;
                     78:        const char *sn;
1.1       cgd        79:
1.19      wiz        80:        setprogname(argv[0]);
1.20      christos   81:        setlocale(LC_ALL, "");
1.1       cgd        82:        if (argc < 2)
                     83:                usage();
                     84:
1.4       jtc        85:        numsig = SIGTERM;
1.7       mycroft    86:
1.4       jtc        87:        argc--, argv++;
1.28      kre        88:
                     89:        /*
                     90:         * Process exactly 1 option, if there is one.
                     91:         */
                     92:        if (argv[0][0] == '-') {
                     93:                switch (argv[0][1]) {
                     94:                case 'l':
                     95:                        if (argv[0][2] != '\0')
                     96:                                sn = argv[0] + 2;
                     97:                        else {
                     98:                                argc--; argv++;
                     99:                                sn = argv[0];
                    100:                        }
                    101:                        if (argc > 1)
1.7       mycroft   102:                                usage();
1.28      kre       103:                        if (argc == 1) {
                    104:                                if (isdigit((unsigned char)*sn) == 0)
                    105:                                        usage();
                    106:                                numsig = signum(sn);
                    107:                                if (numsig >= 128)
                    108:                                        numsig -= 128;
                    109:                                if (numsig == 0 || signalnext(numsig) == -1)
                    110:                                        nosig(sn);
                    111:                                sn = signalname(numsig);
                    112:                                if (sn == NULL)
                    113:                                        errx(EXIT_FAILURE,
                    114:                                           "unknown signal number: %d", numsig);
                    115:                                printf("%s\n", sn);
                    116:                                exit(0);
                    117:                        }
1.29      kre       118:                        printsignals(stdout, 0);
1.7       mycroft   119:                        exit(0);
                    120:
1.28      kre       121:                case 's':
                    122:                        if (argv[0][2] != '\0')
                    123:                                sn = argv[0] + 2;
                    124:                        else {
                    125:                                argc--, argv++;
                    126:                                if (argc < 1) {
                    127:                                        warnx(
                    128:                                            "option requires an argument -- s");
                    129:                                        usage();
                    130:                                }
                    131:                                sn = argv[0];
                    132:                        }
                    133:                        if (strcmp(sn, "0") == 0)
                    134:                                numsig = 0;
                    135:                        else if ((numsig = signalnumber(sn)) == 0) {
                    136:                                if (sn != argv[0])
                    137:                                        goto trysignal;
                    138:                                nosig(sn);
                    139:                        }
                    140:                        argc--, argv++;
                    141:                        break;
                    142:
                    143:                case '-':
                    144:                        if (argv[0][2] == '\0') {
                    145:                                /* process this one again later */
                    146:                                break;
                    147:                        }
                    148:                        /* FALL THROUGH */
                    149:                case '\0':
1.4       jtc       150:                        usage();
1.28      kre       151:                        break;
                    152:
                    153:                default:
                    154:  trysignal:
                    155:                        sn = *argv + 1;
                    156:                        if (((numsig = signalnumber(sn)) == 0)) {
                    157:                                if (isdigit((unsigned char)*sn))
                    158:                                        numsig = signum(sn);
                    159:                                else
                    160:                                        nosig(sn);
1.22      jschauma  161:                        }
1.28      kre       162:
                    163:                        if (numsig != 0 && signalnext(numsig) == -1)
1.24      christos  164:                                nosig(sn);
1.28      kre       165:                        argc--, argv++;
                    166:                        break;
                    167:                }
                    168:        }
                    169:
                    170:        /* deal with the optional '--' end of options option */
                    171:        if (argc > 0 && strcmp(*argv, "--") == 0)
1.7       mycroft   172:                argc--, argv++;
1.1       cgd       173:
1.7       mycroft   174:        if (argc == 0)
1.1       cgd       175:                usage();
                    176:
1.7       mycroft   177:        for (errors = 0; argc; argc--, argv++) {
1.20      christos  178: #ifdef SHELL
                    179:                extern int getjobpgrp(const char *);
                    180:                if (*argv[0] == '%') {
                    181:                        pid = getjobpgrp(*argv);
                    182:                        if (pid == 0) {
                    183:                                warnx("illegal job id: %s", *argv);
                    184:                                errors = 1;
                    185:                                continue;
                    186:                        }
                    187:                } else
                    188: #endif
1.28      kre       189:                        if ((pid = processnum(*argv)) == (pid_t)-1) {
1.20      christos  190:                                errors = 1;
                    191:                                continue;
                    192:                        }
1.28      kre       193:
                    194:                if (kill(pid, numsig) == -1) {
1.7       mycroft   195:                        warn("%s", *argv);
1.1       cgd       196:                        errors = 1;
                    197:                }
1.21      christos  198: #ifdef SHELL
1.28      kre       199:                /*
                    200:                 * Wakeup the process if it was suspended, so it can
                    201:                 * exit without an explicit 'fg'.
                    202:                 *      (kernel handles this for SIGKILL)
                    203:                 */
1.21      christos  204:                if (numsig == SIGTERM || numsig == SIGHUP)
1.28      kre       205:                        kill(pid, SIGCONT);
1.21      christos  206: #endif
1.1       cgd       207:        }
1.7       mycroft   208:
1.1       cgd       209:        exit(errors);
1.14      mycroft   210:        /* NOTREACHED */
1.1       cgd       211: }
                    212:
1.20      christos  213: static int
1.28      kre       214: signum(const char *sn)
                    215: {
                    216:        intmax_t n;
                    217:        char *ep;
                    218:
                    219:        n = strtoimax(sn, &ep, 10);
                    220:
                    221:        /* check for correctly parsed number */
                    222:        if (*ep || n <= INT_MIN || n >= INT_MAX )
                    223:                errx(EXIT_FAILURE, "illegal signal number: %s", sn);
                    224:                /* NOTREACHED */
                    225:
                    226:        return (int)n;
                    227: }
                    228:
                    229: static pid_t
                    230: processnum(const char *s)
1.4       jtc       231: {
1.28      kre       232:        intmax_t n;
                    233:        char *ep;
                    234:
                    235:        n = strtoimax(s, &ep, 10);
1.4       jtc       236:
1.28      kre       237:        /* check for correctly parsed number */
                    238:        if (*ep || n == INTMAX_MIN || n == INTMAX_MAX || (pid_t)n != n ||
                    239:            n == -1) {
                    240:                warnx("illegal process%s id: %s", (n < 0 ? " group" : ""), s);
                    241:                n = -1;
1.4       jtc       242:        }
1.28      kre       243:
                    244:        return (pid_t)n;
1.4       jtc       245: }
                    246:
1.20      christos  247: static void
1.28      kre       248: nosig(const char *name)
1.1       cgd       249: {
1.7       mycroft   250:
                    251:        warnx("unknown signal %s; valid signals:", name);
1.29      kre       252:        printsignals(stderr, 0);
1.1       cgd       253:        exit(1);
1.15      mycroft   254:        /* NOTREACHED */
1.1       cgd       255: }
                    256:
1.30    ! kre       257: #ifndef SHELL
1.29      kre       258: /*
                    259:  * Print the names of all the signals (neatly) to fp
                    260:  * "len" gives the number of chars already printed to
                    261:  * the current output line (in kill.c, always 0)
                    262:  */
                    263: void
                    264: printsignals(FILE *fp, int len)
1.1       cgd       265: {
1.20      christos  266:        int sig;
1.29      kre       267:        int nl, pad;
1.20      christos  268:        const char *name;
                    269:        int termwidth = 80;
                    270:
1.28      kre       271:        if ((name = getenv("COLUMNS")) != 0)
                    272:                termwidth = atoi(name);
                    273:        else if (isatty(fileno(fp))) {
1.20      christos  274:                struct winsize win;
1.28      kre       275:
1.20      christos  276:                if (ioctl(fileno(fp), TIOCGWINSZ, &win) == 0 && win.ws_col > 0)
                    277:                        termwidth = win.ws_col;
                    278:        }
1.1       cgd       279:
1.29      kre       280:        pad = (len | 7) + 1 - len;
                    281:
                    282:        for (sig = 0; (sig = signalnext(sig)) != 0; ) {
1.28      kre       283:                name = signalname(sig);
                    284:                if (name == NULL)
                    285:                        continue;
                    286:
                    287:                nl = strlen(name);
1.20      christos  288:
1.28      kre       289:                if (len > 0 && nl + len + pad >= termwidth) {
1.20      christos  290:                        fprintf(fp, "\n");
                    291:                        len = 0;
1.28      kre       292:                        pad = 0;
                    293:                } else if (pad > 0 && len != 0)
                    294:                        fprintf(fp, "%*s", pad, "");
                    295:                else
                    296:                        pad = 0;
                    297:
                    298:                len += nl + pad;
                    299:                pad = (nl | 7) + 1 - nl;
                    300:
1.20      christos  301:                fprintf(fp, "%s", name);
1.7       mycroft   302:        }
1.20      christos  303:        if (len != 0)
                    304:                fprintf(fp, "\n");
1.1       cgd       305: }
1.30    ! kre       306: #endif
1.1       cgd       307:
1.20      christos  308: static void
1.18      wiz       309: usage(void)
1.1       cgd       310: {
1.28      kre       311:        const char *pn = getprogname();
1.7       mycroft   312:
1.20      christos  313:        fprintf(stderr, "usage: %s [-s signal_name] pid ...\n"
1.28      kre       314:                        "       %s -l [exit_status]\n"
                    315:                        "       %s -signal_name pid ...\n"
                    316:                        "       %s -signal_number pid ...\n",
                    317:            pn, pn, pn, pn);
1.1       cgd       318:        exit(1);
1.15      mycroft   319:        /* NOTREACHED */
1.1       cgd       320: }

CVSweb <webmaster@jp.NetBSD.org>