 |
|
|
| |
1 /*
2 * Copyright (c) 1997-2005 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 /* statics */
61 static char *localhost="localhost";
62 static char newdir[MAXPATHLEN];
63 static char transform[MAXPATHLEN];
64
65 static int
66 find_mt(amq_mount_tree *mt, char *dir)
67 {
68 while (mt) {
69 if (!STREQ(mt->mt_type, "toplvl")) {
70 int len = strlen(mt->mt_mountpoint);
71 if (len != 0 && NSTREQ(mt->mt_mountpoint, dir, len) &&
72 ((dir[len] == '\0') || (dir[len] == '/'))) {
73 char tmp_buf[MAXPATHLEN];
74 strcpy(tmp_buf, mt->mt_directory);
75 strcat(tmp_buf, &dir[len]);
76 strcpy(newdir, tmp_buf);
77 return 1;
78 }
79 }
80 if (find_mt(mt->mt_next,dir))
81 return 1;
82 mt = mt->mt_child;
83 }
84 return 0;
85 }
86
87
88 static int
89 find_mlp(amq_mount_tree_list *mlp, char *dir)
90 {
91 u_int i;
92
93 for (i = 0; i < mlp->amq_mount_tree_list_len; i++) {
94 if (find_mt(mlp->amq_mount_tree_list_val[i], dir))
95 return 1;
96 }
97 return 0;
98 }
99
100
101 #ifdef HAVE_CNODEID
102 static char *
103 cluster_server(void)
104 {
105 # ifdef HAVE_EXTERN_GETCCENT
106 struct cct_entry *cp;
107 # endif /* HAVE_EXTERN_GETCCENT */
108
109 if (cnodeid() == 0)
110 return localhost;
111
112 # ifdef HAVE_EXTERN_GETCCENT
113 while ((cp = getccent()))
114 if (cp->cnode_type == 'r')
115 return cp->cnode_name;
116 # endif /* HAVE_EXTERN_GETCCENT */
117
118 return localhost;
119 }
120 #endif /* HAVE_CNODEID */
121
122
123 /* DISK_HOME_HACK added by gdmr */
124 #ifdef DISK_HOME_HACK
125 static char *
126 hack_name(char *dir)
127 {
128 char partition[MAXPATHLEN];
129 char username[MAXPATHLEN];
130 char hesiod_lookup[MAXPATHLEN];
131 char *to, *ch, *hes_name, *dot;
132 char **hes;
133
134 #ifdef DEBUG
135 fprintf(stderr, "hack_name(%s)\n", dir);
136 #endif /* DEBUG */
137
138 if (dir[0] == '/' && dir[1] == 'a' && dir[2] == '/') {
139 /* Could be /a/server/disk/home/partition/user... */
140 ch = dir + 3;
141 while (*ch && *ch != '/') ch++; /* Skip server */
142 if (!NSTREQ(ch, "/disk/home/", 11))
143 return NULL; /* Nope */
144 /* Looking promising, next should be the partition name */
145 ch += 11;
146 to = partition;
147 while (*ch && *ch != '/') *to++ = *ch++;
148 to = '\0';
149 if (!(*ch))
150 return NULL; /* Off the end */
151 /* Now the username */
152 ch++;
153 to = username;
154 while (*ch && *ch != '/') *to++ = *ch++;
155 to = '\0';
156 #ifdef DEBUG
157 fprintf(stderr, "partition %s, username %s\n", partition, username);
158 #endif /* DEBUG */
159
160 sprintf(hesiod_lookup, "%s.homes-remote", username);
161 hes = hes_resolve(hesiod_lookup, "amd");
162 if (!hes)
163 return NULL;
164 #ifdef DEBUG
165 fprintf(stderr, "hesiod -> <%s>\n", *hes);
166 #endif /* DEBUG */
167 hes_name = strstr(*hes, "/homes/remote/");
168 if (!hes_name) return NULL;
169 hes_name += 14;
170 #ifdef DEBUG
171 fprintf(stderr, "hesiod -> <%s>\n", hes_name);
172 #endif /* DEBUG */
173 dot = hes_name;
174 while (*dot && *dot != '.') dot++;
175 *dot = '\0';
176 #ifdef DEBUG
177 fprintf(stderr, "hesiod -> <%s>\n", hes_name);
178 #endif /* DEBUG */
179
180 if (strcmp(partition, hes_name)) return NULL;
181 #ifdef DEBUG
182 fprintf(stderr, "A match, munging....\n");
183 #endif /* DEBUG */
184 strcpy(transform, "/home/");
185 strcat(transform, username);
186 if (*ch) strcat(transform, ch);
187 #ifdef DEBUG
188 fprintf(stderr, "Munged to <%s>\n", transform);
189 #endif /* DEBUG */
190 return transform;
191 }
192 return NULL;
193 }
194 #endif /* DISK_HOME_HACK */
195
196
197 /*
198 * The routine transform_dir(path) transforms pathnames of directories
199 * mounted with the amd automounter to produce a more "natural" version.
200 * The automount table is obtained from the local amd via the rpc interface
201 * and reverse lookups are repeatedly performed on the directory name
202 * substituting the name of the automount link for the value of the link
203 * whenever it occurs as a prefix of the directory name.
204 */
205 static char *
206 transform_dir(char *dir)
207 {
208 #ifdef DISK_HOME_HACK
209 char *ch;
210 #endif /* DISK_HOME_HACK */
211 char *server;
212 struct sockaddr_in server_addr;
213 int s = RPC_ANYSOCK;
214 CLIENT *clnt;
215 struct hostent *hp;
216 amq_mount_tree_list *mlp;
217 struct timeval tmo = {10, 0};
218
219 #ifdef DISK_HOME_HACK
220 if (ch = hack_name(dir))
221 return ch;
222 #endif /* DISK_HOME_HACK */
223
224 #ifdef HAVE_CNODEID
225 server = cluster_server();
226 #else /* not HAVE_CNODEID */
227 server = localhost;
228 #endif /* not HAVE_CNODEID */
229
230 if ((hp = gethostbyname(server)) == 0)
231 return dir;
232 memset(&server_addr, 0, sizeof(server_addr));
233 server_addr.sin_family = AF_INET;
234 server_addr.sin_addr = *(struct in_addr *) hp->h_addr;
235
236 clnt = clntudp_create(&server_addr, AMQ_PROGRAM, AMQ_VERSION, tmo, &s);
237 if (clnt == 0)
238 return dir;
239
240 strcpy(transform,dir);
241 while ( (mlp = amqproc_export_1((voidp)0, clnt)) &&
242 find_mlp(mlp,transform) ) {
243 strcpy(transform,newdir);
244 }
245 return transform;
246 }
247
248
249 /* getawd() is a substitute for getwd() which transforms the path */
250 static char *
251 getawd(char *path)
252 {
253 #ifdef HAVE_GETCWD
254 char *wd = getcwd(path, MAXPATHLEN);
255 #else /* not HAVE_GETCWD */
256 char *wd = getwd(path);
257 #endif /* not HAVE_GETCWD */
258
259 if (wd == NULL) {
260 return NULL;
261 }
262 strcpy(path, transform_dir(wd));
263 return path;
264 }
265
266
267 int
268 main(int argc, char *argv[])
269 {
270 char tmp_buf[MAXPATHLEN], *wd;
271
272 if (argc == 1) {
273 wd = getawd(tmp_buf);
274 if (wd == NULL) {
275 fprintf(stderr, "pawd: %s\n", tmp_buf);
276 exit(1);
277 } else {
278 fprintf(stdout, "%s\n", wd);
279 }
280 } else {
281 while (--argc) {
282 wd = transform_dir(*++argv);
283 fprintf(stdout, "%s\n", wd);
284 }
285 }
286 exit(0);
287 }
288