~ubuntu-branches/ubuntu/saucy/psmisc/saucy

« back to all changes in this revision

Viewing changes to src/fuser.c

  • Committer: Bazaar Package Importer
  • Author(s): Craig Small
  • Date: 2010-01-04 21:43:16 UTC
  • mfrom: (1.1.11 upstream) (2.1.5 squeeze)
  • Revision ID: james.westby@ubuntu.com-20100104214316-rcesro80k1zmz03e
Tags: 22.10-1
* New upstream release
  - fuser -k -m ... won't kill itself Closes: #562767
  - fuser -NAME fixed Closes: #563388
  - Reversed normal file fuser -k check Closes: #563387

Show diffs side-by-side

added added

removed removed

Lines of Context:
4
4
 * Based on fuser.c Copyright (C) 1993-2005 Werner Almesberger and Craig Small
5
5
 *
6
6
 * Completely re-written
7
 
 * Copyright (C) 2005-2009 Craig Small
 
7
 * Copyright (C) 2005-2010 Craig Small
8
8
 *
9
9
 * This program is free software; you can redistribute it and/or modify
10
10
 * it under the terms of the GNU General Public License as published by
102
102
 
103
103
        fprintf(stderr,
104
104
                _
105
 
                ("Usage: fuser [ -fuv ] [ -a | -s ] [ -4 | -6 ] [ -c | -m | -n SPACE ] [ -k [ -i ] [ -SIGNAL ]] NAME...\n"
 
105
                ("Usage: fuser [-fMuv] [-a|-s] [-4|-6] [-c|-m|-n SPACE] [-k [-i] [-SIGNAL]] NAME...\n"
106
106
                 "       fuser -l\n" "       fuser -V\n"
107
107
                 "Show which processes use the named files, sockets, or filesystems.\n\n"
108
 
                 "    -a        display unused files too\n"
109
 
                 "    -c        Same as -m (for POSIX compatibility)\n"
110
 
                 "    -f        silently ignored (for POSIX compatibility)\n"
111
 
                 "    -i        ask before killing (ignored without -k)\n"
112
 
                 "    -k        kill processes accessing the named file\n"
113
 
                 "    -l        list available signal names\n"
114
 
                 "    -m        show all processes using the named filesystems or block device\n"
115
 
                 "    -n SPACE  search in this name space (file, udp, or tcp)\n"
116
 
                 "    -s        silent operation\n"
117
 
                 "    -SIGNAL   send this signal instead of SIGKILL\n"
118
 
                 "    -u        display user IDs\n"
119
 
                 "    -v        verbose output\n"
120
 
                 "    -V        display version information\n"));
 
108
                 "  -a,--all              display unused files too\n"
 
109
                 "  -i,--interactive      ask before killing (ignored without -k)\n"
 
110
                 "  -k,--kill             kill processes accessing the named file\n"
 
111
                 "  -l,--list-signals     list available signal names\n"
 
112
                 "  -m,--mount            show all processes using the named filesystems or block device\n"
 
113
                 "  -M,--ismountpoint     fulfill request only if NAME is a mount point\n"
 
114
                 "  -n,--namespace SPACE  search in this name space (file, udp, or tcp)\n"
 
115
                 "  -s,--silent           silent operation\n"
 
116
                 "  -SIGNAL               send this signal instead of SIGKILL\n"
 
117
                 "  -u,--user             display user IDs\n"
 
118
                 "  -v,--verbose          verbose output\n"
 
119
                 "  -V,--version          display version information\n"));
121
120
#ifdef WITH_IPV6
122
 
        fprintf(stderr, _("    -4        search IPv4 sockets only\n"
123
 
                          "    -6        search IPv6 sockets only\n"));
 
121
        fprintf(stderr, _(
 
122
         "  -4,--ipv4             search IPv4 sockets only\n"
 
123
                 "  -6,--ipv6             search IPv6 sockets only\n"));
