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