pawd.c revision 38494
138494Sobrien/*
238494Sobrien * Copyright (c) 1997-1998 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
2038494Sobrien *    must display the following acknowledgement:
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 *      %W% (Berkeley) %G%
4038494Sobrien *
4138494Sobrien * $Id: pawd.c,v 5.2.2.1 1992/02/09 15:09:16 jsp beta $
4238494Sobrien *
4338494Sobrien */
4438494Sobrien
4538494Sobrien/*
4638494Sobrien * pawd is similar to pwd, except that it returns more "natural" versions of
4738494Sobrien * pathnames for directories automounted with the amd automounter.  If any
4838494Sobrien * arguments are given, the "more natural" form of the given pathnames are
4938494Sobrien * printed.
5038494Sobrien *
5138494Sobrien * Paul Anderson (paul@ed.lfcs)
5238494Sobrien *
5338494Sobrien */
5438494Sobrien
5538494Sobrien#ifdef HAVE_CONFIG_H
5638494Sobrien# include <config.h>
5738494Sobrien#endif /* HAVE_CONFIG_H */
5838494Sobrien#include <am_defs.h>
5938494Sobrien#include <amq.h>
6038494Sobrien
6138494Sobrien/* dummy variables */
6238494Sobrienchar *progname;
6338494Sobrienchar hostname[MAXHOSTNAMELEN];
6438494Sobrienint orig_umask, foreground, debug_flags;
6538494Sobrienpid_t mypid;
6638494Sobrienserv_state amd_state;
6738494Sobrien
6838494Sobrien/* statics */
6938494Sobrienstatic char *localhost="localhost";
7038494Sobrienstatic char newdir[MAXPATHLEN];
7138494Sobrienstatic char transform[MAXPATHLEN];
7238494Sobrien
7338494Sobrienstatic int
7438494Sobrienfind_mt(amq_mount_tree *mt, char *dir)
7538494Sobrien{
7638494Sobrien  while (mt) {
7738494Sobrien    if (STREQ(mt->mt_type, "link") || STREQ(mt->mt_type, "nfs")) {
7838494Sobrien      int len = strlen(mt->mt_mountpoint);
7938494Sobrien      if (NSTREQ(mt->mt_mountpoint, dir, len) &&
8038494Sobrien	  ((dir[len] == '\0') || (dir[len] == '/'))) {
8138494Sobrien	char tmp_buf[MAXPATHLEN];
8238494Sobrien	strcpy(tmp_buf, mt->mt_directory);
8338494Sobrien	strcat(tmp_buf, &dir[len]);
8438494Sobrien	strcpy(newdir, tmp_buf);
8538494Sobrien	return 1;
8638494Sobrien      }
8738494Sobrien    }
8838494Sobrien    if (find_mt(mt->mt_next,dir))
8938494Sobrien      return 1;
9038494Sobrien    mt = mt->mt_child;
9138494Sobrien  }
9238494Sobrien  return 0;
9338494Sobrien}
9438494Sobrien
9538494Sobrien
9638494Sobrienstatic int
9738494Sobrienfind_mlp(amq_mount_tree_list *mlp, char *dir)
9838494Sobrien{
9938494Sobrien  int i;
10038494Sobrien
10138494Sobrien  for (i = 0; i < mlp->amq_mount_tree_list_len; i++) {
10238494Sobrien    if (find_mt(mlp->amq_mount_tree_list_val[i], dir))
10338494Sobrien      return 1;
10438494Sobrien  }
10538494Sobrien  return 0;
10638494Sobrien}
10738494Sobrien
10838494Sobrien
10938494Sobrien#ifdef HAVE_CNODEID
11038494Sobrienstatic char *
11138494Sobriencluster_server(void)
11238494Sobrien{
11338494Sobrien# ifdef HAVE_EXTERN_GETCCENT
11438494Sobrien  struct cct_entry *cp;
11538494Sobrien# endif /* HAVE_EXTERN_GETCCENT */
11638494Sobrien
11738494Sobrien  if (cnodeid() == 0)
11838494Sobrien    return localhost;
11938494Sobrien
12038494Sobrien# ifdef HAVE_EXTERN_GETCCENT
12138494Sobrien  while ((cp = getccent()))
12238494Sobrien    if (cp->cnode_type == 'r')
12338494Sobrien      return cp->cnode_name;
12438494Sobrien# endif /* HAVE_EXTERN_GETCCENT */
12538494Sobrien
12638494Sobrien  return localhost;
12738494Sobrien}
12838494Sobrien#endif /* HAVE_CNODEID */
12938494Sobrien
13038494Sobrien
13138494Sobrien/* DISK_HOME_HACK added by gdmr */
13238494Sobrien#ifdef DISK_HOME_HACK
13338494Sobrienstatic char *
13438494Sobrienhack_name(char *dir)
13538494Sobrien{
13638494Sobrien  char partition[MAXPATHLEN];
13738494Sobrien  char username[MAXPATHLEN];
13838494Sobrien  char hesiod_lookup[MAXPATHLEN];
13938494Sobrien  char *to, *ch, *hes_name, *dot;
14038494Sobrien  char **hes;
14138494Sobrien
14238494Sobrien#ifdef DEBUG
14338494Sobrien  fprintf(stderr, "hack_name(%s)\n", dir);
14438494Sobrien#endif /* DEBUG */
14538494Sobrien
14638494Sobrien  if (dir[0] == '/' && dir[1] == 'a' && dir[2] == '/') {
14738494Sobrien    /* Could be /a/server/disk/home/partition/user... */
14838494Sobrien    ch = dir + 3;
14938494Sobrien    while (*ch && *ch != '/') ch++;  /* Skip server */
15038494Sobrien    if (!NSTREQ(ch, "/disk/home/", 11))
15138494Sobrien      return NULL;		/* Nope */
15238494Sobrien    /* Looking promising, next should be the partition name */
15338494Sobrien    ch += 11;
15438494Sobrien    to = partition;
15538494Sobrien    while (*ch && *ch != '/') *to++ = *ch++;
15638494Sobrien    to = '\0';
15738494Sobrien    if (!(*ch))
15838494Sobrien      return NULL;		/* Off the end */
15938494Sobrien    /* Now the username */
16038494Sobrien    ch++;
16138494Sobrien    to = username;
16238494Sobrien    while (*ch && *ch != '/') *to++ = *ch++;
16338494Sobrien    to = '\0';
16438494Sobrien#ifdef DEBUG
16538494Sobrien    fprintf(stderr, "partition %s, username %s\n", partition, username);
16638494Sobrien#endif /* DEBUG */
16738494Sobrien
16838494Sobrien    sprintf(hesiod_lookup, "%s.homes-remote", username);
16938494Sobrien    hes = hes_resolve(hesiod_lookup, "amd");
17038494Sobrien    if (!hes)
17138494Sobrien      return NULL;
17238494Sobrien#ifdef DEBUG
17338494Sobrien    fprintf(stderr, "hesiod -> <%s>\n", *hes);
17438494Sobrien#endif /* DEBUG */
17538494Sobrien    hes_name = strstr(*hes, "/homes/remote/");
17638494Sobrien    if (!hes_name) return NULL;
17738494Sobrien    hes_name += 14;
17838494Sobrien#ifdef DEBUG
17938494Sobrien    fprintf(stderr, "hesiod -> <%s>\n", hes_name);
18038494Sobrien#endif /* DEBUG */
18138494Sobrien    dot = hes_name;
18238494Sobrien    while (*dot && *dot != '.') dot++;
18338494Sobrien    *dot = '\0';
18438494Sobrien#ifdef DEBUG
18538494Sobrien    fprintf(stderr, "hesiod -> <%s>\n", hes_name);
18638494Sobrien#endif /* DEBUG */
18738494Sobrien
18838494Sobrien    if (strcmp(partition, hes_name)) return NULL;
18938494Sobrien#ifdef DEBUG
19038494Sobrien    fprintf(stderr, "A match, munging....\n");
19138494Sobrien#endif /* DEBUG */
19238494Sobrien    strcpy(transform, "/home/");
19338494Sobrien    strcat(transform, username);
19438494Sobrien    if (*ch) strcat(transform, ch);
19538494Sobrien#ifdef DEBUG
19638494Sobrien    fprintf(stderr, "Munged to <%s>\n", transform);
19738494Sobrien#endif /* DEBUG */
19838494Sobrien    return transform;
19938494Sobrien  }
20038494Sobrien  return NULL;
20138494Sobrien}
20238494Sobrien#endif /* DISK_HOME_HACK */
20338494Sobrien
20438494Sobrien
20538494Sobrien/*
20638494Sobrien * The routine transform_dir(path) transforms pathnames of directories
20738494Sobrien * mounted with the amd automounter to produce a more "natural" version.
20838494Sobrien * The automount table is obtained from the local amd via the rpc interface
20938494Sobrien * and reverse lookups are repeatedly performed on the directory name
21038494Sobrien * substituting the name of the automount link for the value of the link
21138494Sobrien * whenever it occurs as a prefix of the directory name.
21238494Sobrien */
21338494Sobrienstatic char *
21438494Sobrientransform_dir(char *dir)
21538494Sobrien{
21638494Sobrien#ifdef DISK_HOME_HACK
21738494Sobrien  char *ch;
21838494Sobrien#endif /* DISK_HOME_HACK */
21938494Sobrien  char *server;
22038494Sobrien  struct sockaddr_in server_addr;
22138494Sobrien  int s = RPC_ANYSOCK;
22238494Sobrien  CLIENT *clnt;
22338494Sobrien  struct hostent *hp;
22438494Sobrien  amq_mount_tree_list *mlp;
22538494Sobrien  struct timeval tmo = {10, 0};
22638494Sobrien
22738494Sobrien#ifdef DISK_HOME_HACK
22838494Sobrien  if (ch = hack_name(dir))
22938494Sobrien    return ch;
23038494Sobrien#endif /* DISK_HOME_HACK */
23138494Sobrien
23238494Sobrien#ifdef HAVE_CNODEID
23338494Sobrien  server = cluster_server();
23438494Sobrien#else /* not HAVE_CNODEID */
23538494Sobrien  server = localhost;
23638494Sobrien#endif /* not HAVE_CNODEID */
23738494Sobrien
23838494Sobrien  if ((hp = gethostbyname(server)) == 0)
23938494Sobrien    return dir;
24038494Sobrien  memset(&server_addr, 0, sizeof(server_addr));
24138494Sobrien  server_addr.sin_family = AF_INET;
24238494Sobrien  server_addr.sin_addr = *(struct in_addr *) hp->h_addr;
24338494Sobrien
24438494Sobrien  clnt = clntudp_create(&server_addr, AMQ_PROGRAM, AMQ_VERSION, tmo, &s);
24538494Sobrien  if (clnt == 0)
24638494Sobrien    return dir;
24738494Sobrien
24838494Sobrien  strcpy(transform,dir);
24938494Sobrien  while ( (mlp = amqproc_export_1((voidp)0, clnt)) &&
25038494Sobrien	  find_mlp(mlp,transform) ) {
25138494Sobrien    strcpy(transform,newdir);
25238494Sobrien  }
25338494Sobrien  return transform;
25438494Sobrien}
25538494Sobrien
25638494Sobrien
25738494Sobrien/* getawd() is a substitute for getwd() which transforms the path */
25838494Sobrienstatic char *
25938494Sobriengetawd(char *path)
26038494Sobrien{
26138494Sobrien#ifdef HAVE_GETCWD
26238494Sobrien  char *wd = getcwd(path, MAXPATHLEN+1);
26338494Sobrien#else /* not HAVE_GETCWD */
26438494Sobrien  char *wd = getwd(path);
26538494Sobrien#endif /* not HAVE_GETCWD */
26638494Sobrien
26738494Sobrien  if (wd == NULL) {
26838494Sobrien    return NULL;
26938494Sobrien  }
27038494Sobrien  strcpy(path, transform_dir(wd));
27138494Sobrien  return path;
27238494Sobrien}
27338494Sobrien
27438494Sobrien
27538494Sobrienint
27638494Sobrienmain(int argc, char *argv[])
27738494Sobrien{
27838494Sobrien  char tmp_buf[MAXPATHLEN], *wd;
27938494Sobrien
28038494Sobrien  if (argc == 1) {
28138494Sobrien    wd = getawd(tmp_buf);
28238494Sobrien    if (wd == NULL) {
28338494Sobrien      fprintf(stderr, "pawd: %s\n", tmp_buf);
28438494Sobrien      exit(1);
28538494Sobrien    } else {
28638494Sobrien      fprintf(stdout, "%s\n", wd);
28738494Sobrien    }
28838494Sobrien  } else {
28938494Sobrien    while (--argc) {
29038494Sobrien      wd = transform_dir(*++argv);
29138494Sobrien      fprintf(stdout, "%s\n", wd);
29238494Sobrien    }
29338494Sobrien  }
29438494Sobrien  exit(0);
29538494Sobrien}
29638494Sobrien
297