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