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