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