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