pawd.c revision 174295
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 */
62static char *localhost = "localhost";
63static char transform[MAXPATHLEN];
64
65
66#ifdef HAVE_CNODEID
67static char *
68cluster_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
90static char *
91hack_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 */
172static char *
173transform_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 */
224static char *
225getawd(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
241int
242main(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