16478b79fe3cd1a8181bc8775d56720a4664bb30
[platform/upstream/bash.git] / examples / loadables / realpath.c
1 /*
2  * realpath -- canonicalize pathnames, resolving symlinks
3  *
4  * usage: realpath [-csv] pathname [pathname...]
5  *
6  * options:     -c      check whether or not each resolved path exists
7  *              -s      no output, exit status determines whether path is valid
8  *              -v      produce verbose output
9  *
10  *
11  * exit status: 0       if all pathnames resolved
12  *              1       if any of the pathname arguments could not be resolved
13  *
14  *
15  * Bash loadable builtin version
16  *
17  * Chet Ramey
18  * chet@po.cwru.edu
19  */
20
21 #include "config.h"
22
23 #include <sys/types.h>
24 #include <sys/stat.h>
25
26 #include <stdio.h>
27 #ifdef HAVE_UNISTD_H
28 #  include <unistd.h>
29 #endif
30 #include "bashansi.h"
31 #include <maxpath.h>
32 #include <errno.h>
33
34 #include "builtins.h"
35 #include "shell.h"
36 #include "bashgetopt.h"
37
38 #ifndef errno
39 extern int      errno;
40 #endif
41
42 extern char     *sh_realpath();
43
44 realpath_builtin(list)
45 WORD_LIST       *list;
46 {
47         int     opt, cflag, vflag, sflag, es;
48         char    *r, realbuf[PATH_MAX], *p;
49         struct stat sb;
50
51         if (list == 0) {
52                 builtin_usage();
53                 return (EX_USAGE);
54         }
55
56         vflag = cflag = sflag = 0;
57         reset_internal_getopt();
58         while ((opt = internal_getopt (list, "csv")) != -1) {
59                 switch (opt) {
60                 case 'c':
61                         cflag = 1;
62                         break;
63                 case 's':
64                         sflag = 1;
65                         break;
66                 case 'v':
67                         vflag = 1;
68                         break;
69                 default:
70                         usage();
71                 }
72         }
73
74         list = loptend;
75
76         if (list == 0)
77                 usage();
78
79         for (es = EXECUTION_SUCCESS; list; list = list->next) {
80                 p = list->word->word;
81                 r = sh_realpath(p, realbuf);
82                 if (r == 0) {
83                         es = EXECUTION_FAILURE;
84                         if (sflag == 0)
85                                 builtin_error("%s: cannot resolve: %s", p, strerror(errno));
86                         continue;
87                 }
88                 if (cflag && (stat(realbuf, &sb) < 0)) {
89                         es = EXECUTION_FAILURE;
90                         if (sflag == 0)
91                                 builtin_error("%s: %s", p, strerror(errno));
92                         continue;
93                 }
94                 if (sflag == 0) {
95                         if (vflag)
96                                 printf ("%s -> ", p);
97                         printf("%s\n", realbuf);
98                 }
99         }
100         return es;
101 }
102
103 char *realpath_doc[] = {
104         "Display the canonicalized version of each PATHNAME argument, resolving",
105         "symbolic links.  The -c option checks whether or not each resolved name",
106         "exists.  The -s option produces no output; the exit status determines the",
107         "valididty of each PATHNAME.  The -v option produces verbose output.  The",
108         "exit status is 0 if each PATHNAME was resolved; non-zero otherwise.",
109         (char *)NULL
110 };
111
112 struct builtin realpath_struct = {
113         "realpath",             /* builtin name */
114         realpath_builtin,       /* function implementing the builtin */
115         BUILTIN_ENABLED,        /* initial flags for builtin */
116         realpath_doc,           /* array of long documentation strings */
117         "realpath [-csv] pathname [pathname...]",       /* usage synopsis */
118         0                       /* reserved for internal use */
119 };