pwdx.c 2.46 KB
Newer Older
albert's avatar
albert committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
// Copyright 2004 Nicholas Miell
//
// This file may be used subject to the terms and conditions of the
// GNU Library General Public License Version 2 as published by the
// Free Software Foundation.This program is distributed in the hope
// that it will be useful, but WITHOUT ANY WARRANTY; without even the
// implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the GNU Library General Public License for more
// details.

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <regex.h>
#include <limits.h>
#include <unistd.h>
#include <errno.h>

#include "proc/version.h"

static void die(const char *msg) NORETURN;
static void die(const char *msg)
{
albert's avatar
albert committed
25
     fputs(msg, stderr);
albert's avatar
albert committed
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
     exit(1);
}

static void version(void) NORETURN;
static void version(void)
{
     printf("pwdx (%s)\n", procps_version);
     exit(0);
}

int main(int argc, char* argv[])
{
     char buf[PATH_MAX];
     regex_t re;
     int i;

     if (argc < 2)
          die("Usage: pwdx pid...\n");

     // Allowed on the command line:
     //
     // --version
     // -V
     // /proc/nnnn
     // nnnn
     //
     // where nnnn is any number that doesn't begin with 0.
     //
     // If --version or -V are present, further arguments are ignored
     // completely.
        
     regcomp(&re, "^((/proc/+)?[1-9][0-9]*|-V|--version)$",
             REG_EXTENDED|REG_NOSUB);

     for (i = 1; i < argc; i++) {
          if (regexec(&re, argv[i], 0, NULL, 0) != 0) {
albert's avatar
albert committed
62
               snprintf(buf, sizeof buf, "pwdx: invalid process id: %s\n", argv[i]);
albert's avatar
albert committed
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
               die(buf);
          }
          if (!strcmp("-V", argv[i]) || !strcmp("--version", argv[i]))
               version();
     }

     regfree(&re);

     for (i = 1; i < argc; i++) {
          char * s = buf;
          int len;
          
          // At this point, all arguments are in the form /proc/nnnn
          // or nnnn, so a simple check based on the first char is
          // possible
          if (argv[i][0] != '/')
               sprintf(buf, "/proc/%s/cwd", argv[i]);
          else
               sprintf(buf, "%s/cwd", argv[i]);

          // buf contains /proc/nnnn/cwd symlink name on entry, the
          // target of that symlink on return
          if ((len = readlink(buf, buf, PATH_MAX)) < 0) {
               s = strerror(errno == ENOENT ? ESRCH : errno);
          } else {
               buf[len] = 0;
          }

          printf("%s: %s\n", argv[i], s);
     }

     return 0;
}