1 /*
2 * Copyright (c) 1997-2006 Erez Zadok
3 * Copyright (c) 1990 Jan-Simon Pendry
4 * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
5 * Copyright (c) 1990 The Regents of the University of California.
6 * All rights reserved.
7 *
8 * This code is derived from software contributed to Berkeley by
9 * Jan-Simon Pendry at Imperial College, London.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. All advertising materials mentioning features or use of this software
20 * must display the following acknowledgment:
21 * This product includes software developed by the University of
22 * California, Berkeley and its contributors.
23 * 4. Neither the name of the University nor the names of its contributors
24 * may be used to endorse or promote products derived from this software
25 * without specific prior written permission.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 * SUCH DAMAGE.
38 *
39 *
40 * File: am-utils/amq/pawd.c
41 *
42 */
43
44 /*
45 * pawd is similar to pwd, except that it returns more "natural" versions of
46 * pathnames for directories automounted with the amd automounter. If any
47 * arguments are given, the "more natural" form of the given pathnames are
48 * printed.
49 *
50 * Paul Anderson (paul@ed.lfcs)
51 *
52 */
53
54 #ifdef HAVE_CONFIG_H
55 # include <config.h>
56 #endif /* HAVE_CONFIG_H */
57 #include <am_defs.h>
58 #include <amq.h>
59
60
61 /* statics */
62 static char *localhost = "localhost";
63 static char transform[MAXPATHLEN];
64
65
66 #ifdef HAVE_CNODEID
67 static char *
cluster_server(void)68 cluster_server(void)
69 {
70 # ifdef HAVE_EXTERN_GETCCENT
71 struct cct_entry *cp;
72 # endif /* HAVE_EXTERN_GETCCENT */
73
74 if (cnodeid() == 0)
75 return localhost;
76
77 # ifdef HAVE_EXTERN_GETCCENT
78 while ((cp = getccent()))
79 if (cp->cnode_type == 'r')
80 return cp->cnode_name;
81 # endif /* HAVE_EXTERN_GETCCENT */
82
83 return localhost;
84 }
85 #endif /* HAVE_CNODEID */
86
87
88 /* DISK_HOME_HACK added by gdmr */
89 #ifdef DISK_HOME_HACK
90 static char *
hack_name(char * dir)91 hack_name(char *dir)
92 {
93 char partition[MAXPATHLEN];
94 char username[MAXPATHLEN];
95 char hesiod_lookup[MAXPATHLEN];
96 char *to, *ch, *hes_name, *dot;
97 char **hes;
98
99 #ifdef DEBUG
100 fprintf(stderr, "hack_name(%s)\n", dir);
101 #endif /* DEBUG */
102
103 if (dir[0] == '/' && dir[1] == 'a' && dir[2] == '/') {
104 /* Could be /a/server/disk/home/partition/user... */
105 ch = dir + 3;
106 while (*ch && *ch != '/') ch++; /* Skip server */
107 if (!NSTREQ(ch, "/disk/home/", 11))
108 return NULL; /* Nope */
109 /* Looking promising, next should be the partition name */
110 ch += 11;
111 to = partition;
112 while (*ch && *ch != '/') *to++ = *ch++;
113 to = '\0';
114 if (!(*ch))
115 return NULL; /* Off the end */
116 /* Now the username */
117 ch++;
118 to = username;
119 while (*ch && *ch != '/') *to++ = *ch++;
120 to = '\0';
121 #ifdef DEBUG
122 fprintf(stderr, "partition %s, username %s\n", partition, username);
123 #endif /* DEBUG */
124
125 xsnprintf(hesiod_lookup, sizeof(hesiod_lookup),
126 "%s.homes-remote", username);
127 hes = hes_resolve(hesiod_lookup, "amd");
128 if (!hes)
129 return NULL;
130 #ifdef DEBUG
131 fprintf(stderr, "hesiod -> <%s>\n", *hes);
132 #endif /* DEBUG */
133 hes_name = strstr(*hes, "/homes/remote/");
134 if (!hes_name) return NULL;
135 hes_name += 14;
136 #ifdef DEBUG
137 fprintf(stderr, "hesiod -> <%s>\n", hes_name);
138 #endif /* DEBUG */
139 dot = hes_name;
140 while (*dot && *dot != '.') dot++;
141 *dot = '\0';
142 #ifdef DEBUG
143 fprintf(stderr, "hesiod -> <%s>\n", hes_name);
144 #endif /* DEBUG */
145
146 if (strcmp(partition, hes_name)) return NULL;
147 #ifdef DEBUG
148 fprintf(stderr, "A match, munging....\n");
149 #endif /* DEBUG */
150 xstrlcpy(transform, "/home/", sizeof(transform));
151 xstrlcat(transform, username, sizeof(transform));
152 if (*ch)
153 xstrlcat(transform, ch, sizeof(transform));
154 #ifdef DEBUG
155 fprintf(stderr, "Munged to <%s>\n", transform);
156 #endif /* DEBUG */
157 return transform;
158 }
159 return NULL;
160 }
161 #endif /* DISK_HOME_HACK */
162
163
164 /*
165 * The routine transform_dir(path) transforms pathnames of directories
166 * mounted with the amd automounter to produce a more "natural" version.
167 * The automount table is obtained from the local amd via the rpc interface
168 * and reverse lookups are repeatedly performed on the directory name
169 * substituting the name of the automount link for the value of the link
170 * whenever it occurs as a prefix of the directory name.
171 */
172 static char *
transform_dir(char * dir)173 transform_dir(char *dir)
174 {
175 #ifdef DISK_HOME_HACK
176 char *ch;
177 #endif /* DISK_HOME_HACK */
178 char *server;
179 struct sockaddr_in server_addr;
180 int s = RPC_ANYSOCK;
181 CLIENT *clnt;
182 struct hostent *hp;
183 struct timeval tmo = {10, 0};
184 char *dummystr;
185 amq_string *spp;
186
187 #ifdef DISK_HOME_HACK
188 if (ch = hack_name(dir))
189 return ch;
190 #endif /* DISK_HOME_HACK */
191
192 #ifdef HAVE_CNODEID
193 server = cluster_server();
194 #else /* not HAVE_CNODEID */
195 server = localhost;
196 #endif /* not HAVE_CNODEID */
197
198 if ((hp = gethostbyname(server)) == NULL)
199 return dir;
200 memset(&server_addr, 0, sizeof(server_addr));
201 /* as per POSIX, sin_len need not be set (used internally by kernel) */
202 server_addr.sin_family = AF_INET;
203 server_addr.sin_addr = *(struct in_addr *) hp->h_addr;
204
205 clnt = clntudp_create(&server_addr, AMQ_PROGRAM, AMQ_VERSION, tmo, &s);
206 if (clnt == NULL)
207 clnt = clnttcp_create(&server_addr, AMQ_PROGRAM, AMQ_VERSION, &s, 0, 0);
208 if (clnt == NULL)
209 return dir;
210
211 xstrlcpy(transform, dir, sizeof(transform));
212 dummystr = transform;
213 spp = amqproc_pawd_1((amq_string *) &dummystr, clnt);
214 if (spp && *spp && **spp) {
215 xstrlcpy(transform, *spp, sizeof(transform));
216 XFREE(*spp);
217 }
218 clnt_destroy(clnt);
219 return transform;
220 }
221
222
223 /* getawd() is a substitute for getwd() which transforms the path */
224 static char *
getawd(char * path,size_t l)225 getawd(char *path, size_t l)
226 {
227 #ifdef HAVE_GETCWD
228 char *wd = getcwd(path, MAXPATHLEN);
229 #else /* not HAVE_GETCWD */
230 char *wd = getwd(path);
231 #endif /* not HAVE_GETCWD */
232
233 if (wd == NULL) {
234 return NULL;
235 }
236 xstrlcpy(path, transform_dir(wd), l);
237 return path;
238 }
239
240
241 int
main(int argc,char * argv[])242 main(int argc, char *argv[])
243 {
244 char tmp_buf[MAXPATHLEN], *wd;
245
246 if (argc == 1) {
247 wd = getawd(tmp_buf, sizeof(tmp_buf));
248 if (wd == NULL) {
249 fprintf(stderr, "pawd: %s\n", tmp_buf);
250 exit(1);
251 } else {
252 fprintf(stdout, "%s\n", wd);
253 }
254 } else {
255 while (--argc) {
256 wd = transform_dir(*++argv);
257 fprintf(stdout, "%s\n", wd);
258 }
259 }
260 exit(0);
261 }
262