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