1398a5aebSmckusick /* 2398a5aebSmckusick * Copyright (c) 1990 Jan-Simon Pendry 3398a5aebSmckusick * Copyright (c) 1990 Imperial College of Science, Technology & Medicine 4398a5aebSmckusick * Copyright (c) 1990 The Regents of the University of California. 5398a5aebSmckusick * 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*10042f30Spendry * @(#)util.c 5.5 (Berkeley) 05/31/92 13c626267eSpendry * 14*10042f30Spendry * $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 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 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 */ 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 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)); 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)) 99*10042f30Spendry *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)); 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)); 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)); 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)); 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)); 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)); 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)); 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)); 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)); 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)); 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)); 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)); 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)); 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); 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); 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)); 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)); 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