124
124
#endif
125
 
        fprintf(stderr, _("    -         reset options\n\n"
 
125
        fprintf(stderr, _(
 
126
         "  -                     reset options\n\n"
126
127
                          "  udp/tcp names: [local_port][,[rmt_host][,[rmt_port]]]\n\n"));
127
128
        exit(1);
128
129
}
132
133
        fprintf(stderr, _("fuser (PSmisc) %s\n"), VERSION);
133
134
        fprintf(stderr,
134
135
                _
135
 
                ("Copyright (C) 1993-2009 Werner Almesberger and Craig Small\n\n"));
 
136
                ("Copyright (C) 1993-2010 Werner Almesberger and Craig Small\n\n"));
136
137
        fprintf(stderr,
137
138
                _("PSmisc comes with ABSOLUTELY NO WARRANTY.\n"
138
139
                  "This is free software, and you are welcome to redistribute it under\n"
161
162
 
162
163
        if ((topproc_dir = opendir("/proc")) == NULL) {
163
164
                fprintf(stderr, _("Cannot open /proc directory: %s\n"),
164
 
                        strerror(errno));
 
165
                strerror(errno));
165
166
                exit(1);
166
167
        }
167
168
        my_pid = getpid();
392
393
 
393
394
int parse_file(struct names *this_name, struct inode_list **ino_list)
394
395
{
395
 
        struct stat st;
396
 
 
397
 
        if (stat(this_name->filename, &st) != 0) {
398
 
                fprintf(stderr, _("Cannot stat %s: %s\n"), this_name->filename,
399
 
                        strerror(errno));
 
396
        if (stat(this_name->filename, &(this_name->st)) != 0) {
 
397
      if (errno == ENOENT)
 
398
        fprintf(stderr, _("Specified filename %s does not exist.\n"), this_name->filename);
 
399
      else
 
400
                fprintf(stderr, _("Cannot stat %s: %s\n"), this_name->filename, strerror(errno));
400
401
                return -1;
401
402
        }
402
403
#ifdef DEBUG
403
404
        printf("adding file %s %lX %lX\n", this_name->filename,
404
 
               (unsigned long)st.st_dev, (unsigned long)st.st_ino);
 
405
               (unsigned long)this_name->st.st_dev, (unsigned long)this_name->st.st_ino);
405
406
#endif                          /* DEBUG */
406
 
        add_inode(ino_list, this_name, st.st_dev, st.st_ino);
 
407
        add_inode(ino_list, this_name, this_name->st.st_dev, this_name->st.st_ino);
407
408
        return 0;
408
409
}
409
410
 
412
413
                  struct unixsocket_list *sun_head)
