2 * Copyright (c) 1997-1999 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.
8 * This code is derived from software contributed to Berkeley by
9 * Jan-Simon Pendry at Imperial College, London.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
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.
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
41 * $Id: autil.c,v 1.3 1999/01/10 21:53:44 ezk Exp $
46 * utilities specified to amd, taken out of the older amd/util.c.
51 #endif /* HAVE_CONFIG_H */
55 int NumChild
= 0; /* number of children of primary amd */
56 static char invalid_keys
[] = "\"'!;@ \t\n";
58 #ifdef HAVE_TRANSPORT_TYPE_TLI
59 # define PARENT_USLEEP_TIME 100000 /* 0.1 seconds */
60 #endif /* HAVE_TRANSPORT_TYPE_TLI */
64 strealloc(char *p
, char *s
)
66 int len
= strlen(s
) + 1;
68 p
= (char *) xrealloc((voidp
) p
, len
);
73 #endif /* DEBUG_MEM */
79 strsplit(char *s
, int ch
, int qc
)
85 ivec
= (char **) xmalloc((ic
+ 1) * sizeof(char *));
93 while (*s
&& (ch
== ' ' ? (isascii(*s
) && isspace((int)*s
)) : *s
== ch
))
103 * remember start of string
110 while (*s
&& !(ch
== ' ' ? (isascii(*s
) && isspace((int)*s
)) : *s
== ch
)) {
116 while (*s
&& *s
!= qc
)
128 * save string in new ivec slot
131 ivec
= (char **) xrealloc((voidp
) ivec
, (ic
+ 1) * sizeof(char *));
134 plog(XLOG_DEBUG
, "strsplit saved \"%s\"", v
);
140 plog(XLOG_DEBUG
, "strsplit saved a total of %d strings", ic
);
150 * Strip off the trailing part of a domain
151 * to produce a short-form domain relative
152 * to the local host domain.
153 * Note that this has no effect if the domain
154 * names do not have the same number of
155 * components. If that restriction proves
156 * to be a problem then the loop needs recoding
157 * to skip from right to left and do partial
158 * matches along the way -- ie more expensive.
161 domain_strip(char *otherdom
, char *localdom
)
165 if ((p1
= strchr(otherdom
, '.')) &&
166 (p2
= strchr(localdom
, '.')) &&
167 STREQ(p1
+ 1, p2
+ 1))
173 * Normalize a host name
176 host_normalize(char **chp
)
179 * Normalize hosts is used to resolve host name aliases
180 * and replace them with the standard-form name.
181 * Invoked with "-n" command line option.
183 if (gopt
.flags
& CFM_NORMALIZE_HOSTNAMES
) {
186 hp
= gethostbyname(*chp
);
187 if (hp
&& hp
->h_addrtype
== AF_INET
) {
189 dlog("Hostname %s normalized to %s", *chp
, hp
->h_name
);
191 *chp
= strealloc(*chp
, (char *) hp
->h_name
);
194 domain_strip(*chp
, hostd
);
200 * Keys are not allowed to contain " ' ! or ; to avoid
201 * problems with macro expansions.
207 if (strchr(invalid_keys
, *key
++))
214 forcibly_timeout_mp(am_node
*mp
)
216 mntfs
*mf
= mp
->am_mnt
;
218 * Arrange to timeout this node
220 if (mf
&& ((mp
->am_flags
& AMF_ROOT
) ||
221 (mf
->mf_flags
& (MFF_MOUNTING
| MFF_UNMOUNTING
)))) {
222 if (!(mf
->mf_flags
& MFF_UNMOUNTING
))
223 plog(XLOG_WARNING
, "ignoring timeout request for active node %s", mp
->am_path
);
225 plog(XLOG_INFO
, "\"%s\" forcibly timed out", mp
->am_path
);
226 mp
->am_flags
&= ~AMF_NOTIMEOUT
;
227 mp
->am_ttl
= clocktime();
228 reschedule_timeout_mp();
234 mf_mounted(mntfs
*mf
)
237 int wasmounted
= mf
->mf_flags
& MFF_MOUNTED
;
241 * If this is a freshly mounted
242 * filesystem then update the
245 mf
->mf_flags
|= MFF_MOUNTED
;
249 * Do mounted callback
251 if (mf
->mf_ops
->mounted
) {
252 (*mf
->mf_ops
->mounted
) (mf
);
260 quoted
= strchr(mf
->mf_info
, ' ') != 0;
261 plog(XLOG_INFO
, "%s%s%s %s fstype %s on %s",
265 wasmounted
? "referenced" : "mounted",
266 mf
->mf_ops
->fs_type
, mf
->mf_mount
);
271 am_mounted(am_node
*mp
)
273 mntfs
*mf
= mp
->am_mnt
;
278 * Patch up path for direct mounts
280 if (mp
->am_parent
&& mp
->am_parent
->am_mnt
->mf_ops
== &amfs_direct_ops
)
281 mp
->am_path
= str3cat(mp
->am_path
, mp
->am_parent
->am_path
, "/", ".");
284 * Check whether this mount should be cached permanently
286 if (mf
->mf_ops
->fs_flags
& FS_NOTIMEOUT
) {
287 mp
->am_flags
|= AMF_NOTIMEOUT
;
288 } else if (mf
->mf_mount
[1] == '\0' && mf
->mf_mount
[0] == '/') {
289 mp
->am_flags
|= AMF_NOTIMEOUT
;
293 mnt
.mnt_opts
= mf
->mf_mopts
;
294 if (hasmntopt(&mnt
, "nounmount"))
295 mp
->am_flags
|= AMF_NOTIMEOUT
;
296 if ((mp
->am_timeo
= hasmntval(&mnt
, "utimeout")) == 0)
297 mp
->am_timeo
= gopt
.am_timeo
;
302 * If this node is a symlink then
303 * compute the length of the returned string.
305 if (mp
->am_fattr
.na_type
== NFLNK
)
306 mp
->am_fattr
.na_size
= strlen(mp
->am_link
? mp
->am_link
: mp
->am_mnt
->mf_mount
);
311 mp
->am_fattr
.na_mtime
.nt_seconds
= mp
->am_stats
.s_mtime
= clocktime();
315 * Update mtime of parent node
317 if (mp
->am_parent
&& mp
->am_parent
->am_mnt
)
318 mp
->am_parent
->am_fattr
.na_mtime
.nt_seconds
= mp
->am_stats
.s_mtime
;
321 * Now, if we can, do a reply to our NFS client here
322 * to speed things up.
334 mount_node(am_node
*mp
)
336 mntfs
*mf
= mp
->am_mnt
;
339 mf
->mf_flags
|= MFF_MOUNTING
;
340 error
= (*mf
->mf_ops
->mount_fs
) (mp
);
344 mf
->mf_flags
&= ~MFF_MOUNTING
;
345 if (!error
&& !(mf
->mf_ops
->fs_flags
& FS_MBACKGROUND
)) {
346 /* ...but see ifs_mount */
355 am_unmounted(am_node
*mp
)
357 mntfs
*mf
= mp
->am_mnt
;
359 if (!foreground
) /* firewall - should never happen */
363 * Do unmounted callback
365 if (mf
->mf_ops
->umounted
)
366 (*mf
->mf_ops
->umounted
) (mp
);
369 * Update mtime of parent node
371 if (mp
->am_parent
&& mp
->am_parent
->am_mnt
)
372 mp
->am_parent
->am_fattr
.na_mtime
.nt_seconds
= clocktime();
379 * Fork the automounter
381 * TODO: Need a better strategy for handling errors
391 if (pid
< 0) { /* fork error, retry in 1 second */
395 if (pid
== 0) { /* child process (foreground==false) */
398 } else { /* parent process, has one more child */
413 dlog("backgrounded");