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 */
60 static char *localhost = "localhost";
61 static char transform[MAXPATHLEN];
62
63
64 #ifdef HAVE_CNODEID
65 static char *
cluster_server(void)66 cluster_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
88 static char *
hack_name(char * dir)89 hack_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 */
170 static char *
transform_dir(char * dir)171 transform_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 */
222 static char *
getawd(char * path,size_t l)223 getawd(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
239 int
main(int argc,char * argv[])240 main(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