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