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