pawd.c revision 82794
1/*
2 * Copyright (c) 1997-2001 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.6.2.1 2001/01/10 03:23:14 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 */
62static char *localhost="localhost";
63static char newdir[MAXPATHLEN];
64static char transform[MAXPATHLEN];
65
66static int
67find_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
91static int
92find_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
105static char *
106cluster_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
128static char *
129hack_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 */
208static char *
209transform_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 */
253static char *
254getawd(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
270int
271main(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}
291