1*7c2fbfb3SApril Chin /***********************************************************************
2*7c2fbfb3SApril Chin * *
3*7c2fbfb3SApril Chin * This software is part of the ast package *
4*7c2fbfb3SApril Chin * Copyright (c) 1982-2007 AT&T Intellectual Property *
5*7c2fbfb3SApril Chin * and is licensed under the *
6*7c2fbfb3SApril Chin * Common Public License, Version 1.0 *
7*7c2fbfb3SApril Chin * by AT&T Intellectual Property *
8*7c2fbfb3SApril Chin * *
9*7c2fbfb3SApril Chin * A copy of the License is available at *
10*7c2fbfb3SApril Chin * http://www.opensource.org/licenses/cpl1.0.txt *
11*7c2fbfb3SApril Chin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
12*7c2fbfb3SApril Chin * *
13*7c2fbfb3SApril Chin * Information and Software Systems Research *
14*7c2fbfb3SApril Chin * AT&T Research *
15*7c2fbfb3SApril Chin * Florham Park NJ *
16*7c2fbfb3SApril Chin * *
17*7c2fbfb3SApril Chin * Glenn Fowler <gsf@research.att.com> *
18*7c2fbfb3SApril Chin * David Korn <dgk@research.att.com> *
19*7c2fbfb3SApril Chin * *
20*7c2fbfb3SApril Chin ***********************************************************************/
21*7c2fbfb3SApril Chin #pragma prototyped
22*7c2fbfb3SApril Chin
23*7c2fbfb3SApril Chin static const char usage[] =
24*7c2fbfb3SApril Chin "[-?\n@(#)$Id: readlink (AT&T Research) 2008-06-08 $\n]"
25*7c2fbfb3SApril Chin USAGE_LICENSE
26*7c2fbfb3SApril Chin "[+NAME?readlink - read the contents of a symbolic link]"
27*7c2fbfb3SApril Chin "[+DESCRIPTION?\breadlink\b returns the contents of the symbolic "
28*7c2fbfb3SApril Chin "link referred to by the path argument. Unless the \b-f\b "
29*7c2fbfb3SApril Chin "option is specified an error will be returned when the path "
30*7c2fbfb3SApril Chin "is not a symbolic link.]"
31*7c2fbfb3SApril Chin "[f:canonicalize?The returned value will be an absolute pathname that names "
32*7c2fbfb3SApril Chin "the same file, whose resolution does not involve \".\", \"..\", or "
33*7c2fbfb3SApril Chin "symbolic links, otherwise only the exact (relative) value will be returned.]"
34*7c2fbfb3SApril Chin "[n:no-newline?Supress newline at the end.]"
35*7c2fbfb3SApril Chin "[v:verbose?Verbose - print errors.]"
36*7c2fbfb3SApril Chin "[+SEE ALSO?\bbasename\b(1),\bdirname\b(2),\breadlink\b(2),\breadpath\n(2)]"
37*7c2fbfb3SApril Chin ;
38*7c2fbfb3SApril Chin
39*7c2fbfb3SApril Chin #include <cmd.h>
40*7c2fbfb3SApril Chin
41*7c2fbfb3SApril Chin int
b_readlink(int argc,char ** argv,void * context)42*7c2fbfb3SApril Chin b_readlink(int argc, char** argv, void* context)
43*7c2fbfb3SApril Chin {
44*7c2fbfb3SApril Chin register char* s;
45*7c2fbfb3SApril Chin register int i;
46*7c2fbfb3SApril Chin register char* m;
47*7c2fbfb3SApril Chin register char* x;
48*7c2fbfb3SApril Chin int canonicalize = 0,
49*7c2fbfb3SApril Chin nonewline = 0,
50*7c2fbfb3SApril Chin verbose = 0;
51*7c2fbfb3SApril Chin char buf[PATH_MAX+2];
52*7c2fbfb3SApril Chin int len = 0;
53*7c2fbfb3SApril Chin char *filename,
54*7c2fbfb3SApril Chin *resolvedname = NULL;
55*7c2fbfb3SApril Chin
56*7c2fbfb3SApril Chin cmdinit(argc, argv, context, ERROR_CATALOG, 0);
57*7c2fbfb3SApril Chin for (;;)
58*7c2fbfb3SApril Chin {
59*7c2fbfb3SApril Chin switch (optget(argv, usage))
60*7c2fbfb3SApril Chin {
61*7c2fbfb3SApril Chin case 'f':
62*7c2fbfb3SApril Chin canonicalize = opt_info.num;
63*7c2fbfb3SApril Chin continue;
64*7c2fbfb3SApril Chin case 'n':
65*7c2fbfb3SApril Chin nonewline = opt_info.num;
66*7c2fbfb3SApril Chin continue;
67*7c2fbfb3SApril Chin case 'v':
68*7c2fbfb3SApril Chin verbose = opt_info.num;
69*7c2fbfb3SApril Chin continue;
70*7c2fbfb3SApril Chin case '?':
71*7c2fbfb3SApril Chin error(ERROR_usage(2), "%s", opt_info.arg);
72*7c2fbfb3SApril Chin continue;
73*7c2fbfb3SApril Chin case ':':
74*7c2fbfb3SApril Chin error(2, "%s", opt_info.arg);
75*7c2fbfb3SApril Chin continue;
76*7c2fbfb3SApril Chin }
77*7c2fbfb3SApril Chin break;
78*7c2fbfb3SApril Chin }
79*7c2fbfb3SApril Chin argv += opt_info.index;
80*7c2fbfb3SApril Chin argc -= opt_info.index;
81*7c2fbfb3SApril Chin if(error_info.errors || argc != 1)
82*7c2fbfb3SApril Chin error(ERROR_usage(2),"%s", optusage(NiL));
83*7c2fbfb3SApril Chin filename = argv[0];
84*7c2fbfb3SApril Chin
85*7c2fbfb3SApril Chin if (canonicalize)
86*7c2fbfb3SApril Chin {
87*7c2fbfb3SApril Chin len = resolvepath(filename, buf, sizeof(buf)-2);
88*7c2fbfb3SApril Chin }
89*7c2fbfb3SApril Chin else
90*7c2fbfb3SApril Chin {
91*7c2fbfb3SApril Chin len = readlink(filename, buf, sizeof(buf)-2);
92*7c2fbfb3SApril Chin }
93*7c2fbfb3SApril Chin
94*7c2fbfb3SApril Chin if (len != -1)
95*7c2fbfb3SApril Chin resolvedname = buf;
96*7c2fbfb3SApril Chin
97*7c2fbfb3SApril Chin if (!resolvedname)
98*7c2fbfb3SApril Chin {
99*7c2fbfb3SApril Chin if (verbose)
100*7c2fbfb3SApril Chin error(ERROR_system(1),"%s: readlink failed", filename);
101*7c2fbfb3SApril Chin else
102*7c2fbfb3SApril Chin return 1;
103*7c2fbfb3SApril Chin }
104*7c2fbfb3SApril Chin
105*7c2fbfb3SApril Chin if (!nonewline)
106*7c2fbfb3SApril Chin resolvedname[len++] = '\n';
107*7c2fbfb3SApril Chin
108*7c2fbfb3SApril Chin sfwrite(sfstdout, resolvedname, len);
109*7c2fbfb3SApril Chin
110*7c2fbfb3SApril Chin return 0;
111*7c2fbfb3SApril Chin }
112