xref: /original-bsd/usr.sbin/amd/amd/util.c (revision 4092c5cc)
1398a5aebSmckusick /*
2398a5aebSmckusick  * Copyright (c) 1990 Jan-Simon Pendry
3398a5aebSmckusick  * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
4*4092c5ccSbostic  * Copyright (c) 1990, 1993
5*4092c5ccSbostic  *	The Regents of the University of California.  All rights reserved.
6398a5aebSmckusick  *
7398a5aebSmckusick  * This code is derived from software contributed to Berkeley by
8398a5aebSmckusick  * Jan-Simon Pendry at Imperial College, London.
9398a5aebSmckusick  *
10398a5aebSmckusick  * %sccs.include.redist.c%
11398a5aebSmckusick  *
12*4092c5ccSbostic  *	@(#)util.c	8.1 (Berkeley) 06/06/93
13c626267eSpendry  *
1410042f30Spendry  * $Id: util.c,v 5.2.2.2 1992/03/07 17:52:06 jsp Exp $
15c626267eSpendry  *
16398a5aebSmckusick  */
17398a5aebSmckusick 
18398a5aebSmckusick /*
19398a5aebSmckusick  * Utils
20398a5aebSmckusick  */
21398a5aebSmckusick 
22398a5aebSmckusick #include "am.h"
23398a5aebSmckusick #include <ctype.h>
24398a5aebSmckusick #include <sys/stat.h>
25398a5aebSmckusick #include <netdb.h>
26398a5aebSmckusick 
27398a5aebSmckusick 
strnsave(str,len)28398a5aebSmckusick char *strnsave(str, len)
298a89c22cSpendry Const char *str;
30398a5aebSmckusick int len;
31398a5aebSmckusick {
32398a5aebSmckusick 	char *sp = (char *) xmalloc(len+1);
33398a5aebSmckusick 
34398a5aebSmckusick 	bcopy(str, sp, len);
35398a5aebSmckusick 	sp[len] = 0;
36398a5aebSmckusick 
37398a5aebSmckusick 	return sp;
38398a5aebSmckusick }
39398a5aebSmckusick 
strdup(s)40398a5aebSmckusick char *strdup(s)
418a89c22cSpendry Const char *s;
42398a5aebSmckusick {
43398a5aebSmckusick 	return strnsave(s, strlen(s));
44398a5aebSmckusick }
45398a5aebSmckusick 
46398a5aebSmckusick /*
47398a5aebSmckusick  * Concatenate three strings and store in buffer pointed to
48398a5aebSmckusick  * by p, making p large enough to hold the strings
49398a5aebSmckusick  */
str3cat(p,s1,s2,s3)50398a5aebSmckusick char *str3cat(p, s1, s2, s3)
51398a5aebSmckusick char *p;
52398a5aebSmckusick char *s1;
53398a5aebSmckusick char *s2;
54398a5aebSmckusick char *s3;
55398a5aebSmckusick {
56398a5aebSmckusick 	int l1 = strlen(s1);
57398a5aebSmckusick 	int l2 = strlen(s2);
58398a5aebSmckusick 	int l3 = strlen(s3);
59398a5aebSmckusick 	p = (char *) xrealloc(p, l1 + l2 + l3 + 1);
60398a5aebSmckusick 	bcopy(s1, p, l1);
61398a5aebSmckusick 	bcopy(s2, p + l1, l2);
62398a5aebSmckusick 	bcopy(s3, p + l1 + l2, l3 + 1);
63398a5aebSmckusick 	return p;
64398a5aebSmckusick }
65398a5aebSmckusick 
strealloc(p,s)66398a5aebSmckusick char *strealloc(p, s)
67398a5aebSmckusick char *p;
68398a5aebSmckusick char *s;
69398a5aebSmckusick {
70398a5aebSmckusick 	int len = strlen(s) + 1;
71398a5aebSmckusick 
72398a5aebSmckusick 	p = (char *) xrealloc((voidp) p, len);
73398a5aebSmckusick 
74398a5aebSmckusick 	strcpy(p, s);
75398a5aebSmckusick #ifdef DEBUG_MEM
76398a5aebSmckusick 	malloc_verify();
77398a5aebSmckusick #endif /* DEBUG_MEM */
78398a5aebSmckusick 	return p;
79398a5aebSmckusick }
80398a5aebSmckusick 
818a89c22cSpendry char **strsplit P((char *s, int ch, int qc));
strsplit(s,ch,qc)828a89c22cSpendry char **strsplit(s, ch, qc)
83398a5aebSmckusick char *s;
848a89c22cSpendry int ch;
85398a5aebSmckusick int qc;
86398a5aebSmckusick {
87398a5aebSmckusick 	char **ivec;
88398a5aebSmckusick 	int ic = 0;
89398a5aebSmckusick 	int done = 0;
90398a5aebSmckusick 
91398a5aebSmckusick 	ivec = (char **) xmalloc((ic+1)*sizeof(char *));
92398a5aebSmckusick 
93398a5aebSmckusick 	while (!done) {
94398a5aebSmckusick 		char *v;
95398a5aebSmckusick 		/*
968a89c22cSpendry 		 * skip to split char
97398a5aebSmckusick 		 */
988a89c22cSpendry 		while (*s && (ch == ' ' ? (isascii(*s) && isspace(*s)) : *s == ch))
9910042f30Spendry 				*s++ = '\0';
100398a5aebSmckusick 
101398a5aebSmckusick 		/*
102398a5aebSmckusick 		 * End of string?
103398a5aebSmckusick 		 */
104398a5aebSmckusick 		if (!*s)
105398a5aebSmckusick 			break;
106398a5aebSmckusick 
107398a5aebSmckusick 		/*
108398a5aebSmckusick 		 * remember start of string
109398a5aebSmckusick 		 */
110398a5aebSmckusick 		v = s;
111398a5aebSmckusick 
112398a5aebSmckusick 		/*
1138a89c22cSpendry 		 * skip to split char
114398a5aebSmckusick 		 */
1158a89c22cSpendry 		while (*s && !(ch == ' ' ? (isascii(*s) && isspace(*s)) : *s == ch)) {
116398a5aebSmckusick 			if (*s++ == qc) {
117398a5aebSmckusick 				/*
118398a5aebSmckusick 				 * Skip past string.
119398a5aebSmckusick 				 */
120398a5aebSmckusick 				s++;
121398a5aebSmckusick 				while (*s && *s != qc)
122398a5aebSmckusick 				 	s++;
123398a5aebSmckusick 				if (*s == qc)
124398a5aebSmckusick 					s++;
125398a5aebSmckusick 			}
126398a5aebSmckusick 		}
127398a5aebSmckusick 
128398a5aebSmckusick 		if (!*s)
129398a5aebSmckusick 			done = 1;
130398a5aebSmckusick 		*s++ = '\0';
131398a5aebSmckusick 
132398a5aebSmckusick 		/*
133398a5aebSmckusick 		 * save string in new ivec slot
134398a5aebSmckusick 		 */
135398a5aebSmckusick 		ivec[ic++] = v;
1368a89c22cSpendry 		ivec = (char **) xrealloc((voidp) ivec, (ic+1)*sizeof(char *));
137398a5aebSmckusick #ifdef DEBUG
138398a5aebSmckusick 		Debug(D_STR)
139398a5aebSmckusick 			plog(XLOG_DEBUG, "strsplit saved \"%s\"", v);
140398a5aebSmckusick #endif /* DEBUG */
141398a5aebSmckusick 	}
142398a5aebSmckusick 
143398a5aebSmckusick #ifdef DEBUG
144398a5aebSmckusick 	Debug(D_STR)
145398a5aebSmckusick 		plog(XLOG_DEBUG, "strsplit saved a total of %d strings", ic);
146398a5aebSmckusick #endif /* DEBUG */
147398a5aebSmckusick 
148398a5aebSmckusick 	ivec[ic] = 0;
149398a5aebSmckusick 
150398a5aebSmckusick 	return ivec;
151398a5aebSmckusick }
152398a5aebSmckusick 
153398a5aebSmckusick /*
154398a5aebSmckusick  * Strip off the trailing part of a domain
155398a5aebSmckusick  * to produce a short-form domain relative
156398a5aebSmckusick  * to the local host domain.
157398a5aebSmckusick  * Note that this has no effect if the domain
158398a5aebSmckusick  * names do not have the same number of
159398a5aebSmckusick  * components.  If that restriction proves
160398a5aebSmckusick  * to be a problem then the loop needs recoding
161398a5aebSmckusick  * to skip from right to left and do partial
162398a5aebSmckusick  * matches along the way -- ie more expensive.
163398a5aebSmckusick  */
164398a5aebSmckusick static void domain_strip P((char *otherdom, char *localdom));
domain_strip(otherdom,localdom)165398a5aebSmckusick static void domain_strip(otherdom, localdom)
166398a5aebSmckusick char *otherdom, *localdom;
167398a5aebSmckusick {
1688a89c22cSpendry #ifdef PARTIAL_DOMAINS
169398a5aebSmckusick         char *p1 = otherdom-1;
170398a5aebSmckusick 	char *p2 = localdom-1;
171398a5aebSmckusick 
172398a5aebSmckusick         do {
173398a5aebSmckusick                 if (p1 = strchr(p1+1, '.'))
174398a5aebSmckusick                 if (p2 = strchr(p2+1, '.'))
175398a5aebSmckusick                 if (strcmp(p1+1, p2+1) == 0) {
176398a5aebSmckusick                         *p1 = '\0';
177398a5aebSmckusick                         break;
178398a5aebSmckusick                 }
179398a5aebSmckusick         } while (p1 && p2);
1808a89c22cSpendry #else
1818a89c22cSpendry 	char *p1, *p2;
1828a89c22cSpendry 
1838a89c22cSpendry 	if ((p1 = strchr(otherdom, '.')) &&
1848a89c22cSpendry 			(p2 = strchr(localdom, '.')) &&
1858a89c22cSpendry 			(strcmp(p1+1, p2+1) == 0))
1868a89c22cSpendry 		*p1 = '\0';
1878a89c22cSpendry #endif /* PARTIAL_DOMAINS */
188398a5aebSmckusick }
189398a5aebSmckusick 
190398a5aebSmckusick /*
191398a5aebSmckusick  * Normalize a host name
192398a5aebSmckusick  */
193398a5aebSmckusick void host_normalize P((char **chp));
host_normalize(chp)194398a5aebSmckusick void host_normalize(chp)
195398a5aebSmckusick char **chp;
196398a5aebSmckusick {
197398a5aebSmckusick 	/*
198398a5aebSmckusick 	 * Normalize hosts is used to resolve host name aliases
199398a5aebSmckusick 	 * and replace them with the standard-form name.
200398a5aebSmckusick 	 * Invoked with "-n" command line option.
201398a5aebSmckusick 	 */
202398a5aebSmckusick 	if (normalize_hosts) {
203398a5aebSmckusick 		struct hostent *hp;
204398a5aebSmckusick 		clock_valid = 0;
205398a5aebSmckusick 		hp = gethostbyname(*chp);
206398a5aebSmckusick 		if (hp && hp->h_addrtype == AF_INET) {
207398a5aebSmckusick #ifdef DEBUG
208398a5aebSmckusick 			dlog("Hostname %s normalized to %s", *chp, hp->h_name);
209398a5aebSmckusick #endif /* DEBUG */
210398a5aebSmckusick 			*chp = strealloc(*chp, hp->h_name);
211398a5aebSmckusick 		}
212398a5aebSmckusick 	}
213398a5aebSmckusick 	domain_strip(*chp, hostd);
214398a5aebSmckusick }
215398a5aebSmckusick 
216398a5aebSmckusick /*
2178a89c22cSpendry  * Make a dotted quad from a 32bit IP address
2188a89c22cSpendry  * addr is in network byte order.
2198a89c22cSpendry  * sizeof(buf) needs to be at least 16.
2208a89c22cSpendry  */
2218a89c22cSpendry char *inet_dquad P((char *buf, unsigned long addr));
inet_dquad(buf,addr)2228a89c22cSpendry char *inet_dquad(buf, addr)
2238a89c22cSpendry char *buf;
2248a89c22cSpendry unsigned long addr;
2258a89c22cSpendry {
2268a89c22cSpendry 	addr = ntohl(addr);
2278a89c22cSpendry 	sprintf(buf, "%d.%d.%d.%d",
2288a89c22cSpendry 		((addr >> 24) & 0xff),
2298a89c22cSpendry 		((addr >> 16) & 0xff),
2308a89c22cSpendry 		((addr >> 8) & 0xff),
2318a89c22cSpendry 		((addr >> 0) & 0xff));
2328a89c22cSpendry 	return buf;
2338a89c22cSpendry }
2348a89c22cSpendry 
2358a89c22cSpendry /*
236398a5aebSmckusick  * Keys are not allowed to contain " ' ! or ; to avoid
237398a5aebSmckusick  * problems with macro expansions.
238398a5aebSmckusick  */
239398a5aebSmckusick static char invalid_keys[] = "\"'!;@ \t\n";
240398a5aebSmckusick int valid_key P((char *key));
valid_key(key)241398a5aebSmckusick int valid_key(key)
242398a5aebSmckusick char *key;
243398a5aebSmckusick {
244398a5aebSmckusick 	while (*key)
245398a5aebSmckusick 		if (strchr(invalid_keys, *key++))
246398a5aebSmckusick 			return FALSE;
247398a5aebSmckusick 	return TRUE;
248398a5aebSmckusick }
249398a5aebSmckusick 
250398a5aebSmckusick void going_down P((int rc));
going_down(rc)251398a5aebSmckusick void going_down(rc)
252398a5aebSmckusick int rc;
253398a5aebSmckusick {
254398a5aebSmckusick 	if (foreground) {
255398a5aebSmckusick 		if (amd_state != Start) {
256398a5aebSmckusick 			if (amd_state != Done)
257398a5aebSmckusick 				return;
258398a5aebSmckusick 			unregister_amq();
259398a5aebSmckusick 		}
260398a5aebSmckusick 	}
261398a5aebSmckusick 	if (foreground) {
262398a5aebSmckusick 		plog(XLOG_INFO, "Finishing with status %d", rc);
263398a5aebSmckusick 	} else {
264398a5aebSmckusick #ifdef DEBUG
265398a5aebSmckusick 		dlog("background process exiting with status %d", rc);
266398a5aebSmckusick #endif /* DEBUG */
267398a5aebSmckusick 	}
268398a5aebSmckusick 
269398a5aebSmckusick 	exit(rc);
270398a5aebSmckusick }
271398a5aebSmckusick 
272398a5aebSmckusick 
273398a5aebSmckusick int bind_resv_port P((int so, u_short *pp));
bind_resv_port(so,pp)274398a5aebSmckusick int bind_resv_port(so, pp)
275398a5aebSmckusick int so;
276398a5aebSmckusick u_short *pp;
277398a5aebSmckusick {
278398a5aebSmckusick 	struct sockaddr_in sin;
279398a5aebSmckusick 	int rc;
280398a5aebSmckusick 	unsigned short port;
281398a5aebSmckusick 
282398a5aebSmckusick 	bzero((voidp) &sin, sizeof(sin));
283398a5aebSmckusick 	sin.sin_family = AF_INET;
284398a5aebSmckusick 
285398a5aebSmckusick 	port = IPPORT_RESERVED;
286398a5aebSmckusick 
287398a5aebSmckusick 	do {
288398a5aebSmckusick 		--port;
289398a5aebSmckusick 		sin.sin_port = htons(port);
290398a5aebSmckusick 		rc = bind(so, (struct sockaddr *) &sin, sizeof(sin));
291398a5aebSmckusick 	} while (rc < 0 && port > IPPORT_RESERVED/2);
292398a5aebSmckusick 
293398a5aebSmckusick 	if (pp && rc == 0)
294398a5aebSmckusick 		*pp = port;
295398a5aebSmckusick 	return rc;
296398a5aebSmckusick }
297398a5aebSmckusick 
298398a5aebSmckusick void forcibly_timeout_mp P((am_node *mp));
forcibly_timeout_mp(mp)299398a5aebSmckusick void forcibly_timeout_mp(mp)
300398a5aebSmckusick am_node *mp;
301398a5aebSmckusick {
302398a5aebSmckusick 	mntfs *mf = mp->am_mnt;
303398a5aebSmckusick 	/*
304398a5aebSmckusick 	 * Arrange to timeout this node
305398a5aebSmckusick 	 */
306398a5aebSmckusick 	if (mf && ((mp->am_flags & AMF_ROOT) ||
307398a5aebSmckusick 		(mf->mf_flags & (MFF_MOUNTING|MFF_UNMOUNTING)))) {
308398a5aebSmckusick 		if (!(mf->mf_flags & MFF_UNMOUNTING))
309398a5aebSmckusick 			plog(XLOG_WARNING, "ignoring timeout request for active node %s", mp->am_path);
310398a5aebSmckusick 	} else {
311398a5aebSmckusick 		plog(XLOG_INFO, "\"%s\" forcibly timed out", mp->am_path);
312398a5aebSmckusick 		mp->am_flags &= ~AMF_NOTIMEOUT;
313398a5aebSmckusick 		mp->am_ttl = clocktime();
314398a5aebSmckusick 		reschedule_timeout_mp();
315398a5aebSmckusick 	}
316398a5aebSmckusick }
317398a5aebSmckusick 
3188a89c22cSpendry void mf_mounted P((mntfs *mf));
mf_mounted(mf)3198a89c22cSpendry void mf_mounted(mf)
3208a89c22cSpendry mntfs *mf;
3218a89c22cSpendry {
3228a89c22cSpendry 	int quoted;
323c626267eSpendry 	int wasmounted = mf->mf_flags & MFF_MOUNTED;
3248a89c22cSpendry 
325c626267eSpendry 	if (!wasmounted) {
3268a89c22cSpendry 		/*
3278a89c22cSpendry 		 * If this is a freshly mounted
3288a89c22cSpendry 		 * filesystem then update the
3298a89c22cSpendry 		 * mntfs structure...
3308a89c22cSpendry 		 */
3318a89c22cSpendry 		mf->mf_flags |= MFF_MOUNTED;
3328a89c22cSpendry 		mf->mf_error = 0;
3338a89c22cSpendry 
3348a89c22cSpendry 		/*
3358a89c22cSpendry 		 * Do mounted callback
3368a89c22cSpendry 		 */
3378a89c22cSpendry 		if (mf->mf_ops->mounted)
3388a89c22cSpendry 			(*mf->mf_ops->mounted)(mf);
3398a89c22cSpendry 
3408a89c22cSpendry 		mf->mf_fo = 0;
3418a89c22cSpendry 	}
3428a89c22cSpendry 
3438a89c22cSpendry 	/*
3448a89c22cSpendry 	 * Log message
3458a89c22cSpendry 	 */
3468a89c22cSpendry 	quoted = strchr(mf->mf_info, ' ') != 0;
347c626267eSpendry 	plog(XLOG_INFO, "%s%s%s %s fstype %s on %s",
3488a89c22cSpendry 		quoted ? "\"" : "",
3498a89c22cSpendry 		mf->mf_info,
3508a89c22cSpendry 		quoted ? "\"" : "",
351c626267eSpendry 		wasmounted ? "referenced" : "mounted",
3528a89c22cSpendry 		mf->mf_ops->fs_type, mf->mf_mount);
3538a89c22cSpendry }
3548a89c22cSpendry 
355398a5aebSmckusick void am_mounted P((am_node *mp));
am_mounted(mp)356398a5aebSmckusick void am_mounted(mp)
357398a5aebSmckusick am_node *mp;
358398a5aebSmckusick {
359398a5aebSmckusick 	mntfs *mf = mp->am_mnt;
3608a89c22cSpendry 
3618a89c22cSpendry 	mf_mounted(mf);
362398a5aebSmckusick 
363398a5aebSmckusick 	/*
364398a5aebSmckusick 	 * Patch up path for direct mounts
365398a5aebSmckusick 	 */
366398a5aebSmckusick 	if (mp->am_parent && mp->am_parent->am_mnt->mf_ops == &dfs_ops)
367398a5aebSmckusick 		mp->am_path = str3cat(mp->am_path, mp->am_parent->am_path, "/", ".");
368398a5aebSmckusick 
369398a5aebSmckusick 	/*
370398a5aebSmckusick 	 * Check whether this mount should be cached permanently
371398a5aebSmckusick 	 */
372398a5aebSmckusick 	if (mf->mf_ops->fs_flags & FS_NOTIMEOUT) {
373398a5aebSmckusick 		mp->am_flags |= AMF_NOTIMEOUT;
374398a5aebSmckusick 	} else if (mf->mf_mount[1] == '\0' && mf->mf_mount[0] == '/') {
375398a5aebSmckusick 		mp->am_flags |= AMF_NOTIMEOUT;
376398a5aebSmckusick 	} else {
377398a5aebSmckusick 		struct mntent mnt;
3788a89c22cSpendry 		if (mf->mf_mopts) {
3798a89c22cSpendry 			mnt.mnt_opts = mf->mf_mopts;
380398a5aebSmckusick 			if (hasmntopt(&mnt, "nounmount"))
381398a5aebSmckusick 				mp->am_flags |= AMF_NOTIMEOUT;
382398a5aebSmckusick 			if ((mp->am_timeo = hasmntval(&mnt, "utimeout")) == 0)
383398a5aebSmckusick 				mp->am_timeo = am_timeo;
384398a5aebSmckusick 		}
3858a89c22cSpendry 	}
386398a5aebSmckusick 
387398a5aebSmckusick 	/*
388398a5aebSmckusick 	 * If this node is a symlink then
389398a5aebSmckusick 	 * compute the length of the returned string.
390398a5aebSmckusick 	 */
3918a89c22cSpendry 	if (mp->am_fattr.type == NFLNK)
3928a89c22cSpendry 		mp->am_fattr.size = strlen(mp->am_link ? mp->am_link : mp->am_mnt->mf_mount);
393398a5aebSmckusick 
394398a5aebSmckusick 	/*
395398a5aebSmckusick 	 * Record mount time
396398a5aebSmckusick 	 */
3978a89c22cSpendry 	mp->am_fattr.mtime.seconds = mp->am_stats.s_mtime = clocktime();
398398a5aebSmckusick 	new_ttl(mp);
399398a5aebSmckusick 	/*
400398a5aebSmckusick 	 * Update mtime of parent node
401398a5aebSmckusick 	 */
402398a5aebSmckusick 	if (mp->am_parent && mp->am_parent->am_mnt)
4038a89c22cSpendry 		mp->am_parent->am_fattr.mtime.seconds = mp->am_stats.s_mtime;
404398a5aebSmckusick 
405398a5aebSmckusick 
406398a5aebSmckusick 	/*
407398a5aebSmckusick 	 * Update stats
408398a5aebSmckusick 	 */
409398a5aebSmckusick 	amd_stats.d_mok++;
410398a5aebSmckusick }
411398a5aebSmckusick 
412398a5aebSmckusick int mount_node P((am_node *mp));
mount_node(mp)413398a5aebSmckusick int mount_node(mp)
414398a5aebSmckusick am_node *mp;
415398a5aebSmckusick {
416398a5aebSmckusick 	mntfs *mf = mp->am_mnt;
417398a5aebSmckusick 	int error;
418398a5aebSmckusick 
419398a5aebSmckusick 	mf->mf_flags |= MFF_MOUNTING;
420398a5aebSmckusick 	error = (*mf->mf_ops->mount_fs)(mp);
421398a5aebSmckusick 	mf = mp->am_mnt;
422c626267eSpendry 	if (error >= 0)
423398a5aebSmckusick 		mf->mf_flags &= ~MFF_MOUNTING;
424398a5aebSmckusick 	if (!error && !(mf->mf_ops->fs_flags & FS_MBACKGROUND)) {
425398a5aebSmckusick 		/* ...but see ifs_mount */
426398a5aebSmckusick 		am_mounted(mp);
427398a5aebSmckusick 	}
428398a5aebSmckusick 
429398a5aebSmckusick 	return error;
430398a5aebSmckusick }
431398a5aebSmckusick 
432398a5aebSmckusick void am_unmounted P((am_node *mp));
am_unmounted(mp)433398a5aebSmckusick void am_unmounted(mp)
434398a5aebSmckusick am_node *mp;
435398a5aebSmckusick {
436398a5aebSmckusick 	mntfs *mf = mp->am_mnt;
437398a5aebSmckusick 
438398a5aebSmckusick 	if (!foreground) /* firewall - should never happen */
439398a5aebSmckusick 		return;
440398a5aebSmckusick 
441398a5aebSmckusick #ifdef DEBUG
442398a5aebSmckusick 	/*dlog("in am_unmounted(), foreground = %d", foreground);*/
443398a5aebSmckusick #endif /* DEBUG */
444398a5aebSmckusick 
445398a5aebSmckusick 	/*
446398a5aebSmckusick 	 * Do unmounted callback
447398a5aebSmckusick 	 */
448398a5aebSmckusick 	if (mf->mf_ops->umounted)
449398a5aebSmckusick 		(*mf->mf_ops->umounted)(mp);
450398a5aebSmckusick 
451398a5aebSmckusick 	/*
452398a5aebSmckusick 	 * Update mtime of parent node
453398a5aebSmckusick 	 */
454398a5aebSmckusick 	if (mp->am_parent && mp->am_parent->am_mnt)
4558a89c22cSpendry 		mp->am_parent->am_fattr.mtime.seconds = clocktime();
456398a5aebSmckusick 
457398a5aebSmckusick 	free_map(mp);
458398a5aebSmckusick }
459398a5aebSmckusick 
4608a89c22cSpendry int auto_fmount P((am_node *mp));
auto_fmount(mp)4618a89c22cSpendry int auto_fmount(mp)
4628a89c22cSpendry am_node *mp;
4638a89c22cSpendry {
4648a89c22cSpendry 	mntfs *mf = mp->am_mnt;
4658a89c22cSpendry 	return (*mf->mf_ops->fmount_fs)(mf);
4668a89c22cSpendry }
4678a89c22cSpendry 
4688a89c22cSpendry int auto_fumount P((am_node *mp));
auto_fumount(mp)4698a89c22cSpendry int auto_fumount(mp)
4708a89c22cSpendry am_node *mp;
4718a89c22cSpendry {
4728a89c22cSpendry 	mntfs *mf = mp->am_mnt;
4738a89c22cSpendry 	return (*mf->mf_ops->fumount_fs)(mf);
4748a89c22cSpendry }
475398a5aebSmckusick 
476398a5aebSmckusick /*
477398a5aebSmckusick  * Fork the automounter
478398a5aebSmckusick  *
479398a5aebSmckusick  * TODO: Need a better strategy for handling errors
480398a5aebSmckusick  */
481398a5aebSmckusick static int dofork(P_void);
dofork()482398a5aebSmckusick static int dofork()
483398a5aebSmckusick {
484398a5aebSmckusick 	int pid;
485398a5aebSmckusick top:
486398a5aebSmckusick 	pid = fork();
487398a5aebSmckusick 
488398a5aebSmckusick 	if (pid < 0) {
489398a5aebSmckusick 		sleep(1);
490398a5aebSmckusick 		goto top;
491398a5aebSmckusick 	}
492398a5aebSmckusick 
493398a5aebSmckusick 	if (pid == 0) {
494398a5aebSmckusick 		mypid = getpid();
495398a5aebSmckusick 		foreground = 0;
496398a5aebSmckusick 	}
497398a5aebSmckusick 
498398a5aebSmckusick 	return pid;
499398a5aebSmckusick }
500398a5aebSmckusick 
501398a5aebSmckusick int background(P_void);
background()502398a5aebSmckusick int background()
503398a5aebSmckusick {
504398a5aebSmckusick 	int pid = dofork();
505398a5aebSmckusick 	if (pid == 0) {
506398a5aebSmckusick #ifdef DEBUG
507398a5aebSmckusick 		dlog("backgrounded");
508c626267eSpendry #endif
509398a5aebSmckusick 		foreground = 0;
510398a5aebSmckusick 	}
511398a5aebSmckusick 
512398a5aebSmckusick 	return pid;
513398a5aebSmckusick }
514398a5aebSmckusick 
515c626267eSpendry /*
516c626267eSpendry  * Make all the directories in the path.
517c626267eSpendry  */
518398a5aebSmckusick int mkdirs P((char *path, int mode));
mkdirs(path,mode)519398a5aebSmckusick int mkdirs(path, mode)
520398a5aebSmckusick char *path;
521398a5aebSmckusick int mode;
522398a5aebSmckusick {
523398a5aebSmckusick 	/*
524398a5aebSmckusick 	 * take a copy in case path is in readonly store
525398a5aebSmckusick 	 */
526398a5aebSmckusick 	char *p2 = strdup(path);
527398a5aebSmckusick 	char *sp = p2;
528398a5aebSmckusick 	struct stat stb;
529398a5aebSmckusick 	int error_so_far = 0;
530398a5aebSmckusick 
531398a5aebSmckusick 	/*
532398a5aebSmckusick 	 * Skip through the string make the directories.
533398a5aebSmckusick 	 * Mostly ignore errors - the result is tested at the end.
534398a5aebSmckusick 	 *
535398a5aebSmckusick 	 * This assumes we are root so that we can do mkdir in a
536398a5aebSmckusick 	 * mode 555 directory...
537398a5aebSmckusick 	 */
538398a5aebSmckusick 	while (sp = strchr(sp+1, '/')) {
539398a5aebSmckusick 		*sp = '\0';
540398a5aebSmckusick 		if (mkdir(p2, mode) < 0) {
541398a5aebSmckusick 			error_so_far = errno;
542398a5aebSmckusick 		} else {
543398a5aebSmckusick #ifdef DEBUG
544398a5aebSmckusick 			dlog("mkdir(%s)", p2);
545c626267eSpendry #endif
546398a5aebSmckusick 		}
547398a5aebSmckusick 		*sp = '/';
548398a5aebSmckusick 	}
549398a5aebSmckusick 
550398a5aebSmckusick 	if (mkdir(p2, mode) < 0) {
551398a5aebSmckusick 		error_so_far = errno;
552398a5aebSmckusick 	} else {
553398a5aebSmckusick #ifdef DEBUG
554398a5aebSmckusick 		dlog("mkdir(%s)", p2);
555c626267eSpendry #endif
556398a5aebSmckusick 	}
557398a5aebSmckusick 
558398a5aebSmckusick #ifdef SUNOS4_WORKAROUND
559398a5aebSmckusick 	/*
560398a5aebSmckusick 	 * Do a sync - if we do rmdirs() immediately
561398a5aebSmckusick 	 * and then the system crashes it leaves
562398a5aebSmckusick 	 * the filesystem in a state that fsck -p
563398a5aebSmckusick 	 * can't fix.  (Observed more than once on
564398a5aebSmckusick 	 * SunOS 4 ...)
565398a5aebSmckusick 	 *
566398a5aebSmckusick 	 * The problem was caused by a bug somewhere
567398a5aebSmckusick 	 * in the UFS code which has since been fixed
568398a5aebSmckusick 	 * (at least at Berkeley).
569398a5aebSmckusick 	 *
570398a5aebSmckusick 	 * Attempted workaround - XXX.
571398a5aebSmckusick 	 */
572398a5aebSmckusick 	sync();
573398a5aebSmckusick #endif /* SUNOS4_WORKAROUND */
574398a5aebSmckusick 
575398a5aebSmckusick 	free(p2);
576398a5aebSmckusick 
577398a5aebSmckusick 	return stat(path, &stb) == 0 &&
578398a5aebSmckusick 		(stb.st_mode & S_IFMT) == S_IFDIR ? 0 : error_so_far;
579398a5aebSmckusick }
580398a5aebSmckusick 
581c626267eSpendry /*
582c626267eSpendry  * Remove as many directories in the path as possible.
583c626267eSpendry  * Give up if the directory doesn't appear to have
584c626267eSpendry  * been created by Amd (not mode dr-x) or an rmdir
585c626267eSpendry  * fails for any reason.
586c626267eSpendry  */
587398a5aebSmckusick void rmdirs P((char *dir));
rmdirs(dir)588398a5aebSmckusick void rmdirs(dir)
589398a5aebSmckusick char *dir;
590398a5aebSmckusick {
591398a5aebSmckusick 	char *xdp = strdup(dir);
592398a5aebSmckusick 	char *dp;
593398a5aebSmckusick 
594398a5aebSmckusick 	do {
595398a5aebSmckusick 		struct stat stb;
596398a5aebSmckusick 		/*
597398a5aebSmckusick 		 * Try to find out whether this was
598398a5aebSmckusick 		 * created by amd.  Do this by checking
599398a5aebSmckusick 		 * for owner write permission.
600398a5aebSmckusick 		 */
601398a5aebSmckusick 		if (stat(xdp, &stb) == 0 && (stb.st_mode & 0200) == 0) {
602398a5aebSmckusick 			if (rmdir(xdp) < 0) {
603c626267eSpendry 				if (errno != ENOTEMPTY &&
604c626267eSpendry 				    errno != EBUSY &&
605c626267eSpendry 				    errno != EEXIST &&
606c626267eSpendry 				    errno != EINVAL)
607398a5aebSmckusick 					plog(XLOG_ERROR, "rmdir(%s): %m", xdp);
608398a5aebSmckusick 				break;
609398a5aebSmckusick 			} else {
610398a5aebSmckusick #ifdef DEBUG
611398a5aebSmckusick 				dlog("rmdir(%s)", xdp);
612c626267eSpendry #endif
613398a5aebSmckusick 			}
614398a5aebSmckusick 		} else {
615398a5aebSmckusick 			break;
616398a5aebSmckusick 		}
617398a5aebSmckusick 		dp = strrchr(xdp, '/');
618398a5aebSmckusick 		if (dp)
619398a5aebSmckusick 			*dp = '\0';
620398a5aebSmckusick 	} while (dp && dp > xdp);
621398a5aebSmckusick 	free(xdp);
622398a5aebSmckusick }
623