xref: /netbsd-src/external/bsd/am-utils/dist/amq/pawd.c (revision 8bae5d409deb915cf7c8f0539fae22ff2cb8a313)
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