2 * pwdx.c - print process working directory
3 * Copyright 2004 Nicholas Miell
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
26 #include <sys/types.h>
32 #include "fileutils.h"
34 static void __attribute__ ((__noreturn__)) usage(FILE * out)
36 fputs(USAGE_HEADER, out);
37 fprintf(out, _(" %s [options] pid...\n"), program_invocation_short_name);
38 fputs(USAGE_OPTIONS, out);
39 fputs(USAGE_HELP, out);
40 fputs(USAGE_VERSION, out);
41 fprintf(out, USAGE_MAN_TAIL("pwdx(1)"));
43 exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
46 int check_pid_argument(char *input)
52 if (!strncmp("/proc/", input, 6))
55 pid = strtol(input + skip, &end, 10);
57 if (errno || input + skip == end || (end && *end))
64 int main(int argc, char *argv[])
68 ssize_t alloclen = 128;
71 static const struct option longopts[] = {
72 {"version", no_argument, 0, 'V'},
73 {"help", no_argument, 0, 'h'},
77 #ifdef HAVE_PROGRAM_INVOCATION_NAME
78 program_invocation_name = program_invocation_short_name;
80 setlocale (LC_ALL, "");
81 bindtextdomain(PACKAGE, LOCALEDIR);
85 while ((ch = getopt_long(argc, argv, "Vh", longopts, NULL)) != -1)
88 printf(PROCPS_NG_VERSION);
102 pathbuf = xmalloc(alloclen);
104 for (i = 0; i < argc; i++) {
107 /* Constant 10 is the length of strings "/proc/" + "/cwd" + 1 */
109 buflen = 10 + strlen(argv[i]) + 1;
110 buf = xmalloc(buflen);
112 if (check_pid_argument(argv[i]))
113 xerrx(EXIT_FAILURE, _("invalid process id: %s"),
116 * At this point, all arguments are in the form
117 * /proc/NNNN or NNNN, so a simple check based on
118 * the first char is possible
120 if (argv[i][0] != '/')
121 snprintf(buf, buflen, "/proc/%s/cwd", argv[i]);
123 snprintf(buf, buflen, "%s/cwd", argv[i]);
126 * buf contains /proc/NNNN/cwd symlink name
127 * on entry, the target of that symlink on return
129 while ((len = readlink(buf, pathbuf, alloclen)) == alloclen) {
131 pathbuf = xrealloc(pathbuf, alloclen);
136 s = strerror(errno == ENOENT ? ESRCH : errno);
137 retval = EXIT_FAILURE;
138 fprintf(stderr, "%s: %s\n", argv[i], s);
145 printf("%s: %s\n", argv[i], s);