138494Sobrien/*
2174294Sobrien * Copyright (c) 1997-2006 Erez Zadok
338494Sobrien * Copyright (c) 1990 Jan-Simon Pendry
438494Sobrien * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
538494Sobrien * Copyright (c) 1990 The Regents of the University of California.
638494Sobrien * All rights reserved.
738494Sobrien *
838494Sobrien * This code is derived from software contributed to Berkeley by
938494Sobrien * Jan-Simon Pendry at Imperial College, London.
1038494Sobrien *
1138494Sobrien * Redistribution and use in source and binary forms, with or without
1238494Sobrien * modification, are permitted provided that the following conditions
1338494Sobrien * are met:
1438494Sobrien * 1. Redistributions of source code must retain the above copyright
1538494Sobrien *    notice, this list of conditions and the following disclaimer.
1638494Sobrien * 2. Redistributions in binary form must reproduce the above copyright
1738494Sobrien *    notice, this list of conditions and the following disclaimer in the
1838494Sobrien *    documentation and/or other materials provided with the distribution.
1938494Sobrien * 3. All advertising materials mentioning features or use of this software
2042629Sobrien *    must display the following acknowledgment:
2138494Sobrien *      This product includes software developed by the University of
2238494Sobrien *      California, Berkeley and its contributors.
2338494Sobrien * 4. Neither the name of the University nor the names of its contributors
2438494Sobrien *    may be used to endorse or promote products derived from this software
2538494Sobrien *    without specific prior written permission.
2638494Sobrien *
2738494Sobrien * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2838494Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2938494Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
3038494Sobrien * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
3138494Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3238494Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3338494Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3438494Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3538494Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3638494Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3738494Sobrien * SUCH DAMAGE.
3838494Sobrien *
3938494Sobrien *
40174294Sobrien * File: am-utils/amq/pawd.c
4138494Sobrien *
4238494Sobrien */
4338494Sobrien
4438494Sobrien/*
4538494Sobrien * pawd is similar to pwd, except that it returns more "natural" versions of
4638494Sobrien * pathnames for directories automounted with the amd automounter.  If any
4738494Sobrien * arguments are given, the "more natural" form of the given pathnames are
4838494Sobrien * printed.
4938494Sobrien *
5038494Sobrien * Paul Anderson (paul@ed.lfcs)
5138494Sobrien *
5238494Sobrien */
5338494Sobrien
5438494Sobrien#ifdef HAVE_CONFIG_H
5538494Sobrien# include <config.h>
5638494Sobrien#endif /* HAVE_CONFIG_H */
5738494Sobrien#include <am_defs.h>
5838494Sobrien#include <amq.h>
5938494Sobrien
60174294Sobrien
6138494Sobrien/* statics */
62174294Sobrienstatic char *localhost = "localhost";
6338494Sobrienstatic char transform[MAXPATHLEN];
6438494Sobrien
6538494Sobrien
6638494Sobrien#ifdef HAVE_CNODEID
6738494Sobrienstatic char *
6838494Sobriencluster_server(void)
6938494Sobrien{
7038494Sobrien# ifdef HAVE_EXTERN_GETCCENT
7138494Sobrien  struct cct_entry *cp;
7238494Sobrien# endif /* HAVE_EXTERN_GETCCENT */
7338494Sobrien
7438494Sobrien  if (cnodeid() == 0)
7538494Sobrien    return localhost;
7638494Sobrien
7738494Sobrien# ifdef HAVE_EXTERN_GETCCENT
7838494Sobrien  while ((cp = getccent()))
7938494Sobrien    if (cp->cnode_type == 'r')
8038494Sobrien      return cp->cnode_name;
8138494Sobrien# endif /* HAVE_EXTERN_GETCCENT */
8238494Sobrien
8338494Sobrien  return localhost;
8438494Sobrien}
8538494Sobrien#endif /* HAVE_CNODEID */
8638494Sobrien
8738494Sobrien
8838494Sobrien/* DISK_HOME_HACK added by gdmr */
8938494Sobrien#ifdef DISK_HOME_HACK
9038494Sobrienstatic char *
9138494Sobrienhack_name(char *dir)
9238494Sobrien{
9338494Sobrien  char partition[MAXPATHLEN];
9438494Sobrien  char username[MAXPATHLEN];
9538494Sobrien  char hesiod_lookup[MAXPATHLEN];
9638494Sobrien  char *to, *ch, *hes_name, *dot;
9738494Sobrien  char **hes;
9838494Sobrien
9938494Sobrien#ifdef DEBUG
10038494Sobrien  fprintf(stderr, "hack_name(%s)\n", dir);
10138494Sobrien#endif /* DEBUG */
10238494Sobrien
10338494Sobrien  if (dir[0] == '/' && dir[1] == 'a' && dir[2] == '/') {
10438494Sobrien    /* Could be /a/server/disk/home/partition/user... */
10538494Sobrien    ch = dir + 3;
10638494Sobrien    while (*ch && *ch != '/') ch++;  /* Skip server */
10738494Sobrien    if (!NSTREQ(ch, "/disk/home/", 11))
10838494Sobrien      return NULL;		/* Nope */
10938494Sobrien    /* Looking promising, next should be the partition name */
11038494Sobrien    ch += 11;
11138494Sobrien    to = partition;
11238494Sobrien    while (*ch && *ch != '/') *to++ = *ch++;
11338494Sobrien    to = '\0';
11438494Sobrien    if (!(*ch))
11538494Sobrien      return NULL;		/* Off the end */
11638494Sobrien    /* Now the username */
11738494Sobrien    ch++;
11838494Sobrien    to = username;
11938494Sobrien    while (*ch && *ch != '/') *to++ = *ch++;
12038494Sobrien    to = '\0';
12138494Sobrien#ifdef DEBUG
12238494Sobrien    fprintf(stderr, "partition %s, username %s\n", partition, username);
12338494Sobrien#endif /* DEBUG */
12438494Sobrien
125174294Sobrien    xsnprintf(hesiod_lookup, sizeof(hesiod_lookup),
126174294Sobrien	      "%s.homes-remote", username);
12738494Sobrien    hes = hes_resolve(hesiod_lookup, "amd");
12838494Sobrien    if (!hes)
12938494Sobrien      return NULL;
13038494Sobrien#ifdef DEBUG
13138494Sobrien    fprintf(stderr, "hesiod -> <%s>\n", *hes);
13238494Sobrien#endif /* DEBUG */
13338494Sobrien    hes_name = strstr(*hes, "/homes/remote/");
13438494Sobrien    if (!hes_name) return NULL;
13538494Sobrien    hes_name += 14;
13638494Sobrien#ifdef DEBUG
13738494Sobrien    fprintf(stderr, "hesiod -> <%s>\n", hes_name);
13838494Sobrien#endif /* DEBUG */
13938494Sobrien    dot = hes_name;
14038494Sobrien    while (*dot && *dot != '.') dot++;
14138494Sobrien    *dot = '\0';
14238494Sobrien#ifdef DEBUG
14338494Sobrien    fprintf(stderr, "hesiod -> <%s>\n", hes_name);
14438494Sobrien#endif /* DEBUG */
14538494Sobrien
14638494Sobrien    if (strcmp(partition, hes_name)) return NULL;
14738494Sobrien#ifdef DEBUG
14838494Sobrien    fprintf(stderr, "A match, munging....\n");
14938494Sobrien#endif /* DEBUG */
150174294Sobrien    xstrlcpy(transform, "/home/", sizeof(transform));
151174294Sobrien    xstrlcat(transform, username, sizeof(transform));
152174294Sobrien    if (*ch)
153174294Sobrien      xstrlcat(transform, ch, sizeof(transform));
15438494Sobrien#ifdef DEBUG
15538494Sobrien    fprintf(stderr, "Munged to <%s>\n", transform);
15638494Sobrien#endif /* DEBUG */
15738494Sobrien    return transform;
15838494Sobrien  }
15938494Sobrien  return NULL;
16038494Sobrien}
16138494Sobrien#endif /* DISK_HOME_HACK */
16238494Sobrien
16338494Sobrien
16438494Sobrien/*
16538494Sobrien * The routine transform_dir(path) transforms pathnames of directories
16638494Sobrien * mounted with the amd automounter to produce a more "natural" version.
16738494Sobrien * The automount table is obtained from the local amd via the rpc interface
16838494Sobrien * and reverse lookups are repeatedly performed on the directory name
16938494Sobrien * substituting the name of the automount link for the value of the link
17038494Sobrien * whenever it occurs as a prefix of the directory name.
17138494Sobrien */
17238494Sobrienstatic char *
17338494Sobrientransform_dir(char *dir)
17438494Sobrien{
17538494Sobrien#ifdef DISK_HOME_HACK
17638494Sobrien  char *ch;
17738494Sobrien#endif /* DISK_HOME_HACK */
17838494Sobrien  char *server;
17938494Sobrien  struct sockaddr_in server_addr;
18038494Sobrien  int s = RPC_ANYSOCK;
18138494Sobrien  CLIENT *clnt;
18238494Sobrien  struct hostent *hp;
18338494Sobrien  struct timeval tmo = {10, 0};
184174294Sobrien  char *dummystr;
185174294Sobrien  amq_string *spp;
18638494Sobrien
18738494Sobrien#ifdef DISK_HOME_HACK
18838494Sobrien  if (ch = hack_name(dir))
18938494Sobrien    return ch;
19038494Sobrien#endif /* DISK_HOME_HACK */
19138494Sobrien
19238494Sobrien#ifdef HAVE_CNODEID
19338494Sobrien  server = cluster_server();
19438494Sobrien#else /* not HAVE_CNODEID */
19538494Sobrien  server = localhost;
19638494Sobrien#endif /* not HAVE_CNODEID */
19738494Sobrien
198174294Sobrien  if ((hp = gethostbyname(server)) == NULL)
19938494Sobrien    return dir;
20038494Sobrien  memset(&server_addr, 0, sizeof(server_addr));
201174294Sobrien  /* as per POSIX, sin_len need not be set (used internally by kernel) */
20238494Sobrien  server_addr.sin_family = AF_INET;
20338494Sobrien  server_addr.sin_addr = *(struct in_addr *) hp->h_addr;
20438494Sobrien
20538494Sobrien  clnt = clntudp_create(&server_addr, AMQ_PROGRAM, AMQ_VERSION, tmo, &s);
206174294Sobrien  if (clnt == NULL)
207174294Sobrien    clnt = clnttcp_create(&server_addr, AMQ_PROGRAM, AMQ_VERSION, &s, 0, 0);
208174294Sobrien  if (clnt == NULL)
20938494Sobrien    return dir;
21038494Sobrien
211174294Sobrien  xstrlcpy(transform, dir, sizeof(transform));
212174294Sobrien  dummystr = transform;
213174294Sobrien  spp = amqproc_pawd_1((amq_string *) &dummystr, clnt);
214174294Sobrien  if (spp && *spp && **spp) {
215174294Sobrien    xstrlcpy(transform, *spp, sizeof(transform));
216174294Sobrien    XFREE(*spp);
21738494Sobrien  }
218174294Sobrien  clnt_destroy(clnt);
21938494Sobrien  return transform;
22038494Sobrien}
22138494Sobrien
22238494Sobrien
22338494Sobrien/* getawd() is a substitute for getwd() which transforms the path */
22438494Sobrienstatic char *
225174294Sobriengetawd(char *path, size_t l)
22638494Sobrien{
22738494Sobrien#ifdef HAVE_GETCWD
228174294Sobrien  char *wd = getcwd(path, MAXPATHLEN);
22938494Sobrien#else /* not HAVE_GETCWD */
23038494Sobrien  char *wd = getwd(path);
23138494Sobrien#endif /* not HAVE_GETCWD */
23238494Sobrien
23338494Sobrien  if (wd == NULL) {
23438494Sobrien    return NULL;
23538494Sobrien  }
236174294Sobrien  xstrlcpy(path, transform_dir(wd), l);
23738494Sobrien  return path;
23838494Sobrien}
23938494Sobrien
24038494Sobrien
24138494Sobrienint
24238494Sobrienmain(int argc, char *argv[])
24338494Sobrien{
24438494Sobrien  char tmp_buf[MAXPATHLEN], *wd;
24538494Sobrien
24638494Sobrien  if (argc == 1) {
247174294Sobrien    wd = getawd(tmp_buf, sizeof(tmp_buf));
24838494Sobrien    if (wd == NULL) {
24938494Sobrien      fprintf(stderr, "pawd: %s\n", tmp_buf);
25038494Sobrien      exit(1);
25138494Sobrien    } else {
25238494Sobrien      fprintf(stdout, "%s\n", wd);
25338494Sobrien    }
25438494Sobrien  } else {
25538494Sobrien    while (--argc) {
25638494Sobrien      wd = transform_dir(*++argv);
25738494Sobrien      fprintf(stdout, "%s\n", wd);
25838494Sobrien    }
25938494Sobrien  }
26038494Sobrien  exit(0);
26138494Sobrien}
262