413
414
{
414
415
        struct unixsocket_list *sun_tmp;
415
 
        struct stat st;
416
416
        dev_t net_dev;
417
417
 
418
 
        if (stat(this_name->filename, &st) != 0) {
419
 
                fprintf(stderr, _("Cannot stat %s: %s\n"), this_name->filename,
420
 
                        strerror(errno));
421
 
                return -1;
422
 
        }
423
418
        net_dev = find_net_dev();
424
419
 
425
420
        for (sun_tmp = sun_head; sun_tmp != NULL; sun_tmp = sun_tmp->next) {
426
 
                if (sun_tmp->dev == st.st_dev && sun_tmp->inode == st.st_ino) {
 
421
                if (sun_tmp->dev == this_name->st.st_dev && sun_tmp->inode == this_name->st.st_ino) {
427
422
                        add_inode(ino_list, this_name, net_dev,
428
423
                                  sun_tmp->net_inode);
429
424
                        return 0;
436
431
parse_mounts(struct names *this_name, struct device_list **dev_list,
437
432
             const char opts)
438
433
{
439
 
        struct stat st;
440
434
        dev_t match_device;
441
435
 
442
 
        if (stat(this_name->filename, &st) != 0) {
443
 
                fprintf(stderr, _("Cannot stat %s: %s\n"), this_name->filename,
444
 
                        strerror(errno));
445
 
                return -1;
446
 
        }
447
 
        if (S_ISBLK(st.st_mode))
448
 
                match_device = st.st_rdev;
 
436
        if (S_ISBLK(this_name->st.st_mode))
 
437
                match_device = this_name->st.st_rdev;
449
438
        else
450
 
                match_device = st.st_dev;
 
439
                match_device = this_name->st.st_dev;
451
440
        add_device(dev_list, this_name, match_device);
452
441
        return 0;
453
442
}
767
756
}
768
757
#endif
769
758
 
 
759
static void
 
760
read_proc_mounts(struct mount_list **mnt_list)
 
761
{
 
762
        FILE *fp;
 
763
        char line[BUFSIZ];
 
764
        char *find_mountp;
 
765
        char *find_space;
 
766
        struct mount_list *mnt_tmp;
 
767
 
 
768
        if ((fp = fopen(PROC_MOUNTS, "r")) == NULL) {
 
769
                fprintf(stderr, "Cannot open %s\n", PROC_MOUNTS);
 
770
                return;
 
771
        }
 
772
        while (fgets(line, BUFSIZ, fp) != NULL) {
 
773
                if ((find_mountp = strchr(line, ' ')) == NULL)
 
774
                        continue;
 
775
                find_mountp++;
 
776
                if ((find_space = strchr(find_mountp, ' ')) == NULL)
 
777
                        continue;
 
778
                *find_space = '\0';
 
779
                if ((mnt_tmp = malloc(sizeof(struct mount_list))) == NULL)
 
780
                        continue;
 
781
                if ((mnt_tmp->mountpoint = strdup(find_mountp)) == NULL)
 
782
                        continue;
 
783
                mnt_tmp->next = *mnt_list;
 
784
                *mnt_list = mnt_tmp;
 
785
        }
 
786
        fclose(fp);
 
787
}
 
788
 
 
789
static int
 
790
is_mountpoint(struct mount_list **mnt_list, char *arg)
 
791
{
 
792
        char *p;
 
793
        struct mount_list *mnt_tmp;
 
794
 
 
795
        if (*arg == '\0')
 
796
                return 0;
 
797
        /* Remove trailing slashes. */
 
798
        for (p = arg; *p != '\0'; p++)
 
799
                ;
 
800
        while (*(--p) == '/' && p > arg)
 
801
                *p = '\0';
 
802
 
 
803
        for (mnt_tmp = *mnt_list; mnt_tmp != NULL; mnt_tmp = mnt_tmp->next)
 
804
                if (!strcmp(mnt_tmp->mountpoint, arg))
 
805
                        return 1;
 
806
        return 0;
 
807
}
 
808
 
770
809
int main(int argc, char *argv[])
771
810
{
772
811
        opt_type opts;
777
816
        unsigned char default_namespace = NAMESPACE_FILE;
778
817
        struct device_list *match_devices = NULL;
779
818
        struct unixsocket_list *unixsockets = NULL;
 
819
        struct mount_list *mounts = NULL;
780
820
 
781
821
        dev_t netdev;
782
822
        struct ip_connections *tcp_connection_list = NULL;
787
827
#endif
788
828
        struct inode_list *match_inodes = NULL;
789
829
        struct names *names_head, *this_name, *names_tail;
790
 
        int optc;
 
830
        int argc_cnt;
 
831
    char *current_argv, *option;
 
832
    char option_buf[3];
 
833
    struct option *optr;
791
834
        char *nsptr;
792
 
        int ignore_options;
793
 
        char *sig_aname;
 
835
  int skip_argv;
794
836
 
795
837
        struct option options[] = {
796
838
                {"all", 0, NULL, 'a'},
798
840
                {"interactive", 0, NULL, 'i'},
799
841
                {"list-signals", 0, NULL, 'l'},
800
842
                {"mount", 0, NULL, 'm'},
 
843
                {"ismountpoint", 0, NULL, 'M'},
801
844
                {"namespace", 1, NULL, 'n'},
802
845
                {"silent", 0, NULL, 's'},
803
846
                {"user", 0, NULL, 'u'},
807
850
                {"ipv4", 0, NULL, '4'},
808
851
                {"ipv6", 0, NULL, '6'},
809
852
#endif
810
 
                {"SIG", 1, NULL, 'S'},
811
 
 
812
 
        
 
853
                { 0, 0, 0, 0 }
813
854
        };
814
855
 
815
856
#ifdef WITH_IPV6
829
870
        netdev = find_net_dev();
830
871
        fill_unix_cache(&unixsockets);
831
872
 
832
 
        opterr=0;
833
 
        ignore_options=0;
834
 
        while ((optc =
835
 
#ifdef WITH_IPV6
836
 
                getopt_long(argc, argv, "46acfhikmn:sS:uvV", options,NULL)
837
 
#else
838
 
                getopt_long(argc, argv, "acfhikmn:sS:uvV", options,NULL)
839
 
#endif
840
 
                            ) != -1) {
841
 
          if (ignore_options > 0) {
842
 
                ignore_options--;
843
 
                continue;
844
 
          }
845
 
                switch (optc) {
846
 
#ifdef WITH_IPV6
847
 
                case '4':
 
873
    for (argc_cnt = 1; argc_cnt < argc; argc_cnt++) {
 
874
      current_argv = argv[argc_cnt];
 
875
      if (current_argv[0] == '-') { /* its an option */
 
876
        if (current_argv[1] == '-') { /* its a long option */
 
877
          if (current_argv[2] == '\0')  /* -- */
 
878
            break;
 
879
          /* Parse the long options */
 
880
          option = option_buf;
 
881
          for (optr = options; optr->name != NULL; optr++) {
 
882
            if (strcmp(current_argv+2,optr->name) == 0) {
 
883
              sprintf(option_buf, "-%c", (char)optr->val);
 
884
              break;
 
885
            }
 
886
          }
 
887
          if (optr->name == NULL) {
 
888
                        fprintf(stderr, _("%s: Invalid option %s\n"), argv[0],
 
889
                                current_argv);
 
890
                        usage(NULL);
 
891
          }
 
892
        } else {
 
893
          option = current_argv;
 
894
        }
 
895
        skip_argv=0;
 
896
        while (*(++option) != '\0' && !skip_argv) { /* skips over the - */
 
897
                  switch (*option) {
 
898
#ifdef WITH_IPV6
 
899
                  case '4':
848
900
                        ipv4_only = 1;
849
901
                        break;
850
 
                case '6':
 
902
                  case '6':
851
903
                        ipv6_only = 1;
852
904
                        break;
853
 
#endif
854
 
                case 'a':
 
905
#endif /* WITH_IPV6 */
 
906
                  case 'a':
855
907
                        opts |= OPT_ALLFILES;
856
908
                        break;
857
 
                case 'c':
858
 
                        opts |= OPT_MOUNTPOINT;
 
909
                  case 'c':
 
910
                        opts |= OPT_MOUNTS;
859
911
                        break;
860
 
                case 'f':
 
912
                  case 'f':
861
913
                        /* ignored */
862
914
                        break;
863
 
                case 'h':
 
915
                  case 'h':
864
916
                        usage(NULL);
865
917
                        break;
866
 
                case 'i':
 
918
                  case 'i':
867
919
                        opts |= OPT_INTERACTIVE;
868
920
                        break;
869
 
                case 'k':
 
921
                  case 'k':
870
922
                        opts |= OPT_KILL;
871
923
                        break;
872
 
                case 'l':
 
924
                  case 'l':
873
925
                        list_signals();
874
926
                        return 0;
875
 
                case 'm':
 
927
                  case 'm':
876
928
                        opts |= OPT_MOUNTS;
877
929
                        break;
878
 
                case 'n':
879
 
                        if (strcmp(optarg, "tcp") == 0)
 
930
                  case 'M':
 
931
                        opts |= OPT_ISMOUNTPOINT;
 
932
                    read_proc_mounts(&mounts);
 
933
                        break;
 
934
                  case 'n':
 
935
            argc_cnt++;
 
936
            if (argc_cnt >= argc) {
 
937
              usage(_ ("Namespace option requires an argument."));
 
938
              exit(1);;
 
939
            }
 
940
            skip_argv=1;
 
941
            //while(option != '\0') option++;
 
942
                        if (strcmp(argv[argc_cnt], "tcp") == 0)
880
943
                                default_namespace = NAMESPACE_TCP;
881
 
                        else if (strcmp(optarg, "udp") == 0)
 
944
                        else if (strcmp(argv[argc_cnt], "udp") == 0)
882
945
                                default_namespace = NAMESPACE_UDP;
883
 
                        else if (strcmp(optarg, "file") == 0)
 
946
                        else if (strcmp(argv[argc_cnt], "file") == 0)
884
947
                                default_namespace = NAMESPACE_FILE;
885
948
                        else
886
949
                                usage(_("Invalid namespace name"));
887
950
                        break;
888
 
                case 's':
 
951
                  case 's':
889
952
                        opts |= OPT_SILENT;
890
953
                        break;
891
 
                case 'S':
892
 
                        {
893
 
                          char *signame;
894
 
                          if (asprintf(&signame, "S%s",optarg) > 0) {
895
 
                                sig_number = get_signal(signame,argv[0]);
896
 
                            free(signame);
897
 
                          }
898
 
                          break;
899
 
                        }
900
 
                case 'u':
 
954
                  case 'u':
901
955
                        opts |= OPT_USER;
902
956
                        break;
903
 
                case 'v':
 
957
                  case 'v':
904
958
                        opts |= OPT_VERBOSE;
905
959
                        break;
906
 
                case 'V':
 
960
                  case 'V':
907
961
                        print_version();
908
962
                        return 0;
909
 
                case '?':
910
 
                        if (optopt=='n') {
911
 
                                usage(_
912
 
                                      ("Namespace option requires an argument."));
913
 
                        }
914
 
                        if (isdigit(optopt)) {
915
 
                          if (strlen(argv[optind-1]) == 2)
916
 
                                sig_aname =strdup(argv[optind-1]+1);
917
 
                          else {
918
 
                                sig_aname = strdup(argv[optind]+1);
919
 
                            ignore_options = strlen(argv[optind])-2;
920
 
                          }
921
 
                          sig_number = get_signal(sig_aname,argv[0]);
922
 
                          free(sig_aname);
923
 
                          break;
924
 
                        }
 
963
          default:
 
964
            if (isupper(*option) || isdigit(*option)) {
 
965
              sig_number = get_signal(current_argv+1, argv[0]);
 
966
            skip_argv=1;
 
967
              break;
 
968
            }
925
969
                        fprintf(stderr, "%s: Invalid option %c\n", argv[0],
926
 
                                optopt);
927
 
                        exit(1);
 
970
                                *option);
928
971
                        usage(NULL);
929
 
 
 
972
                        exit(1);
930
973
                        break;
931
 
                default:
932
 
                        printf("unknown optc %c\n", optc);
933
 
                        exit(1);
 
974
                  }             /* switch */
 
975
            }                   /* while option */
 
976
        continue;
 
977
      } /* an option */
 
978
      /* Not an option, must be a file specification */
934
979
 
935
 
                }               /* switch */
936
 
        }                       /* while optc */
937
 
        for (optc = optind; optc < argc; optc++) {
938
 
                /* File specifications */
939
980
                if ((this_name = malloc(sizeof(struct names))) == NULL)
940
981
                        continue;
941
982
                this_name->next = NULL;
942
 
                if (names_head == NULL)
943
 
                        names_head = this_name;
944
 
                if (names_tail != NULL)
945
 
                        names_tail->next = this_name;
946
 
                names_tail = this_name;
947
983
                /* try to find namespace spec */
948
984
                this_name->name_space = default_namespace;
949
 
                if (((nsptr = strchr(argv[optc], '/')) != NULL)
950
 
                    && (nsptr != argv[optc])) {
 
985
                if (((nsptr = strchr(current_argv, '/')) != NULL)
 
986
                    && (nsptr != current_argv)) {
951
987
                        if (strcmp(nsptr + 1, "tcp") == 0) {
952
988
                                this_name->name_space = NAMESPACE_TCP;
953
989
                                *nsptr = '\0';
960
996
                        }
961
997
                }
962
998
                this_name->matched_procs = NULL;
963
 
                if ((opts & OPT_MOUNTS || opts & OPT_MOUNTPOINT)
 
999
                if (opts & (OPT_MOUNTS|OPT_ISMOUNTPOINT)
964
1000
                    && this_name->name_space != NAMESPACE_FILE)
965
1001
                        usage(_
966
 
                              ("You can only use files with mountpoint option"));
 
1002
                              ("You can only use files with mountpoint options"));
 
1003
                if (opts & OPT_ISMOUNTPOINT &&
 
1004
                    !is_mountpoint(&mounts, current_argv)) {
 
1005
                        free(this_name);
 
1006
                        continue;
 
1007
                }
967
1008
                switch (this_name->name_space) {
968
1009
                case NAMESPACE_TCP:
969
 
                        if (asprintf(&(this_name->filename), "%s/tcp", argv[optc]) > 0) {
 
1010
                        if (asprintf(&(this_name->filename), "%s/tcp", current_argv) > 0) {
970
1011
#ifdef WITH_IPV6
971
1012
                          parse_inet(this_name, ipv4_only, ipv6_only,
972
1013
                                   &tcp_connection_list, &tcp6_connection_list);
976
1017
                        }
977
1018
                        break;
978
1019
                case NAMESPACE_UDP:
979
 
                        if (asprintf(&(this_name->filename), "%s/udp", argv[optc]) > 0) {
 
1020
                        if (asprintf(&(this_name->filename), "%s/udp", current_argv) > 0) {
980
1021
#ifdef WITH_IPV6
981
1022
                          parse_inet(this_name, ipv4_only, ipv6_only,
982
1023
                                   &udp_connection_list, &udp6_connection_list);
986
1027
                        }
987
1028
                        break;
988
1029
                default:        /* FILE */
989
 
                        this_name->filename = strdup(argv[optc]);
990
 
                        parse_file(this_name, &match_inodes);
991
 
                        parse_unixsockets(this_name, &match_inodes,
992
 
                                          unixsockets);
993
 
                        if (opts & OPT_MOUNTPOINT || opts & OPT_MOUNTS)
 
1030
                        this_name->filename = strdup(current_argv);
 
1031
                        if (parse_file(this_name, &match_inodes) == 0) {
 
1032
              parse_unixsockets(this_name, &match_inodes, unixsockets);
 
1033
                          if (opts & OPT_MOUNTS)
994
1034
                                parse_mounts(this_name, &match_devices, opts);
 
1035
            }
995
1036
                        break;
996
1037
                }
997
1038
 
998
 
        }                       /* for optc */
999
 
 
1000
 
        if (names_head == NULL) {
 
1039
                if (names_head == NULL)
 
1040
                        names_head = this_name;
 
1041
                if (names_tail != NULL)
 
1042
                        names_tail->next = this_name;
 
1043
                names_tail = this_name;
 
1044
    } /* for across the argvs */
 
1045
        if (names_head == NULL)
1001
1046
                usage(_("No process specification given"));
1002
 
        }
1003
 
        /* Check conflicting operations */
1004
 
        if (opts & OPT_MOUNTPOINT) {
1005
 
                if (opts & OPT_MOUNTS)
1006
 
                        usage(_
1007
 
                              ("You cannot use the mounted and mountpoint flags together"));
1008
 
        }
 
1047
 
1009
1048
        if (opts & OPT_SILENT) {
1010
1049
                opts &= ~OPT_VERBOSE;
1011
1050
                opts &= ~OPT_USER;
1450
1489
                  const int sig_number)
1451
1490
{
1452
1491
        struct procs *pptr;
 
1492
  pid_t *mypid;
 
1493
 
 
1494
  mypid = getpid();
1453
1495
 
1454
1496
        for (pptr = proc_head; pptr != NULL; pptr = pptr->next) {
 
1497
    if ( pptr->pid == mypid)
 
1498
      continue; /* dont kill myself */
 
1499
                if ( pptr->proc_type != PTYPE_NORMAL )
 
1500
            continue;
1455
1501
                if ((opts & OPT_INTERACTIVE) && (ask(pptr->pid) == 0))
1456
 
                        continue;
1457
 
                if (kill(pptr->pid, sig_number) < 0) {
 
1502
                  continue;
 
1503
                if ( kill(pptr->pid, sig_number) < 0) {
1458
1504
                        fprintf(stderr, _("Could not kill process %d: %s\n"),
1459
 
                                pptr->pid, strerror(errno));
 
1505
                                        pptr->pid, strerror(errno));
1460
1506
                }
1461
 
 
1462
1507
        }
1463
1508
}
1464
1509