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
39extern int	errno;
40#endif
41
42extern char	*sh_realpath();
43
44realpath_builtin(list)
45WORD_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
103char *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
112struct 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};
120