1/* 2 * Copyright (c) 1997-2014 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. Neither the name of the University nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 * 35 * 36 * File: am-utils/amq/pawd.c 37 * 38 */ 39 40/* 41 * pawd is similar to pwd, except that it returns more "natural" versions of 42 * pathnames for directories automounted with the amd automounter. If any 43 * arguments are given, the "more natural" form of the given pathnames are 44 * printed. 45 * 46 * Paul Anderson (paul@ed.lfcs) 47 * 48 */ 49 50#ifdef HAVE_CONFIG_H 51# include <config.h> 52#endif /* HAVE_CONFIG_H */ 53#include <am_defs.h> 54#include <amq.h> 55 56 57/* statics */ 58static char *localhost = "localhost"; 59static char transform[MAXPATHLEN]; 60 61 62#ifdef HAVE_CNODEID 63static char * 64cluster_server(void) 65{ 66# ifdef HAVE_EXTERN_GETCCENT 67 struct cct_entry *cp; 68# endif /* HAVE_EXTERN_GETCCENT */ 69 70 if (cnodeid() == 0) 71 return localhost; 72 73# ifdef HAVE_EXTERN_GETCCENT 74 while ((cp = getccent())) 75 if (cp->cnode_type == 'r') 76 return cp->cnode_name; 77# endif /* HAVE_EXTERN_GETCCENT */ 78 79 return localhost; 80} 81#endif /* HAVE_CNODEID */ 82 83 84/* DISK_HOME_HACK added by gdmr */ 85#ifdef DISK_HOME_HACK 86static char * 87hack_name(char *dir) 88{ 89 char partition[MAXPATHLEN]; 90 char username[MAXPATHLEN]; 91 char hesiod_lookup[MAXPATHLEN]; 92 char *to, *ch, *hes_name, *dot; 93 char **hes; 94 95#ifdef DEBUG 96 fprintf(stderr, "hack_name(%s)\n", dir); 97#endif /* DEBUG */ 98 99 if (dir[0] == '/' && dir[1] == 'a' && dir[2] == '/') { 100 /* Could be /a/server/disk/home/partition/user... */ 101 ch = dir + 3; 102 while (*ch && *ch != '/') ch++; /* Skip server */ 103 if (!NSTREQ(ch, "/disk/home/", 11)) 104 return NULL; /* Nope */ 105 /* Looking promising, next should be the partition name */ 106 ch += 11; 107 to = partition; 108 while (*ch && *ch != '/') *to++ = *ch++; 109 to = '\0'; 110 if (!(*ch)) 111 return NULL; /* Off the end */ 112 /* Now the username */ 113 ch++; 114 to = username; 115 while (*ch && *ch != '/') *to++ = *ch++; 116 to = '\0'; 117#ifdef DEBUG 118 fprintf(stderr, "partition %s, username %s\n", partition, username); 119#endif /* DEBUG */ 120 121 xsnprintf(hesiod_lookup, sizeof(hesiod_lookup), 122 "%s.homes-remote", username); 123 hes = hes_resolve(hesiod_lookup, "amd"); 124 if (!hes) 125 return NULL; 126#ifdef DEBUG 127 fprintf(stderr, "hesiod -> <%s>\n", *hes); 128#endif /* DEBUG */ 129 hes_name = strstr(*hes, "/homes/remote/"); 130 if (!hes_name) return NULL; 131 hes_name += 14; 132#ifdef DEBUG 133 fprintf(stderr, "hesiod -> <%s>\n", hes_name); 134#endif /* DEBUG */ 135 dot = hes_name; 136 while (*dot && *dot != '.') dot++; 137 *dot = '\0'; 138#ifdef DEBUG 139 fprintf(stderr, "hesiod -> <%s>\n", hes_name); 140#endif /* DEBUG */ 141 142 if (strcmp(partition, hes_name)) return NULL; 143#ifdef DEBUG 144 fprintf(stderr, "A match, munging....\n"); 145#endif /* DEBUG */ 146 xstrlcpy(transform, "/home/", sizeof(transform)); 147 xstrlcat(transform, username, sizeof(transform)); 148 if (*ch) 149 xstrlcat(transform, ch, sizeof(transform)); 150#ifdef DEBUG 151 fprintf(stderr, "Munged to <%s>\n", transform); 152#endif /* DEBUG */ 153 return transform; 154 } 155 return NULL; 156} 157#endif /* DISK_HOME_HACK */ 158 159 160/* 161 * The routine transform_dir(path) transforms pathnames of directories 162 * mounted with the amd automounter to produce a more "natural" version. 163 * The automount table is obtained from the local amd via the rpc interface 164 * and reverse lookups are repeatedly performed on the directory name 165 * substituting the name of the automount link for the value of the link 166 * whenever it occurs as a prefix of the directory name. 167 */ 168static char * 169transform_dir(char *dir) 170{ 171#ifdef DISK_HOME_HACK 172 char *ch; 173#endif /* DISK_HOME_HACK */ 174 char *server; 175 struct sockaddr_in server_addr; 176 int s = RPC_ANYSOCK; 177 CLIENT *clnt; 178 struct hostent *hp; 179 struct timeval tmo = {10, 0}; 180 char *dummystr; 181 amq_string *spp; 182 183#ifdef DISK_HOME_HACK 184 if (ch = hack_name(dir)) 185 return ch; 186#endif /* DISK_HOME_HACK */ 187 188#ifdef HAVE_CNODEID 189 server = cluster_server(); 190#else /* not HAVE_CNODEID */ 191 server = localhost; 192#endif /* not HAVE_CNODEID */ 193 194 if ((hp = gethostbyname(server)) == NULL) 195 return dir; 196 memset(&server_addr, 0, sizeof(server_addr)); 197 /* as per POSIX, sin_len need not be set (used internally by kernel) */ 198 server_addr.sin_family = AF_INET; 199 server_addr.sin_addr = *(struct in_addr *) hp->h_addr; 200 201 clnt = clntudp_create(&server_addr, AMQ_PROGRAM, AMQ_VERSION, tmo, &s); 202 if (clnt == NULL) 203 clnt = clnttcp_create(&server_addr, AMQ_PROGRAM, AMQ_VERSION, &s, 0, 0); 204 if (clnt == NULL) 205 return dir; 206 207 xstrlcpy(transform, dir, sizeof(transform)); 208 dummystr = transform; 209 spp = amqproc_pawd_1((amq_string *) &dummystr, clnt); 210 if (spp && *spp && **spp) { 211 xstrlcpy(transform, *spp, sizeof(transform)); 212 XFREE(*spp); 213 } 214 clnt_destroy(clnt); 215 return transform; 216} 217 218 219/* getawd() is a substitute for getwd() which transforms the path */ 220static char * 221getawd(char *path, size_t l) 222{ 223#ifdef HAVE_GETCWD 224 char *wd = getcwd(path, MAXPATHLEN); 225#else /* not HAVE_GETCWD */ 226 char *wd = getwd(path); 227#endif /* not HAVE_GETCWD */ 228 229 if (wd == NULL) { 230 return NULL; 231 } 232 xstrlcpy(path, transform_dir(wd), l); 233 return path; 234} 235 236 237int 238main(int argc, char *argv[]) 239{ 240 char tmp_buf[MAXPATHLEN], *wd; 241 242 if (argc == 1) { 243 wd = getawd(tmp_buf, sizeof(tmp_buf)); 244 if (wd == NULL) { 245 fprintf(stderr, "pawd: %s\n", tmp_buf); 246 exit(1); 247 } else { 248 fprintf(stdout, "%s\n", wd); 249 } 250 } else { 251 while (--argc) { 252 wd = transform_dir(*++argv); 253 fprintf(stdout, "%s\n", wd); 254 } 255 } 256 exit(0); 257} 258