ping

On 11/19/18 6:29 PM, Martijn van Duren wrote:
> So I hacked this together because I got annoyed by the fact that for 
> every pid I want to investigate I had to rerun fstat.
> 
> Diff below alleviates the searched pid from kvm_getfiles(3) to fstat(1).
> I left atomicity (is there any in kvm_getfiles?) in place, by retrieving
> everything in one go and filtering it before printing instead of doing
> multiple calls to kvm_getfiles.
> 
> Would something like this be interesting for inclusion? If not, I reckon
> we should add a check that -p and -u are mutually exclusive, because now
> the last argument wins, which is not what might be expected.
> 
> martijn@
> 
> Index: fstat.c
> ===================================================================
> RCS file: /cvs/src/usr.bin/fstat/fstat.c,v
> retrieving revision 1.95
> diff -u -p -r1.95 fstat.c
> --- fstat.c   16 Sep 2018 02:44:06 -0000      1.95
> +++ fstat.c   19 Nov 2018 17:28:04 -0000
> @@ -87,10 +87,14 @@
>  
>  #define MAXIMUM(a, b)        (((a) > (b)) ? (a) : (b))
>  
> +struct fstat_filter {
> +     int what;
> +     int arg;
> +};
> +
>  struct fileargs fileargs = SLIST_HEAD_INITIALIZER(fileargs);
>  
>  int  fsflg;  /* show files on same filesystem as file(s) argument */
> -int  pflg;   /* show files open by a particular pid */
>  int  uflg;   /* show files open by a particular (effective) user */
>  int  checkfile; /* true if restricting to particular files or filesystems */
>  int  nflg;   /* (numerical) display f.s. and rdev as dev_t */
> @@ -102,6 +106,9 @@ int       cflg;   /* fuser only */
>  int  fuser;  /* 1 if we are fuser, 0 if we are fstat */
>  int  signo;  /* signal to send (fuser only) */
>  
> +int  nfilter = 0;    /* How many uid/pid filters are in place */
> +struct fstat_filter *filter = NULL; /* An array of uid/pid filters */
> +
>  kvm_t *kd;
>  uid_t uid;
>  
> @@ -137,7 +144,7 @@ main(int argc, char *argv[])
>  {
>       struct passwd *passwd;
>       struct kinfo_file *kf, *kflast;
> -     int arg, ch, what;
> +     int ch;
>       char *memf, *nlistf, *optstr;
>       char buf[_POSIX2_LINE_MAX];
>       const char *errstr;
> @@ -145,8 +152,6 @@ main(int argc, char *argv[])
>  
>       hideroot = getuid();
>  
> -     arg = -1;
> -     what = KERN_FILE_BYPID;
>       nlistf = memf = NULL;
>       oflg = 0;
>  
> @@ -196,15 +201,18 @@ main(int argc, char *argv[])
>                       oflg = 1;
>                       break;
>               case 'p':
> -                     if (pflg++)
> -                             usage();
> -                     arg = strtonum(optarg, 0, INT_MAX, &errstr);
> +                     if ((filter = recallocarray(filter, nfilter, nfilter + 
> 1,
> +                         sizeof(*filter))) == NULL)
> +                             err(1, NULL);
> +                     filter[nfilter].arg = strtonum(optarg, 0, INT_MAX,
> +                         &errstr);
>                       if (errstr != NULL) {
>                               warnx("-p requires a process id, %s: %s",
>                                       errstr, optarg);
>                               usage();
>                       }
> -                     what = KERN_FILE_BYPID;
> +                     filter[nfilter].what = KERN_FILE_BYPID;
> +                     nfilter++;
>                       break;
>               case 's':
>                       sflg = 1;
> @@ -217,8 +225,7 @@ main(int argc, char *argv[])
>                       }
>                       break;
>               case 'u':
> -                     if (uflg++)
> -                             usage();
> +                     uflg = 1;
>                       if (!fuser) {
>                               uid_t uid;
>  
> @@ -230,8 +237,12 @@ main(int argc, char *argv[])
>                                                   optarg);
>                                       }
>                               }
> -                             arg = uid;
> -                             what = KERN_FILE_BYUID;
> +                             if ((filter = recallocarray(filter, nfilter,
> +                                 nfilter + 1, sizeof(*filter))) == NULL)
> +                                     err(1, NULL);
> +                             filter[nfilter].arg = uid;
> +                             filter[nfilter].what = KERN_FILE_BYUID;
> +                             nfilter++;
>                       }
>                       break;
>               case 'v':
> @@ -275,8 +286,15 @@ main(int argc, char *argv[])
>               checkfile = 1;
>       }
>  
> -     if ((kf = kvm_getfiles(kd, what, arg, sizeof(*kf), &cnt)) == NULL)
> -             errx(1, "%s", kvm_geterr(kd));
> +     if (nfilter == 1) {
> +             if ((kf = kvm_getfiles(kd, filter[0].what, filter[0].arg,
> +                 sizeof(*kf), &cnt)) == NULL)
> +                     errx(1, "%s", kvm_geterr(kd));
> +     } else {
> +             if ((kf = kvm_getfiles(kd, KERN_FILE_BYPID, -1, sizeof(*kf),
> +                 &cnt)) == NULL)
> +                     errx(1, "%s", kvm_geterr(kd));
> +     }
>  
>       if (fuser) {
>               /*
> @@ -367,11 +385,23 @@ pid_t   Pid;
>  void
>  fstat_dofile(struct kinfo_file *kf)
>  {
> +     int i;
>  
>       Uname = user_from_uid(kf->p_uid, 0);
>       procuid = &kf->p_uid;
>       Pid = kf->p_pid;
>       Comm = kf->p_comm;
> +
> +     for (i = 0; i < nfilter; i++) {
> +             if (filter[i].what == KERN_FILE_BYPID) {
> +                     if (filter[i].arg == Pid)
> +                             break;
> +             } else if (filter[i].arg == *procuid) {
> +                     break;
> +             }
> +     }
> +     if (i == nfilter && nfilter != 0)
> +             return;
>  
>       switch (kf->f_type) {
>       case DTYPE_VNODE:
> 

Reply via email to