~ubuntu-branches/ubuntu/karmic/sysvinit/karmic-updates

« back to all changes in this revision

Viewing changes to src/killall5.c

  • Committer: Bazaar Package Importer
  • Author(s): Scott James Remnant
  • Date: 2009-09-07 19:56:53 UTC
  • mfrom: (1.1.4 upstream) (2.1.7 sid)
  • Revision ID: james.westby@ubuntu.com-20090907195653-2i6t0j91wfbf1f0d
Tags: 2.87dsf-4ubuntu1
* Merge from debian unstable, remaining changes:
  - Support Cell processor:
    + debian/initscripts/postinst: Create spu system group and /spu mount
      point if we are running on a Cell processor.
    + debian/initscripts/etc/init.d/mountkernfs.sh: Mount spufs if Cell
      processor is detected.
    + debian/initscripts/lib/init/mount-functions.sh: Modprobe spufs
      if not available.
    + debian/control: Add initscripts dependency 'passwd' for groupadd.
    (Forwarded to Debian #483399)
  - Use tmpfs mounts for /var/lock and /var/run:
    + debian/initscripts/share/default.rcS: Enable RAMRUN and RAMLOCK by
      default.
    + debian/initscripts.postinst: Enable RAMRUN and RAMLOCK in
      /etc/default/rcS on upgrades. This needs to be kept until the next
      LTS.
    + debian/initscripts/etc/init.d/mountkernfs.sh: Propagate files from the
      initramfs to our new /var/run, so that we can populate
      /var/run/sendsigs.omit from initramfs.
  - Boot ordering differences:
    + mountkernfs.sh: 02 -> 01
    + mountdevsubfs.sh: 04 -> 11
    + bootlogd: disabled by default
    + checkroot.sh: 10 -> 20
    + mtab.sh: 12 -> 22
  - debian/patches/91_sulogin_lockedpw.dpatch: Disable "root account is
    locked" warning, since this is the default in Ubuntu. Document this in
    sulogin.8.
  - debian/control: Drop Essential: yes from packages since we use Upstart.
  - debian/control: Conflict/Replace sysvconfig which has also previously
    provided service(8).
  - debian/control, debian/rules: Previous name for sysvinit-utils was
    'sysvutils' in Ubuntu, so Conflict/Replace/Provide it. Also create a
    dummy sysvutils package, since Hardy has reverse versioned dependencies
    to it. This needs to be kept until after the next LTS.
  - debian/control: Depend on lsb-base (>= 3.2-14) for status_of_proc()
    function.
  - debian/initscripts/etc/init.d/checkfs.sh: Don't depend on hwclockfirst
    which Ubuntu does not have.
  - debian/initscripts/etc/init.d/mountkernfs.sh: Always mount devpts, and
    do not touch /dev/ptmx (which is already managed by udev).
  - debian/initscripts/etc/init.d/mountkernfs.sh: mount fusectl if it is
    available
  - debian/initscripts/etc/init.d/mountkernfs.sh: mount securityfs if it is
    available. This allows for easier AppArmor confinement of applications
    early in the boot process. LP: #399954
  - debian/initscripts/etc/init.d/mountkernfs.sh: mount debugfs if it is
    available.
  - debian/initscripts/etc/init.d/ondemand: Sleep for 60 seconds, then
    set CPU Frequency Scaling governor to "ondemand".   LP: #341573.
  - debian/initscripts/etc/init.d/umountfs: Don't unmount filesystems
    that precede root or use force for some mountpoints.
  - debian/initscripts/etc/network/if-up.d/mountnfs: Rename ifstate
    file to /var/run/network/ifstate
  - ./debian/initscripts/lib/init/usplash-fsck-functions.sh: Use blkid,
    vol_id is gone.
  - debian/initscripts.{pre,postinst}: waitnfs.sh -> mountnfs.sh renaming
    transition. This needs to be kept until after the next LTS.

LP: #32455, #94120, #160197, #382097 (amongst others).

* debian/sysv-rc/sbin/update-rc.d: Dropped support for "multiuser"
  command-line option.
* debian/rules: Compat symlink from /usr/bin/service to /usr/sbin/service
* debian/initscripts.postinst: Transition from bootlogs.sh to bootlogs

* debian/sysv-rc.postinst: Don't try and use insserv by default, though
  everything's in place for you to try if you like.  It can be activated
  with:
      USEINSSERV=yes dpkg-reconfigure sysv-rc

Show diffs side-by-side

added added

removed removed

Lines of Context:
40
40
#include <syslog.h>
41
41
#include <getopt.h>
42
42
#include <stdarg.h>
 
43
#include <sys/mman.h>
43
44
 
44
45
char *Version = "@(#)killall5 2.86 31-Jul-2004 miquels@cistron.nl";
45
46
 
46
47
#define STATNAMELEN     15
 
48
#define DO_STAT 1
 
49
#define NO_STAT 0
47
50
 
48
51
/* Info about a process. */
49
52
typedef struct proc {
165
168
 
166
169
/*
167
170
 *      Read the proc filesystem.
 
171
 *      CWD must be /proc to avoid problems if / is affected by the killing (ie depend on fuse).
168
172
 */
169
 
int readproc()
 
173
int readproc(int do_stat)
170
174
{
171
175
        DIR             *dir;
172
176
        FILE            *fp;
180
184
        int             pid, f;
181
185
 
182
186
        /* Open the /proc directory. */
183
 
        if ((dir = opendir("/proc")) == NULL) {
 
187
        if (chdir("/proc") == -1) {
 
188
                nsyslog(LOG_ERR, "chdir /proc failed");
 
189
                return -1;
 
190
        }
 
191
        if ((dir = opendir(".")) == NULL) {
184
192
                nsyslog(LOG_ERR, "cannot opendir(/proc)");
185
193
                return -1;
186
194
        }
206
214
                memset(p, 0, sizeof(PROC));
207
215
 
208
216
                /* Open the status file. */
209
 
                snprintf(path, sizeof(path), "/proc/%s/stat", d->d_name);
 
217
                snprintf(path, sizeof(path), "%s/stat", d->d_name);
210
218
 
211
219
                /* Read SID & statname from it. */
212
 
                if ((fp = fopen(path, "r")) != NULL) {
 
220
                if ((fp = fopen(path, "r")) != NULL) {
213
221
                        buf[0] = 0;
214
222
                        fgets(buf, sizeof(buf), fp);
215
223
 
223
231
                                if (q == NULL) {
224
232
                                        p->sid = 0;
225
233
                                        nsyslog(LOG_ERR,
226
 
                                        "can't get program name from %s\n",
 
234
                                        "can't get program name from /proc/%s\n",
227
235
                                                path);
228
236
                                        free(p);
229
237
                                        continue;
260
268
                        continue;
261
269
                }
262
270
 
263
 
                snprintf(path, sizeof(path), "/proc/%s/cmdline", d->d_name);
 
271
                snprintf(path, sizeof(path), "%s/cmdline", d->d_name);
264
272
                if ((fp = fopen(path, "r")) != NULL) {
265
273
 
266
274
                        /* Now read argv[0] */
306
314
 
307
315
                /* Try to stat the executable. */
308
316
                snprintf(path, sizeof(path), "/proc/%s/exe", d->d_name);
309
 
                if (stat(path, &st) == 0) {
 
317
                if (do_stat && stat(path, &st) == 0) {
310
318
                        p->dev = st.st_dev;
311
319
                        p->ino = st.st_ino;
312
320
                }
378
386
        int             foundone = 0;
379
387
        int             ok = 0;
380
388
 
381
 
        /* Try to stat the executable. */
382
 
        if (prog[0] == '/' && stat(prog, &st) == 0) dostat++;
 
389
        if (! prog)
 
390
                return NULL;
383
391
 
384
392
        /* Get basename of program. */
385
393
        if ((s = strrchr(prog, '/')) == NULL)
387
395
        else
388
396
                s++;
389
397
 
 
398
        if (! *s)
 
399
                return NULL;
 
400
 
390
401
        q = (PIDQ_HEAD *)xmalloc(sizeof(PIDQ_HEAD));
391
402
        q = init_pid_q(q);
392
403
 
 
404
        /* Try to stat the executable. */
 
405
        if (prog[0] == '/' && stat(prog, &st) == 0)
 
406
                dostat++;
 
407
 
393
408
        /* First try to find a match based on dev/ino pair. */
394
409
        if (dostat) {
395
410
                for (p = plist; p; p = p->next) {
404
419
        if (!foundone) for (p = plist; p; p = p->next) {
405
420
                ok = 0;
406
421
 
407
 
                /* Compare name (both basename and full path) */
408
 
                ok += (p->argv0 && strcmp(p->argv0, prog) == 0);
409
 
                ok += (p->argv0 && strcmp(p->argv0base, s) == 0);
 
422
                /*             matching        nonmatching
 
423
                 * proc name   prog name       prog name
 
424
                 * ---         -----------     ------------
 
425
                 *   b         b, p/b, q/b
 
426
                 * p/b         b, p/b          q/b
 
427
                 *
 
428
                 * Algorithm: Match if:
 
429
                 *    cmd = arg
 
430
                 * or cmd = base(arg)
 
431
                 * or base(cmd) = arg
 
432
                 *
 
433
                 * Specifically, do not match just because base(cmd) = base(arg)
 
434
                 * as was done in earlier versions of this program, since this
 
435
                 * allows /aaa/foo to match /bbb/foo .
 
436
                 */
 
437
                ok |=
 
438
                        (p->argv0 && strcmp(p->argv0, prog) == 0)
 
439
                        || (p->argv0 && s != prog && strcmp(p->argv0, s) == 0)
 
440
                        || (p->argv0base && strcmp(p->argv0base, prog) == 0);
410
441
 
411
442
                /* For scripts, compare argv[1] as well. */
412
 
                if (scripts_too && p->argv1 &&
413
 
                    !strncmp(p->statname, p->argv1base, STATNAMELEN)) {
414
 
                        ok += (strcmp(p->argv1, prog) == 0);
415
 
                        ok += (strcmp(p->argv1base, s) == 0);
 
443
                if (
 
444
                        scripts_too && p->statname && p->argv1base
 
445
                        && !strncmp(p->statname, p->argv1base, STATNAMELEN)
 
446
                ) {
 
447
                        ok |=
 
448
                                (p->argv1 && strcmp(p->argv1, prog) == 0)
 
449
                                || (p->argv1 && s != prog && strcmp(p->argv1, s) == 0)
 
450
                                || (p->argv1base && strcmp(p->argv1base, prog) == 0);
416
451
                }
417
452
 
418
453
                /*
423
458
                    (p->argv0 == NULL ||
424
459
                     p->argv0[0] == 0 ||
425
460
                     strchr(p->argv0, ' '))) {
426
 
                        ok += (strcmp(p->statname, s) == 0);
 
461
                        ok |= (strcmp(p->statname, s) == 0);
427
462
                }
428
463
                if (ok) add_pid_to_q(q, p);
429
464
        }
476
511
        int             f;
477
512
        int             first = 1;
478
513
        int             i, oind, opt, flags = 0;
 
514
        int             chroot_check = 0;
 
515
        struct stat     st;
 
516
        char            tmp[512];
479
517
 
480
518
        for (oind = PIDOF_OMITSZ-1; oind > 0; oind--)
481
519
                opid[oind] = 0;
482
520
        opterr = 0;
483
521
 
484
 
        while ((opt = getopt(argc,argv,"ho:sx")) != EOF) switch (opt) {
 
522
        while ((opt = getopt(argc,argv,"hco:sx")) != EOF) switch (opt) {
485
523
                case '?':
486
524
                        nsyslog(LOG_ERR,"invalid options on command line!\n");
487
525
                        closelog();
488
526
                        exit(1);
 
527
                case 'c':
 
528
                        if (geteuid() == 0) chroot_check = 1;
 
529
                        break;
489
530
                case 'o':
490
531
                        if (oind >= PIDOF_OMITSZ -1) {
491
532
                                nsyslog(LOG_ERR,"omit pid buffer size %d "
518
559
        argc -= optind;
519
560
        argv += optind;
520
561
 
 
562
        /* Check if we are in a chroot */
 
563
        if (chroot_check) {
 
564
                snprintf(tmp, 512, "/proc/%d/root", getpid());
 
565
                if (stat(tmp, &st) < 0) {
 
566
                        nsyslog(LOG_ERR, "stat failed for %s!\n", tmp);
 
567
                        closelog();
 
568
                        exit(1);
 
569
                }
 
570
        }
 
571
 
521
572
        /* Print out process-ID's one by one. */
522
 
        readproc();
 
573
        readproc(DO_STAT);
523
574
        for(f = 0; f < argc; f++) {
524
575
                if ((q = pidof(argv[f])) != NULL) {
525
576
                        spid = 0;
541
592
                                        else
542
593
                                                spid = 1;
543
594
                                }
 
595
                                if (chroot_check) {
 
596
                                        struct stat st2;
 
597
                                        snprintf(tmp, 512, "/proc/%d/root",
 
598
                                                 p->pid);
 
599
                                        if (stat(tmp, &st2) < 0 ||
 
600
                                            st.st_dev != st2.st_dev ||
 
601
                                            st.st_ino != st2.st_ino) {
 
602
                                                continue;
 
603
                                        }
 
604
                                }
544
605
                                if (!first)
545
606
                                        printf(" ");
546
607
                                printf("%d", p->pid);
548
609
                        }
549
610
                }
550
611
        }
551
 
        printf("\n");
 
612
        if (!first)
 
613
                printf("\n");
552
614
        closelog();
553
615
        return(first ? 1 : 0);
554
616
}
555
617
 
556
618
 
557
619
 
 
620
#define KILLALL_OMITSZ  16
 
621
 
558
622
/* Main for either killall or pidof. */
559
623
int main(int argc, char **argv)
560
624
{
561
625
        PROC            *p;
562
626
        int             pid, sid = -1;
 
627
        pid_t           opid[KILLALL_OMITSZ];
 
628
        int             i, oind, omit = 0;
563
629
        int             sig = SIGKILL;
564
630
 
 
631
        /* return non-zero if no process was killed */
 
632
        int             retval = 2;
 
633
 
565
634
        /* Get program name. */
566
635
        if ((progname = strrchr(argv[0], '/')) == NULL)
567
636
                progname = argv[0];
576
645
                return main_pidof(argc, argv);
577
646
 
578
647
        /* Right, so we are "killall". */
 
648
        for (oind = KILLALL_OMITSZ-1; oind > 0; oind--)
 
649
                opid[oind] = 0;
 
650
 
579
651
        if (argc > 1) {
580
 
                if (argc != 2) usage();
581
 
                if (argv[1][0] == '-') (argv[1])++;
582
 
                if ((sig = atoi(argv[1])) <= 0 || sig > 31) usage();
 
652
                for (i = 1; i < argc; i++) {
 
653
                        if (argv[i][0] == '-') (argv[i])++;
 
654
                        if (argv[i][0] == 'o') {
 
655
                                if (++i >= argc) usage();
 
656
                                if (oind >= KILLALL_OMITSZ -1) {
 
657
                                        nsyslog(LOG_ERR,"omit pid buffer size "
 
658
                                                "%d exceeded!\n",
 
659
                                                KILLALL_OMITSZ);
 
660
                                        closelog();
 
661
                                        exit(1);
 
662
                                }
 
663
                                if ((opid[oind] = atoi(argv[i])) < 1) {
 
664
                                        nsyslog(LOG_ERR,
 
665
                                                "illegal omit pid value "
 
666
                                                "(%s)!\n", argv[i]);
 
667
                                        closelog();
 
668
                                        exit(1);
 
669
                                }
 
670
                                oind++;
 
671
                                omit = 1;
 
672
                        }
 
673
                        else if ((sig = atoi(argv[1])) <= 0 || sig > 31)
 
674
                                usage();
 
675
                }
583
676
        }
584
677
 
585
678
        /* First get the /proc filesystem online. */
595
688
        signal(SIGSTOP, SIG_IGN);
596
689
        signal(SIGKILL, SIG_IGN);
597
690
 
 
691
        /* lock us into memory */
 
692
        mlockall(MCL_CURRENT | MCL_FUTURE);
 
693
 
598
694
        /* Now stop all processes. */
599
695
        kill(-1, SIGSTOP);
600
696
        sent_sigstop = 1;
601
697
 
602
698
        /* Read /proc filesystem */
603
 
        if (readproc() < 0) {
 
699
        if (readproc(NO_STAT) < 0) {
604
700
                kill(-1, SIGCONT);
605
 
                exit(1);
 
701
                return(1);
606
702
        }
607
703
 
608
 
        /* Now kill all processes except our session. */
 
704
        /* Now kill all processes except init (pid 1) and our session. */
609
705
        sid = (int)getsid(0);
610
706
        pid = (int)getpid();
611
 
        for (p = plist; p; p = p->next)
612
 
                if (p->pid != pid && p->sid != sid && !p->kernel)
613
 
                        kill(p->pid, sig);
 
707
        for (p = plist; p; p = p->next) {
 
708
                if (p->pid == 1 || p->pid == pid || p->sid == sid || p->kernel)
 
709
                        continue;
 
710
                if (omit) {
 
711
                        for (i = 0; i < oind; i++)
 
712
                                if (opid[i] == p->pid)
 
713
                                        break;
 
714
                        /* On a match, continue with the for loop above. */
 
715
                        if (i < oind)
 
716
                                continue;
 
717
                }
 
718
                kill(p->pid, sig);
 
719
                retval = 0;
 
720
        }
614
721
 
615
722
        /* And let them continue. */
616
723
        kill(-1, SIGCONT);
618
725
        /* Done. */
619
726
        closelog();
620
727
 
621
 
        return 0;
 
728
        /* Force the kernel to run the scheduler */
 
729
        usleep(1);
 
730
 
 
731
        return retval;
622
732
}