pawd.c revision 119679
1/* 2 * Copyright (c) 1997-2003 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 * %W% (Berkeley) %G% 40 * 41 * $Id: pawd.c,v 1.6.2.3 2002/12/27 22:44:46 ezk Exp $ 42 * 43 */ 44 45/* 46 * pawd is similar to pwd, except that it returns more "natural" versions of 47 * pathnames for directories automounted with the amd automounter. If any 48 * arguments are given, the "more natural" form of the given pathnames are 49 * printed. 50 * 51 * Paul Anderson (paul@ed.lfcs) 52 * 53 */ 54 55#ifdef HAVE_CONFIG_H 56# include <config.h> 57#endif /* HAVE_CONFIG_H */ 58#include <am_defs.h> 59#include <amq.h> 60 61/* statics */ 62static char *localhost="localhost"; 63static char newdir[MAXPATHLEN]; 64static char transform[MAXPATHLEN]; 65 66static int 67find_mt(amq_mount_tree *mt, char *dir) 68{ 69 while (mt) { 70 if (STREQ(mt->mt_type, "link") || 71 STREQ(mt->mt_type, "nfs") || 72 STREQ(mt->mt_type, "nfsl")) { 73 int len = strlen(mt->mt_mountpoint); 74 if (NSTREQ(mt->mt_mountpoint, dir, len) && 75 ((dir[len] == '\0') || (dir[len] == '/'))) { 76 char tmp_buf[MAXPATHLEN]; 77 strcpy(tmp_buf, mt->mt_directory); 78 strcat(tmp_buf, &dir[len]); 79 strcpy(newdir, tmp_buf); 80 return 1; 81 } 82 } 83 if (find_mt(mt->mt_next,dir)) 84 return 1; 85 mt = mt->mt_child; 86 } 87 return 0; 88} 89 90 91static int 92find_mlp(amq_mount_tree_list *mlp, char *dir) 93{ 94 int i; 95 96 for (i = 0; i < mlp->amq_mount_tree_list_len; i++) { 97 if (find_mt(mlp->amq_mount_tree_list_val[i], dir)) 98 return 1; 99 } 100 return 0; 101} 102 103 104#ifdef HAVE_CNODEID 105static char * 106cluster_server(void) 107{ 108# ifdef HAVE_EXTERN_GETCCENT 109 struct cct_entry *cp; 110# endif /* HAVE_EXTERN_GETCCENT */ 111 112 if (cnodeid() == 0) 113 return localhost; 114 115# ifdef HAVE_EXTERN_GETCCENT 116 while ((cp = getccent())) 117 if (cp->cnode_type == 'r') 118 return cp->cnode_name; 119# endif /* HAVE_EXTERN_GETCCENT */ 120 121 return localhost; 122} 123#endif /* HAVE_CNODEID */ 124 125 126/* DISK_HOME_HACK added by gdmr */ 127#ifdef DISK_HOME_HACK 128static char * 129hack_name(char *dir) 130{ 131 char partition[MAXPATHLEN]; 132 char username[MAXPATHLEN]; 133 char hesiod_lookup[MAXPATHLEN]; 134 char *to, *ch, *hes_name, *dot; 135 char **hes; 136 137#ifdef DEBUG 138 fprintf(stderr, "hack_name(%s)\n", dir); 139#endif /* DEBUG */ 140 141 if (dir[0] == '/' && dir[1] == 'a' && dir[2] == '/') { 142 /* Could be /a/server/disk/home/partition/user... */ 143 ch = dir + 3; 144 while (*ch && *ch != '/') ch++; /* Skip server */ 145 if (!NSTREQ(ch, "/disk/home/", 11)) 146 return NULL; /* Nope */ 147 /* Looking promising, next should be the partition name */ 148 ch += 11; 149 to = partition; 150 while (*ch && *ch != '/') *to++ = *ch++; 151 to = '\0'; 152 if (!(*ch)) 153 return NULL; /* Off the end */ 154 /* Now the username */ 155 ch++; 156 to = username; 157 while (*ch && *ch != '/') *to++ = *ch++; 158 to = '\0'; 159#ifdef DEBUG 160 fprintf(stderr, "partition %s, username %s\n", partition, username); 161#endif /* DEBUG */ 162 163 sprintf(hesiod_lookup, "%s.homes-remote", username); 164 hes = hes_resolve(hesiod_lookup, "amd"); 165 if (!hes) 166 return NULL; 167#ifdef DEBUG 168 fprintf(stderr, "hesiod -> <%s>\n", *hes); 169#endif /* DEBUG */ 170 hes_name = strstr(*hes, "/homes/remote/"); 171 if (!hes_name) return NULL; 172 hes_name += 14; 173#ifdef DEBUG 174 fprintf(stderr, "hesiod -> <%s>\n", hes_name); 175#endif /* DEBUG */ 176 dot = hes_name; 177 while (*dot && *dot != '.') dot++; 178 *dot = '\0'; 179#ifdef DEBUG 180 fprintf(stderr, "hesiod -> <%s>\n", hes_name); 181#endif /* DEBUG */ 182 183 if (strcmp(partition, hes_name)) return NULL; 184#ifdef DEBUG 185 fprintf(stderr, "A match, munging....\n"); 186#endif /* DEBUG */ 187 strcpy(transform, "/home/"); 188 strcat(transform, username); 189 if (*ch) strcat(transform, ch); 190#ifdef DEBUG 191 fprintf(stderr, "Munged to <%s>\n", transform); 192#endif /* DEBUG */ 193 return transform; 194 } 195 return NULL; 196} 197#endif /* DISK_HOME_HACK */ 198 199 200/* 201 * The routine transform_dir(path) transforms pathnames of directories 202 * mounted with the amd automounter to produce a more "natural" version. 203 * The automount table is obtained from the local amd via the rpc interface 204 * and reverse lookups are repeatedly performed on the directory name 205 * substituting the name of the automount link for the value of the link 206 * whenever it occurs as a prefix of the directory name. 207 */ 208static char * 209transform_dir(char *dir) 210{ 211#ifdef DISK_HOME_HACK 212 char *ch; 213#endif /* DISK_HOME_HACK */ 214 char *server; 215 struct sockaddr_in server_addr; 216 int s = RPC_ANYSOCK; 217 CLIENT *clnt; 218 struct hostent *hp; 219 amq_mount_tree_list *mlp; 220 struct timeval tmo = {10, 0}; 221 222#ifdef DISK_HOME_HACK 223 if (ch = hack_name(dir)) 224 return ch; 225#endif /* DISK_HOME_HACK */ 226 227#ifdef HAVE_CNODEID 228 server = cluster_server(); 229#else /* not HAVE_CNODEID */ 230 server = localhost; 231#endif /* not HAVE_CNODEID */ 232 233 if ((hp = gethostbyname(server)) == 0) 234 return dir; 235 memset(&server_addr, 0, sizeof(server_addr)); 236 server_addr.sin_family = AF_INET; 237 server_addr.sin_addr = *(struct in_addr *) hp->h_addr; 238 239 clnt = clntudp_create(&server_addr, AMQ_PROGRAM, AMQ_VERSION, tmo, &s); 240 if (clnt == 0) 241 return dir; 242 243 strcpy(transform,dir); 244 while ( (mlp = amqproc_export_1((voidp)0, clnt)) && 245 find_mlp(mlp,transform) ) { 246 strcpy(transform,newdir); 247 } 248 return transform; 249} 250 251 252/* getawd() is a substitute for getwd() which transforms the path */ 253static char * 254getawd(char *path) 255{ 256#ifdef HAVE_GETCWD 257 char *wd = getcwd(path, MAXPATHLEN+1); 258#else /* not HAVE_GETCWD */ 259 char *wd = getwd(path); 260#endif /* not HAVE_GETCWD */ 261 262 if (wd == NULL) { 263 return NULL; 264 } 265 strcpy(path, transform_dir(wd)); 266 return path; 267} 268 269 270int 271main(int argc, char *argv[]) 272{ 273 char tmp_buf[MAXPATHLEN], *wd; 274 275 if (argc == 1) { 276 wd = getawd(tmp_buf); 277 if (wd == NULL) { 278 fprintf(stderr, "pawd: %s\n", tmp_buf); 279 exit(1); 280 } else { 281 fprintf(stdout, "%s\n", wd); 282 } 283 } else { 284 while (--argc) { 285 wd = transform_dir(*++argv); 286 fprintf(stdout, "%s\n", wd); 287 } 288 } 289 exit(0); 290} 291