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