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