138494Sobrien/*
2310490Scy * Copyright (c) 1997-2014 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.
19310490Scy * 3. Neither the name of the University nor the names of its contributors
2038494Sobrien *    may be used to endorse or promote products derived from this software
2138494Sobrien *    without specific prior written permission.
2238494Sobrien *
2338494Sobrien * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2438494Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2538494Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2638494Sobrien * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2738494Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2838494Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2938494Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3038494Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3138494Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3238494Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3338494Sobrien * SUCH DAMAGE.
3438494Sobrien *
3538494Sobrien *
36174294Sobrien * File: am-utils/amq/pawd.c
3738494Sobrien *
3838494Sobrien */
3938494Sobrien
4038494Sobrien/*
4138494Sobrien * pawd is similar to pwd, except that it returns more "natural" versions of
4238494Sobrien * pathnames for directories automounted with the amd automounter.  If any
4338494Sobrien * arguments are given, the "more natural" form of the given pathnames are
4438494Sobrien * printed.
4538494Sobrien *
4638494Sobrien * Paul Anderson (paul@ed.lfcs)
4738494Sobrien *
4838494Sobrien */
4938494Sobrien
5038494Sobrien#ifdef HAVE_CONFIG_H
5138494Sobrien# include <config.h>
5238494Sobrien#endif /* HAVE_CONFIG_H */
5338494Sobrien#include <am_defs.h>
5438494Sobrien#include <amq.h>
5538494Sobrien
56174294Sobrien
5738494Sobrien/* statics */
58174294Sobrienstatic char *localhost = "localhost";
5938494Sobrienstatic char transform[MAXPATHLEN];
6038494Sobrien
6138494Sobrien
6238494Sobrien#ifdef HAVE_CNODEID
6338494Sobrienstatic char *
6438494Sobriencluster_server(void)
6538494Sobrien{
6638494Sobrien# ifdef HAVE_EXTERN_GETCCENT
6738494Sobrien  struct cct_entry *cp;
6838494Sobrien# endif /* HAVE_EXTERN_GETCCENT */
6938494Sobrien
7038494Sobrien  if (cnodeid() == 0)
7138494Sobrien    return localhost;
7238494Sobrien
7338494Sobrien# ifdef HAVE_EXTERN_GETCCENT
7438494Sobrien  while ((cp = getccent()))
7538494Sobrien    if (cp->cnode_type == 'r')
7638494Sobrien      return cp->cnode_name;
7738494Sobrien# endif /* HAVE_EXTERN_GETCCENT */
7838494Sobrien
7938494Sobrien  return localhost;
8038494Sobrien}
8138494Sobrien#endif /* HAVE_CNODEID */
8238494Sobrien
8338494Sobrien
8438494Sobrien/* DISK_HOME_HACK added by gdmr */
8538494Sobrien#ifdef DISK_HOME_HACK
8638494Sobrienstatic char *
8738494Sobrienhack_name(char *dir)
8838494Sobrien{
8938494Sobrien  char partition[MAXPATHLEN];
9038494Sobrien  char username[MAXPATHLEN];
9138494Sobrien  char hesiod_lookup[MAXPATHLEN];
9238494Sobrien  char *to, *ch, *hes_name, *dot;
9338494Sobrien  char **hes;
9438494Sobrien
9538494Sobrien#ifdef DEBUG
9638494Sobrien  fprintf(stderr, "hack_name(%s)\n", dir);
9738494Sobrien#endif /* DEBUG */
9838494Sobrien
9938494Sobrien  if (dir[0] == '/' && dir[1] == 'a' && dir[2] == '/') {
10038494Sobrien    /* Could be /a/server/disk/home/partition/user... */
10138494Sobrien    ch = dir + 3;
10238494Sobrien    while (*ch && *ch != '/') ch++;  /* Skip server */
10338494Sobrien    if (!NSTREQ(ch, "/disk/home/", 11))
10438494Sobrien      return NULL;		/* Nope */
10538494Sobrien    /* Looking promising, next should be the partition name */
10638494Sobrien    ch += 11;
10738494Sobrien    to = partition;
10838494Sobrien    while (*ch && *ch != '/') *to++ = *ch++;
10938494Sobrien    to = '\0';
11038494Sobrien    if (!(*ch))
11138494Sobrien      return NULL;		/* Off the end */
11238494Sobrien    /* Now the username */
11338494Sobrien    ch++;
11438494Sobrien    to = username;
11538494Sobrien    while (*ch && *ch != '/') *to++ = *ch++;
11638494Sobrien    to = '\0';
11738494Sobrien#ifdef DEBUG
11838494Sobrien    fprintf(stderr, "partition %s, username %s\n", partition, username);
11938494Sobrien#endif /* DEBUG */
12038494Sobrien
121174294Sobrien    xsnprintf(hesiod_lookup, sizeof(hesiod_lookup),
122174294Sobrien	      "%s.homes-remote", username);
12338494Sobrien    hes = hes_resolve(hesiod_lookup, "amd");
12438494Sobrien    if (!hes)
12538494Sobrien      return NULL;
12638494Sobrien#ifdef DEBUG
12738494Sobrien    fprintf(stderr, "hesiod -> <%s>\n", *hes);
12838494Sobrien#endif /* DEBUG */
12938494Sobrien    hes_name = strstr(*hes, "/homes/remote/");
13038494Sobrien    if (!hes_name) return NULL;
13138494Sobrien    hes_name += 14;
13238494Sobrien#ifdef DEBUG
13338494Sobrien    fprintf(stderr, "hesiod -> <%s>\n", hes_name);
13438494Sobrien#endif /* DEBUG */
13538494Sobrien    dot = hes_name;
13638494Sobrien    while (*dot && *dot != '.') dot++;
13738494Sobrien    *dot = '\0';
13838494Sobrien#ifdef DEBUG
13938494Sobrien    fprintf(stderr, "hesiod -> <%s>\n", hes_name);
14038494Sobrien#endif /* DEBUG */
14138494Sobrien
14238494Sobrien    if (strcmp(partition, hes_name)) return NULL;
14338494Sobrien#ifdef DEBUG
14438494Sobrien    fprintf(stderr, "A match, munging....\n");
14538494Sobrien#endif /* DEBUG */
146174294Sobrien    xstrlcpy(transform, "/home/", sizeof(transform));
147174294Sobrien    xstrlcat(transform, username, sizeof(transform));
148174294Sobrien    if (*ch)
149174294Sobrien      xstrlcat(transform, ch, sizeof(transform));
15038494Sobrien#ifdef DEBUG
15138494Sobrien    fprintf(stderr, "Munged to <%s>\n", transform);
15238494Sobrien#endif /* DEBUG */
15338494Sobrien    return transform;
15438494Sobrien  }
15538494Sobrien  return NULL;
15638494Sobrien}
15738494Sobrien#endif /* DISK_HOME_HACK */
15838494Sobrien
15938494Sobrien
16038494Sobrien/*
16138494Sobrien * The routine transform_dir(path) transforms pathnames of directories
16238494Sobrien * mounted with the amd automounter to produce a more "natural" version.
16338494Sobrien * The automount table is obtained from the local amd via the rpc interface
16438494Sobrien * and reverse lookups are repeatedly performed on the directory name
16538494Sobrien * substituting the name of the automount link for the value of the link
16638494Sobrien * whenever it occurs as a prefix of the directory name.
16738494Sobrien */
16838494Sobrienstatic char *
16938494Sobrientransform_dir(char *dir)
17038494Sobrien{
17138494Sobrien#ifdef DISK_HOME_HACK
17238494Sobrien  char *ch;
17338494Sobrien#endif /* DISK_HOME_HACK */
17438494Sobrien  char *server;
17538494Sobrien  struct sockaddr_in server_addr;
17638494Sobrien  int s = RPC_ANYSOCK;
17738494Sobrien  CLIENT *clnt;
17838494Sobrien  struct hostent *hp;
17938494Sobrien  struct timeval tmo = {10, 0};
180174294Sobrien  char *dummystr;
181174294Sobrien  amq_string *spp;
18238494Sobrien
18338494Sobrien#ifdef DISK_HOME_HACK
18438494Sobrien  if (ch = hack_name(dir))
18538494Sobrien    return ch;
18638494Sobrien#endif /* DISK_HOME_HACK */
18738494Sobrien
18838494Sobrien#ifdef HAVE_CNODEID
18938494Sobrien  server = cluster_server();
19038494Sobrien#else /* not HAVE_CNODEID */
19138494Sobrien  server = localhost;
19238494Sobrien#endif /* not HAVE_CNODEID */
19338494Sobrien
194174294Sobrien  if ((hp = gethostbyname(server)) == NULL)
19538494Sobrien    return dir;
19638494Sobrien  memset(&server_addr, 0, sizeof(server_addr));
197174294Sobrien  /* as per POSIX, sin_len need not be set (used internally by kernel) */
19838494Sobrien  server_addr.sin_family = AF_INET;
19938494Sobrien  server_addr.sin_addr = *(struct in_addr *) hp->h_addr;
20038494Sobrien
20138494Sobrien  clnt = clntudp_create(&server_addr, AMQ_PROGRAM, AMQ_VERSION, tmo, &s);
202174294Sobrien  if (clnt == NULL)
203174294Sobrien    clnt = clnttcp_create(&server_addr, AMQ_PROGRAM, AMQ_VERSION, &s, 0, 0);
204174294Sobrien  if (clnt == NULL)
20538494Sobrien    return dir;
20638494Sobrien
207174294Sobrien  xstrlcpy(transform, dir, sizeof(transform));
208174294Sobrien  dummystr = transform;
209174294Sobrien  spp = amqproc_pawd_1((amq_string *) &dummystr, clnt);
210174294Sobrien  if (spp && *spp && **spp) {
211174294Sobrien    xstrlcpy(transform, *spp, sizeof(transform));
212174294Sobrien    XFREE(*spp);
21338494Sobrien  }
214174294Sobrien  clnt_destroy(clnt);
21538494Sobrien  return transform;
21638494Sobrien}
21738494Sobrien
21838494Sobrien
21938494Sobrien/* getawd() is a substitute for getwd() which transforms the path */
22038494Sobrienstatic char *
221174294Sobriengetawd(char *path, size_t l)
22238494Sobrien{
22338494Sobrien#ifdef HAVE_GETCWD
224174294Sobrien  char *wd = getcwd(path, MAXPATHLEN);
22538494Sobrien#else /* not HAVE_GETCWD */
22638494Sobrien  char *wd = getwd(path);
22738494Sobrien#endif /* not HAVE_GETCWD */
22838494Sobrien
22938494Sobrien  if (wd == NULL) {
23038494Sobrien    return NULL;
23138494Sobrien  }
232174294Sobrien  xstrlcpy(path, transform_dir(wd), l);
23338494Sobrien  return path;
23438494Sobrien}
23538494Sobrien
23638494Sobrien
23738494Sobrienint
23838494Sobrienmain(int argc, char *argv[])
23938494Sobrien{
24038494Sobrien  char tmp_buf[MAXPATHLEN], *wd;
24138494Sobrien
24238494Sobrien  if (argc == 1) {
243174294Sobrien    wd = getawd(tmp_buf, sizeof(tmp_buf));
24438494Sobrien    if (wd == NULL) {
24538494Sobrien      fprintf(stderr, "pawd: %s\n", tmp_buf);
24638494Sobrien      exit(1);
24738494Sobrien    } else {
24838494Sobrien      fprintf(stdout, "%s\n", wd);
24938494Sobrien    }
25038494Sobrien  } else {
25138494Sobrien    while (--argc) {
25238494Sobrien      wd = transform_dir(*++argv);
25338494Sobrien      fprintf(stdout, "%s\n", wd);
25438494Sobrien    }
25538494Sobrien  }
25638494Sobrien  exit(0);
25738494Sobrien}
258