/* * Take a little-endian domain name and * transform into a big-endian Un*x pathname. * For example: kiska.doc.ic -> ic/doc/kiska */ static char * compute_hostpath(char *hn) { char *p = xmalloc(MAXPATHLEN); char *d; char path[MAXPATHLEN]; xstrlcpy(p, hn, MAXPATHLEN); domain_strip(p, hostname); path[0] = '\0'; do { d = strrchr(p, '.'); if (d) { *d = 0; xstrlcat(path, d + 1, sizeof(path)); xstrlcat(path, "/", sizeof(path)); } else { xstrlcat(path, p, sizeof(path)); } } while (d); fsi_log("hostpath of '%s' is '%s'", hn, path); xstrlcpy(p, path, MAXPATHLEN); return p; }
/* * Update the destination's file-tree with respect to changes in the * source manpath components. * "Change" is defined by an updated index or btree database. * Returns 1 on success, 0 on failure. */ static int manup(const struct manpaths *dirs, char *base) { char dst[MAXPATHLEN], src[MAXPATHLEN]; const char *path; int i, c; size_t sz; FILE *f; /* Create the path and file for the catman.conf file. */ sz = strlen(base); xstrlcpy(dst, base, MAXPATHLEN); xstrlcat(dst, "/etc", MAXPATHLEN); if (-1 == mkpath(dst, 0755, 0755)) { perror(dst); return(0); } xstrlcat(dst, "/catman.conf", MAXPATHLEN); if (NULL == (f = fopen(dst, "w"))) { perror(dst); return(0); } else if (verbose) printf("%s\n", dst); for (i = 0; i < dirs->sz; i++) { path = dirs->paths[i]; dst[(int)sz] = '\0'; xstrlcat(dst, path, MAXPATHLEN); if (-1 == mkpath(dst, 0755, 0755)) { perror(dst); break; } xstrlcpy(src, path, MAXPATHLEN); if (-1 == (c = treecpy(dst, src))) break; else if (0 == c) continue; /* * We want to use a relative path here because manpath.h * will realpath() when invoked with man.cgi, and we'll * make sure to chdir() into the cache directory before. * * This allows the cache directory to be in an arbitrary * place, working in both chroot() and non-chroot() * "safe" modes. */ assert('/' == path[0]); fprintf(f, "_whatdb %s/whatis.db\n", path + 1); } fclose(f); return(i == dirs->sz); }
static void ops_show1(char *buf, size_t l, int *linesizep, const char *name) { xstrlcat(buf, name, l); xstrlcat(buf, ", ", l); *linesizep += strlen(name) + 2; if (*linesizep > 60) { xstrlcat(buf, "\t\n", l); *linesizep = 0; } }
/* * start with an empty string. for each opts1 option that is not * in opts2, add it to the string (make sure the reverse of it * isn't in either). finally add opts2. return new string. * Both opts1 and opts2 must not be null! * Caller must eventually free the string being returned. */ static char * merge_opts(const char *opts1, const char *opts2) { mntent_t mnt2; /* place holder for opts2 */ char *newstr; /* new string to return (malloc'ed) */ char *tmpstr; /* temp */ char *eq; /* pointer to whatever follows '=' within temp */ char oneopt[80]; /* one option w/o value if any */ char *revoneopt; /* reverse of oneopt */ size_t len = strlen(opts1) + strlen(opts2) + 2; /* space for "," and NULL */ char *s1 = strdup(opts1); /* copy of opts1 to munge */ /* initialization */ mnt2.mnt_opts = (char *) opts2; newstr = xmalloc(len); newstr[0] = '\0'; for (tmpstr = strtok(s1, ","); tmpstr; tmpstr = strtok(NULL, ",")) { /* copy option to temp buffer */ xstrlcpy(oneopt, tmpstr, sizeof(oneopt)); /* if option has a value such as rsize=1024, chop the value part */ if ((eq = haseq(oneopt))) *eq = '\0'; /* find reverse option of oneopt */ revoneopt = reverse_option(oneopt); /* if option orits reverse exist in opts2, ignore it */ if (amu_hasmntopt(&mnt2, oneopt) || amu_hasmntopt(&mnt2, revoneopt)) continue; /* add option to returned string */ if (newstr[0]) { xstrlcat(newstr, ",", len); xstrlcat(newstr, tmpstr, len); } else { xstrlcpy(newstr, tmpstr, len); } } /* finally, append opts2 itself */ if (newstr[0]) { xstrlcat(newstr, ",", len); xstrlcat(newstr, opts2, len); } else { xstrlcpy(newstr, opts2, len); } XFREE(s1); return newstr; }
/* * return string option which is the reverse of opt. * nosuid -> suid * quota -> noquota * ro -> rw * etc. * may return pointer to static buffer or subpointer within opt. */ static char * reverse_option(const char *opt) { static char buf[80]; /* sanity check */ if (!opt) return NULL; /* check special cases */ /* XXX: if this gets too long, rewrite the code more flexibly */ if (STREQ(opt, "ro")) return "rw"; if (STREQ(opt, "rw")) return "ro"; if (STREQ(opt, "bg")) return "fg"; if (STREQ(opt, "fg")) return "bg"; if (STREQ(opt, "soft")) return "hard"; if (STREQ(opt, "hard")) return "soft"; /* check if string starts with 'no' and chop it */ if (NSTREQ(opt, "no", 2)) { xstrlcpy(buf, &opt[2], sizeof(buf)); } else { /* finally return a string prepended with 'no' */ xstrlcpy(buf, "no", sizeof(buf)); xstrlcat(buf, opt, sizeof(buf)); } return buf; }
int ndbm_init(mnt_map *m, char *map, time_t *tp) { DBM *db; db = dbm_open(map, O_RDONLY, 0); if (db) { struct stat stb; int error; #ifdef DBM_SUFFIX char dbfilename[256]; xstrlcpy(dbfilename, map, sizeof(dbfilename)); xstrlcat(dbfilename, DBM_SUFFIX, sizeof(dbfilename)); error = stat(dbfilename, &stb); #else /* not DBM_SUFFIX */ error = fstat(dbm_pagfno(db), &stb); #endif /* not DBM_SUFFIX */ if (error < 0) *tp = clocktime(NULL); else *tp = stb.st_mtime; dbm_close(db); return 0; } return errno; }
int ndbm_search(mnt_map *m, char *map, char *key, char **pval, time_t *tp) { DBM *db; db = dbm_open(map, O_RDONLY, 0); if (db) { struct stat stb; int error; #ifdef DBM_SUFFIX char dbfilename[256]; xstrlcpy(dbfilename, map, sizeof(dbfilename)); xstrlcat(dbfilename, DBM_SUFFIX, sizeof(dbfilename)); error = stat(dbfilename, &stb); #else /* not DBM_SUFFIX */ error = fstat(dbm_pagfno(db), &stb); #endif /* not DBM_SUFFIX */ if (!error && *tp < stb.st_mtime) { *tp = stb.st_mtime; error = -1; } else { error = search_ndbm(m, db, key, pval); } (void) dbm_close(db); return error; } return errno; }
static mntent_t * mnt_dup(struct statfs *mp) { mntent_t *new_mp = ALLOC(mntent_t); char *ty; char *at; char mntfrombuf[MNAMELEN]; char *mntfromptr; /* * Under DEC OSF/1 T1.2-2 the f_mntfromname fields of * the statfs structure can be in the format <fs>@<host> * instead of <host>:<fs>. Here we check for this and * reformat it if necessary. */ mntfromptr = mp->f_mntfromname; switch (mp->f_type) { case MOUNT_TYPE_NFS: #ifdef HAVE_FS_NFS3 case MOUNT_TYPE_NFS3: #endif /* HAVE_FS_NFS3 */ at = strchr(mp->f_mntfromname, '@'); if (at != '\0') { xstrlcpy(mntfrombuf, (at + 1), sizeof(mntfrombuf)); xstrlcat(mntfrombuf, ":", sizeof(mntfrombuf)); strncat(mntfrombuf, mp->f_mntfromname, (at - mp->f_mntfromname)); mntfromptr = mntfrombuf; } } new_mp->mnt_fsname = strdup(mntfromptr); new_mp->mnt_dir = strdup(mp->f_mntonname); switch (mp->f_type) { case MOUNT_TYPE_UFS: ty = MNTTAB_TYPE_UFS; break; #ifdef HAVE_FS_NFS3 case MOUNT_TYPE_NFS3: ty = MNTTAB_TYPE_NFS3; break; #endif /* HAVE_FS_NFS3 */ case MOUNT_TYPE_NFS: ty = MNTTAB_TYPE_NFS; break; case MOUNT_TYPE_MFS: ty = MNTTAB_TYPE_MFS; break; default: ty = "unknown"; break; } new_mp->mnt_type = strdup(ty); new_mp->mnt_opts = strdup("unset"); new_mp->mnt_freq = 0; new_mp->mnt_passno = 0; return new_mp; }
void ops_showamfstypes(char *buf, size_t l) { struct am_ops **ap; int linesize = 0; buf[0] = '\0'; for (ap = vops; *ap; ap++) { xstrlcat(buf, (*ap)->fs_type, l); if (ap[1]) xstrlcat(buf, ", ", l); linesize += strlen((*ap)->fs_type) + 2; if (linesize > 62) { linesize = 0; xstrlcat(buf, "\n ", l); } } }
void fatalerror(char *str) { #define ERRM ": %m" size_t l = strlen(str) + sizeof(ERRM) - 1; char *tmp = strnsave(str, l); xstrlcat(tmp, ERRM, l); fatal(tmp); }
void mapc_showtypes(char *buf, size_t l) { map_type *mt=NULL, *lastmt; int linesize = 0, i; i = sizeof(maptypes) / sizeof(maptypes[0]); lastmt = maptypes + i; buf[0] = '\0'; for (mt = maptypes; mt < lastmt; mt++) { xstrlcat(buf, mt->name, l); if (mt == (lastmt-1)) break; /* if last one, don't do xstrlcat's that follows */ linesize += strlen(mt->name); if (--i > 0) { xstrlcat(buf, ", ", l); linesize += 2; } if (linesize > 54) { linesize = 0; xstrlcat(buf, "\n\t\t ", l); } } }
/* * Process PAWD string of remote pawd tool. * * We repeat the resolution of the string until the resolved string resolves * to itself. This ensures that we follow path resolutions through all * possible Amd mount points until we reach some sort of convergence. To * prevent possible infinite loops, we break out of this loop if the strings * do not converge after MAX_PAWD_TRIES times. */ amq_string * amqproc_pawd_1_svc(voidp argp, struct svc_req *rqstp) { static amq_string res; #define MAX_PAWD_TRIES 10 int index, len, maxagain = MAX_PAWD_TRIES; am_node *mp; char *mountpoint; char *dir = *(char **) argp; static char tmp_buf[MAXPATHLEN]; char prev_buf[MAXPATHLEN]; tmp_buf[0] = prev_buf[0] = '\0'; /* default is empty string: no match */ do { for (mp = get_first_exported_ap(&index); mp; mp = get_next_exported_ap(&index)) { if (STREQ(mp->am_al->al_mnt->mf_ops->fs_type, "toplvl")) continue; if (STREQ(mp->am_al->al_mnt->mf_ops->fs_type, "auto")) continue; mountpoint = (mp->am_link ? mp->am_link : mp->am_al->al_mnt->mf_mount); len = strlen(mountpoint); if (len == 0) continue; if (!NSTREQ(mountpoint, dir, len)) continue; if (dir[len] != '\0' && dir[len] != '/') continue; xstrlcpy(tmp_buf, mp->am_path, sizeof(tmp_buf)); xstrlcat(tmp_buf, &dir[len], sizeof(tmp_buf)); break; } /* end of "for" loop */ /* once tmp_buf and prev_buf are equal, break out of "do" loop */ if (STREQ(tmp_buf, prev_buf)) break; else xstrlcpy(prev_buf, tmp_buf, sizeof(prev_buf)); } while (--maxagain); /* check if we couldn't resolve the string after MAX_PAWD_TRIES times */ if (maxagain <= 0) plog(XLOG_WARNING, "path \"%s\" did not resolve after %d tries", tmp_buf, MAX_PAWD_TRIES); res = tmp_buf; return &res; }
/* get string version (in hex) of identifier */ static char * get_hex_string(u_int len, const char *fhdata) { u_int i; static char buf[128]; /* better not go over it! */ char str[16]; short int arr[64]; if (!fhdata) return NULL; buf[0] = '\0'; memset(&arr[0], 0, (64 * sizeof(short int))); memcpy(&arr[0], &fhdata[0], len); for (i=0; i<len/sizeof(unsigned short int); i++) { xsnprintf(str, sizeof(str), "%04x", ntohs(arr[i])); xstrlcat(buf, str, sizeof(buf)); } return buf; }
/* * Display a pwd data */ static void show_pwd(amq_mount_tree *mt, char *path, size_t l, int *flag) { int len; while (mt) { len = strlen(mt->mt_mountpoint); if (NSTREQ(path, mt->mt_mountpoint, len) && !STREQ(mt->mt_directory, mt->mt_mountpoint)) { char buf[MAXPATHLEN+1]; /* must be same size as 'path' */ xstrlcpy(buf, mt->mt_directory, sizeof(buf)); xstrlcat(buf, &path[len], sizeof(buf)); xstrlcpy(path, buf, l); *flag = 1; } show_pwd(mt->mt_next, path, l, flag); mt = mt->mt_child; } }
/* * See if btree or recno databases in the destination are out of date * with respect to a single manpath component. * Return -1 on fatal error, 0 if the source is no longer valid (and * shouldn't be listed), and 1 if the update went well. */ static int treecpy(char *dst, char *src) { size_t dsz, ssz; int rc; dsz = strlen(dst); ssz = strlen(src); xstrlcat(src, "/", MAXPATHLEN); xstrlcat(dst, "/", MAXPATHLEN); xstrlcat(src, MANDOC_IDX, MAXPATHLEN); xstrlcat(dst, MANDOC_IDX, MAXPATHLEN); if (-1 == (rc = isnewer(dst, src))) return(0); dst[(int)dsz] = src[(int)ssz] = '\0'; if (1 == rc) return(update(dst, src)); xstrlcat(src, "/", MAXPATHLEN); xstrlcat(dst, "/", MAXPATHLEN); xstrlcat(src, MANDOC_DB, MAXPATHLEN); xstrlcat(dst, MANDOC_DB, MAXPATHLEN); if (-1 == (rc = isnewer(dst, src))) return(0); else if (rc == 0) return(1); dst[(int)dsz] = src[(int)ssz] = '\0'; return(update(dst, src)); }
/* return malloc'ed buffer. caller must free it */ char * print_wires(void) { addrlist *al; char s[256]; int i; char *buf; int bufcount = 0; int buf_size = 1024; buf = SALLOC(buf_size); /* initial allocation (may grow!) */ if (!buf) return NULL; if (!localnets) { xstrlcpy(buf, "No networks\n", buf_size); return buf; } /* check if there's more than one network */ if (!localnets->ip_next) { /* use buf_size for sizeof(buf) because of the realloc() below */ xsnprintf(buf, buf_size, "Network: wire=\"%s\" (netnumber=%s).\n", localnets->ip_net_name, localnets->ip_net_num); return buf; } buf[0] = '\0'; /* null out buffer before appending */ for (i = 1, al = localnets; al; al = al->ip_next, i++) { xsnprintf(s, sizeof(s), "Network %d: wire=\"%s\" (netnumber=%s).\n", i, al->ip_net_name, al->ip_net_num); bufcount += strlen(s); if (bufcount > buf_size) { buf_size *= 2; buf = xrealloc(buf, buf_size); } xstrlcat(buf, s, buf_size); } return buf; }
/* * Copy both recno and btree databases into the destination. * Call in to begin recreating HTML files. * Return -1 on fatal error and 1 if the update went well. */ static int update(char *dst, char *src) { size_t dsz, ssz; dsz = strlen(dst); ssz = strlen(src); xstrlcat(src, "/", MAXPATHLEN); xstrlcat(dst, "/", MAXPATHLEN); xstrlcat(src, MANDOC_DB, MAXPATHLEN); xstrlcat(dst, MANDOC_DB, MAXPATHLEN); if ( ! filecpy(dst, src)) return(-1); if (verbose) printf("%s\n", dst); dst[(int)dsz] = src[(int)ssz] = '\0'; xstrlcat(src, "/", MAXPATHLEN); xstrlcat(dst, "/", MAXPATHLEN); xstrlcat(src, MANDOC_IDX, MAXPATHLEN); xstrlcat(dst, MANDOC_IDX, MAXPATHLEN); if ( ! filecpy(dst, src)) return(-1); if (verbose) printf("%s\n", dst); dst[(int)dsz] = src[(int)ssz] = '\0'; return(indexhtml(src, ssz, dst, dsz)); }
static void set_auto_attrcache_timeout(char *preopts, char *opts, size_t l) { #ifdef MNTTAB_OPT_NOAC /* * Don't cache attributes - they are changing under the kernel's feet. * For example, IRIX5.2 will dispense with nfs lookup calls and hand stale * filehandles to getattr unless we disable attribute caching on the * automount points. */ if (gopt.auto_attrcache == 0) { xsnprintf(preopts, l, ",%s", MNTTAB_OPT_NOAC); xstrlcat(opts, preopts, l); } #endif /* MNTTAB_OPT_NOAC */ /* * XXX: note that setting these to 0 in the past resulted in an error on * some systems, which is why it's better to use "noac" if possible. For * now, we're setting everything possible, but if this will cause trouble, * then we'll have to condition the remainder of this on OPT_NOAC. */ #ifdef MNTTAB_OPT_ACTIMEO xsnprintf(preopts, l, ",%s=%d", MNTTAB_OPT_ACTIMEO, gopt.auto_attrcache); xstrlcat(opts, preopts, l); #else /* MNTTAB_OPT_ACTIMEO */ # ifdef MNTTAB_OPT_ACDIRMIN xsnprintf(preopts, l, ",%s=%d", MNTTAB_OPT_ACTDIRMIN, gopt.auto_attrcache); xstrlcat(opts, preopts, l); # endif /* MNTTAB_OPT_ACDIRMIN */ # ifdef MNTTAB_OPT_ACDIRMAX xsnprintf(preopts, l, ",%s=%d", MNTTAB_OPT_ACTDIRMAX, gopt.auto_attrcache); xstrlcat(opts, preopts, l); # endif /* MNTTAB_OPT_ACDIRMAX */ # ifdef MNTTAB_OPT_ACREGMIN xsnprintf(preopts, l, ",%s=%d", MNTTAB_OPT_ACTREGMIN, gopt.auto_attrcache); xstrlcat(opts, preopts, l); # endif /* MNTTAB_OPT_ACREGMIN */ # ifdef MNTTAB_OPT_ACREGMAX xsnprintf(preopts, l, ",%s=%d", MNTTAB_OPT_ACTREGMAX, gopt.auto_attrcache); xstrlcat(opts, preopts, l); # endif /* MNTTAB_OPT_ACREGMAX */ #endif /* MNTTAB_OPT_ACTIMEO */ }
int autofs_get_fh(am_node *mp) { autofs_fh_t *fh; char buf[MAXHOSTNAMELEN]; mntfs *mf = mp->am_al->al_mnt; struct utsname utsname; plog(XLOG_DEBUG, "autofs_get_fh for %s", mp->am_path); fh = ALLOC(autofs_fh_t); memset((voidp) fh, 0, sizeof(autofs_fh_t)); /* Paranoid */ /* * SET MOUNT ARGS */ if (uname(&utsname) < 0) { xstrlcpy(buf, "localhost.autofs", sizeof(buf)); } else { xstrlcpy(buf, utsname.nodename, sizeof(buf)); xstrlcat(buf, ".autofs", sizeof(buf)); } #ifdef HAVE_AUTOFS_ARGS_T_ADDR fh->addr.buf = xstrdup(buf); fh->addr.len = fh->addr.maxlen = strlen(buf); #endif /* HAVE_AUTOFS_ARGS_T_ADDR */ fh->direct = (mf->mf_fsflags & FS_DIRECT) ? 1 : 0; fh->rpc_to = 1; /* XXX: arbitrary */ fh->mount_to = mp->am_timeo; fh->path = mp->am_path; fh->opts = ""; /* XXX: arbitrary */ fh->map = mp->am_path; /* this is what we get back in readdir */ mp->am_autofs_fh = fh; return 0; }
/* * Return the version string (dynamic buffer) */ char * get_version_string(void) { char *vers = NULL; char tmpbuf[1024]; char *wire_buf; int wire_buf_len = 0; size_t len; /* max allocated length (to avoid buf overflow) */ /* * First get dynamic string listing all known networks. * This could be a long list, if host has lots of interfaces. */ wire_buf = print_wires(); if (wire_buf) wire_buf_len = strlen(wire_buf); len = 2048 + wire_buf_len; vers = xmalloc(len); xsnprintf(vers, len, "%s\n%s\n%s\n%s\n", "Copyright (c) 1997-2014 Erez Zadok", "Copyright (c) 1990 Jan-Simon Pendry", "Copyright (c) 1990 Imperial College of Science, Technology & Medicine", "Copyright (c) 1990 The Regents of the University of California."); xsnprintf(tmpbuf, sizeof(tmpbuf), "%s version %s (build %d).\n", PACKAGE_NAME, PACKAGE_VERSION, AMU_BUILD_VERSION); xstrlcat(vers, tmpbuf, len); xsnprintf(tmpbuf, sizeof(tmpbuf), "Report bugs to %s.\n", PACKAGE_BUGREPORT); xstrlcat(vers, tmpbuf, len); #if 0 /* * XXX This block (between from the #if 0 to #endif was in the * XXX original was in the original merge however in the interest * XXX of reproduceable builds and the fact that this is redundant * XXX information, it is effectively removed. */ xsnprintf(tmpbuf, sizeof(tmpbuf), "Configured by %s@%s on date %s.\n", USER_NAME, HOST_NAME, CONFIG_DATE); xstrlcat(vers, tmpbuf, len); xsnprintf(tmpbuf, sizeof(tmpbuf), "Built by %s@%s on date %s.\n", BUILD_USER, BUILD_HOST, BUILD_DATE); xstrlcat(vers, tmpbuf, len); #endif xsnprintf(tmpbuf, sizeof(tmpbuf), "cpu=%s (%s-endian), arch=%s, karch=%s.\n", cpu, endian, gopt.arch, gopt.karch); xstrlcat(vers, tmpbuf, len); xsnprintf(tmpbuf, sizeof(tmpbuf), "full_os=%s, os=%s, osver=%s, vendor=%s, distro=%s.\n", gopt.op_sys_full, gopt.op_sys, gopt.op_sys_ver, gopt.op_sys_vendor, DISTRO_NAME); xstrlcat(vers, tmpbuf, len); xsnprintf(tmpbuf, sizeof(tmpbuf), "domain=%s, host=%s, hostd=%s.\n", hostdomain, am_get_hostname(), hostd); xstrlcat(vers, tmpbuf, len); xstrlcat(vers, "Map support for: ", len); mapc_showtypes(tmpbuf, sizeof(tmpbuf)); xstrlcat(vers, tmpbuf, len); xstrlcat(vers, ".\nAMFS: ", len); ops_showamfstypes(tmpbuf, sizeof(tmpbuf)); xstrlcat(vers, tmpbuf, len); xstrlcat(vers, ", inherit.\nFS: ", len); /* hack: "show" that we support type:=inherit */ ops_showfstypes(tmpbuf, sizeof(tmpbuf)); xstrlcat(vers, tmpbuf, len); /* append list of networks if available */ if (wire_buf) { xstrlcat(vers, wire_buf, len); XFREE(wire_buf); } return vers; }
/* * Mount the top-level */ int amfs_toplvl_mount(am_node *mp, mntfs *mf) { struct stat stb; char opts[SIZEOF_OPTS], preopts[SIZEOF_OPTS], toplvl_opts[40]; int error; /* * Mounting the automounter. * Make sure the mount directory exists, construct * the mount options and call the mount_amfs_toplvl routine. */ if (stat(mp->am_path, &stb) < 0) { return errno; } else if ((stb.st_mode & S_IFMT) != S_IFDIR) { plog(XLOG_WARNING, "%s is not a directory", mp->am_path); return ENOTDIR; } /* * Construct some mount options: * * Tack on magic map=<mapname> option in mtab to emulate * SunOS automounter behavior. */ #ifdef HAVE_FS_AUTOFS if (mf->mf_flags & MFF_IS_AUTOFS) { autofs_get_opts(opts, sizeof(opts), mp->am_autofs_fh); } else #endif /* HAVE_FS_AUTOFS */ { preopts[0] = '\0'; #ifdef MNTTAB_OPT_INTR xstrlcat(preopts, MNTTAB_OPT_INTR, sizeof(preopts)); xstrlcat(preopts, ",", sizeof(preopts)); #endif /* MNTTAB_OPT_INTR */ #ifdef MNTTAB_OPT_IGNORE xstrlcat(preopts, MNTTAB_OPT_IGNORE, sizeof(preopts)); xstrlcat(preopts, ",", sizeof(preopts)); #endif /* MNTTAB_OPT_IGNORE */ /* write most of the initial options + preopts */ xsnprintf(opts, sizeof(opts), "%s%s,%s=%d,%s,map=%s", preopts, MNTTAB_OPT_RW, MNTTAB_OPT_PORT, nfs_port, mf->mf_ops->fs_type, mf->mf_info); /* process toplvl timeo/retrans options, if any */ if (gopt.amfs_auto_timeo[AMU_TYPE_TOPLVL] > 0) { xsnprintf(toplvl_opts, sizeof(toplvl_opts), ",%s=%d", MNTTAB_OPT_TIMEO, gopt.amfs_auto_timeo[AMU_TYPE_TOPLVL]); xstrlcat(opts, toplvl_opts, sizeof(opts)); } if (gopt.amfs_auto_retrans[AMU_TYPE_TOPLVL] > 0) { xsnprintf(toplvl_opts, sizeof(toplvl_opts), ",%s=%d", MNTTAB_OPT_RETRANS, gopt.amfs_auto_retrans[AMU_TYPE_TOPLVL]); xstrlcat(opts, toplvl_opts, sizeof(opts)); } #ifdef MNTTAB_OPT_NOLOCK xstrlcat(opts, ",", sizeof(opts)); xstrlcat(opts, MNTTAB_OPT_NOLOCK, sizeof(opts)); #endif /* MNTTAB_OPT_NOLOCK */ #ifdef MNTTAB_OPT_NOAC if (gopt.auto_attrcache == 0) { xstrlcat(opts, ",", sizeof(opts)); xstrlcat(opts, MNTTAB_OPT_NOAC, sizeof(opts)); } else #endif /* MNTTAB_OPT_NOAC */ set_auto_attrcache_timeout(preopts, opts, sizeof(preopts)); } /* now do the mount */ error = amfs_mount(mp, mf, opts); if (error) { errno = error; plog(XLOG_FATAL, "amfs_toplvl_mount: amfs_mount failed: %m"); return error; } return 0; }
static char * hack_name(char *dir) { char partition[MAXPATHLEN]; char username[MAXPATHLEN]; char hesiod_lookup[MAXPATHLEN]; char *to, *ch, *hes_name, *dot; char **hes; #ifdef DEBUG fprintf(stderr, "hack_name(%s)\n", dir); #endif /* DEBUG */ if (dir[0] == '/' && dir[1] == 'a' && dir[2] == '/') { /* Could be /a/server/disk/home/partition/user... */ ch = dir + 3; while (*ch && *ch != '/') ch++; /* Skip server */ if (!NSTREQ(ch, "/disk/home/", 11)) return NULL; /* Nope */ /* Looking promising, next should be the partition name */ ch += 11; to = partition; while (*ch && *ch != '/') *to++ = *ch++; to = '\0'; if (!(*ch)) return NULL; /* Off the end */ /* Now the username */ ch++; to = username; while (*ch && *ch != '/') *to++ = *ch++; to = '\0'; #ifdef DEBUG fprintf(stderr, "partition %s, username %s\n", partition, username); #endif /* DEBUG */ xsnprintf(hesiod_lookup, sizeof(hesiod_lookup), "%s.homes-remote", username); hes = hes_resolve(hesiod_lookup, "amd"); if (!hes) return NULL; #ifdef DEBUG fprintf(stderr, "hesiod -> <%s>\n", *hes); #endif /* DEBUG */ hes_name = strstr(*hes, "/homes/remote/"); if (!hes_name) return NULL; hes_name += 14; #ifdef DEBUG fprintf(stderr, "hesiod -> <%s>\n", hes_name); #endif /* DEBUG */ dot = hes_name; while (*dot && *dot != '.') dot++; *dot = '\0'; #ifdef DEBUG fprintf(stderr, "hesiod -> <%s>\n", hes_name); #endif /* DEBUG */ if (strcmp(partition, hes_name)) return NULL; #ifdef DEBUG fprintf(stderr, "A match, munging....\n"); #endif /* DEBUG */ xstrlcpy(transform, "/home/", sizeof(transform)); xstrlcat(transform, username, sizeof(transform)); if (*ch) xstrlcat(transform, ch, sizeof(transform)); #ifdef DEBUG fprintf(stderr, "Munged to <%s>\n", transform); #endif /* DEBUG */ return transform; } return NULL; }
void ops_showfstypes(char *buf, size_t l) { int linesize = 0; buf[0] = '\0'; #ifdef MNTTAB_TYPE_AUTOFS ops_show1(buf, l, &linesize, MNTTAB_TYPE_AUTOFS); #endif /* MNTTAB_TYPE_AUTOFS */ #ifdef MNTTAB_TYPE_CACHEFS ops_show1(buf, l, &linesize, MNTTAB_TYPE_CACHEFS); #endif /* MNTTAB_TYPE_CACHEFS */ #ifdef MNTTAB_TYPE_CDFS ops_show1(buf, l, &linesize, MNTTAB_TYPE_CDFS); #endif /* MNTTAB_TYPE_CDFS */ #ifdef MNTTAB_TYPE_CFS ops_show1(buf, l, &linesize, MNTTAB_TYPE_CFS); #endif /* MNTTAB_TYPE_CFS */ #ifdef MNTTAB_TYPE_LOFS ops_show1(buf, l, &linesize, MNTTAB_TYPE_LOFS); #endif /* MNTTAB_TYPE_LOFS */ #ifdef MNTTAB_TYPE_EFS ops_show1(buf, l, &linesize, MNTTAB_TYPE_EFS); #endif /* MNTTAB_TYPE_EFS */ #ifdef MNTTAB_TYPE_MFS ops_show1(buf, l, &linesize, MNTTAB_TYPE_MFS); #endif /* MNTTAB_TYPE_MFS */ #ifdef MNTTAB_TYPE_NFS ops_show1(buf, l, &linesize, MNTTAB_TYPE_NFS); #endif /* MNTTAB_TYPE_NFS */ #ifdef MNTTAB_TYPE_NFS3 ops_show1(buf, l, &linesize, "nfs3"); /* always hard-code as nfs3 */ #endif /* MNTTAB_TYPE_NFS3 */ #ifdef MNTTAB_TYPE_NULLFS ops_show1(buf, l, &linesize, MNTTAB_TYPE_NULLFS); #endif /* MNTTAB_TYPE_NULLFS */ #ifdef MNTTAB_TYPE_PCFS ops_show1(buf, l, &linesize, MNTTAB_TYPE_PCFS); #endif /* MNTTAB_TYPE_PCFS */ #ifdef MNTTAB_TYPE_TFS ops_show1(buf, l, &linesize, MNTTAB_TYPE_TFS); #endif /* MNTTAB_TYPE_TFS */ #ifdef MNTTAB_TYPE_TMPFS ops_show1(buf, l, &linesize, MNTTAB_TYPE_TMPFS); #endif /* MNTTAB_TYPE_TMPFS */ #ifdef MNTTAB_TYPE_UFS ops_show1(buf, l, &linesize, MNTTAB_TYPE_UFS); #endif /* MNTTAB_TYPE_UFS */ #ifdef MNTTAB_TYPE_UMAPFS ops_show1(buf, l, &linesize, MNTTAB_TYPE_UMAPFS); #endif /* MNTTAB_TYPE_UMAPFS */ #ifdef MNTTAB_TYPE_UNIONFS ops_show1(buf, l, &linesize, MNTTAB_TYPE_UNIONFS); #endif /* MNTTAB_TYPE_UNIONFS */ #ifdef MNTTAB_TYPE_XFS ops_show1(buf, l, &linesize, MNTTAB_TYPE_XFS); #endif /* MNTTAB_TYPE_XFS */ /* terminate with a period, newline, and NULL */ if (buf[strlen(buf)-1] == '\n') buf[strlen(buf) - 4] = '\0'; else buf[strlen(buf) - 2] = '\0'; xstrlcat(buf, ".\n", l); }
/* * Write out a mount list */ void rewrite_mtab(mntlist *mp, const char *mnttabname) { FILE *mfp; int error = 0; char tmpname[64]; int retries; int tmpfd; char *cp; char mcp[128]; if (!mtab_is_writable()) { return; } /* * Concoct a temporary name in the same directory as the target mount * table so that rename() will work. */ xstrlcpy(mcp, mnttabname, sizeof(mcp)); cp = strrchr(mcp, '/'); if (cp) { memmove(tmpname, mcp, cp - mcp); tmpname[cp - mcp] = '\0'; } else { plog(XLOG_WARNING, "No '/' in mtab (%s), using \".\" as tmp directory", mnttabname); tmpname[0] = '.'; tmpname[1] = '\0'; } xstrlcat(tmpname, "/mtabXXXXXX", sizeof(tmpname)); retries = 0; enfile1: #ifdef HAVE_MKSTEMP tmpfd = mkstemp(tmpname); fchmod(tmpfd, 0644); #else /* not HAVE_MKSTEMP */ mktemp(tmpname); tmpfd = open(tmpname, O_RDWR | O_CREAT | O_TRUNC, 0644); #endif /* not HAVE_MKSTEMP */ if (tmpfd < 0) { if (errno == ENFILE && retries++ < NFILE_RETRIES) { sleep(1); goto enfile1; } plog(XLOG_ERROR, "%s: open: %m", tmpname); return; } if (close(tmpfd) < 0) plog(XLOG_ERROR, "Couldn't close tmp file descriptor: %m"); retries = 0; enfile2: mfp = setmntent(tmpname, "w"); if (!mfp) { if (errno == ENFILE && retries++ < NFILE_RETRIES) { sleep(1); goto enfile2; } plog(XLOG_ERROR, "setmntent(\"%s\", \"w\"): %m", tmpname); error = 1; goto out; } while (mp) { if (mp->mnt) { if (addmntent(mfp, mp->mnt)) { plog(XLOG_ERROR, "Can't write entry to %s", tmpname); error = 1; goto out; } } mp = mp->mnext; } /* * SunOS 4.1 manuals say that the return code from entmntent() * is always 1 and to treat as a void. That means we need to * call fflush() to make sure the new mtab file got written. */ if (fflush(mfp)) { plog(XLOG_ERROR, "flush new mtab file: %m"); error = 1; goto out; } (void) endmntent(mfp); /* * Rename temporary mtab to real mtab */ if (rename(tmpname, mnttabname) < 0) { plog(XLOG_ERROR, "rename %s to %s: %m", tmpname, mnttabname); error = 1; goto out; } out: if (error) (void) unlink(tmpname); }
/* * Pass over the recno database and re-create HTML pages if they're * found to be out of date. * Returns -1 on fatal error, 1 on success. */ static int indexhtml(char *src, size_t ssz, char *dst, size_t dsz) { DB *idx; DBT key, val; int c, rc; unsigned int fl; const char *f; char *d; char fname[MAXPATHLEN]; pid_t pid; pid = -1; xstrlcpy(fname, dst, MAXPATHLEN); xstrlcat(fname, "/", MAXPATHLEN); xstrlcat(fname, MANDOC_IDX, MAXPATHLEN); idx = dbopen(fname, O_RDONLY, 0, DB_RECNO, NULL); if (NULL == idx) { perror(fname); return(-1); } fl = R_FIRST; while (0 == (c = (*idx->seq)(idx, &key, &val, fl))) { fl = R_NEXT; /* * If the record is zero-length, then it's unassigned. * Skip past these. */ if (0 == val.size) continue; f = (const char *)val.data + 1; if (NULL == memchr(f, '\0', val.size - 1)) break; src[(int)ssz] = dst[(int)dsz] = '\0'; xstrlcat(dst, "/", MAXPATHLEN); xstrlcat(dst, f, MAXPATHLEN); xstrlcat(src, "/", MAXPATHLEN); xstrlcat(src, f, MAXPATHLEN); if (-1 == (rc = isnewer(dst, src))) { fprintf(stderr, "%s: File missing\n", f); break; } else if (0 == rc) continue; d = strrchr(dst, '/'); assert(NULL != d); *d = '\0'; if (-1 == mkpath(dst, 0755, 0755)) { perror(dst); break; } *d = '/'; if ( ! filecpy(dst, src)) break; if (verbose) printf("%s\n", dst); } (*idx->close)(idx); if (c < 0) perror(fname); else if (0 == c) fprintf(stderr, "%s: Corrupt index\n", fname); return(1 == c ? 1 : -1); }
int main(int argc, char *argv[]) { char *dot; char *mntopts = (char *) NULL; char hostpid_fs[MAXHOSTNAMELEN + 1 + 16]; /* room for ":(pid###)" */ char progpid_fs[PROGNAMESZ + 1 + 11]; /* room for ":pid" */ char preopts[128]; char *progname; int forcecache = 0; int forcefast = 0; int genflags = 0; int opt, ret; int opterrs = 0; int retry; int soNFS; /* NFS socket */ int s = -99; mntent_t mnt; nfs_args_t nfs_args; am_nfs_handle_t anh; struct dirent *direntry; struct group *grp; struct stat stmodes; DIR *mountdir; MTYPE_TYPE type = MOUNT_TYPE_NFS; #ifdef HAVE_SIGACTION struct sigaction sa; #endif /* not HAVE_SIGACTION */ #ifndef HAVE_TRANSPORT_TYPE_TLI struct sockaddr_in localsocket; #endif /* not HAVE_TRANSPORT_TYPE_TLI */ /* get program name and truncate so we don't overflow progpid_fs */ if ((progname = strrchr(argv[0], '/')) != NULL) progname++; else progname = argv[0]; if ((int) strlen(progname) > PROGNAMESZ) /* truncate to reasonable size */ progname[PROGNAMESZ] = '\0'; am_set_progname(progname); while ((opt = getopt(argc, argv, "a:c:CD:fg:hi:l:no:pP:x:v")) != -1) switch (opt) { case 'a': if (!optarg || optarg[0] != '/') { printf("%s: invalid directory for -a: %s\n", am_get_progname(), optarg); exit(3); } alt_spooldir = optarg; break; case 'c': if (!atoi(optarg)) { printf("%s: invalid interval for -c: %s\n", am_get_progname(), optarg); exit(3); } cache_interval = atoi(optarg); break; case 'C': forcecache++; break; case 'f': forcefast++; break; case 'g': hlfs_group = optarg; break; case 'i': if (!atoi(optarg)) { printf("%s: invalid interval for -i: %s\n", am_get_progname(), optarg); exit(3); } reloadinterval.it_interval.tv_sec = atoi(optarg); reloadinterval.it_value.tv_sec = atoi(optarg); break; case 'l': logfile = optarg; break; case 'n': noverify++; break; case 'o': mntopts = optarg; break; case 'p': printpid++; break; case 'P': passwdfile = optarg; break; case 'v': fprintf(stderr, "%s\n", HLFSD_VERSION); exit(0); case 'x': opterrs += switch_option(optarg); break; case 'D': #ifdef DEBUG opterrs += debug_option(optarg); #else /* not DEBUG */ fprintf(stderr, "%s: not compiled with DEBUG -- sorry.\n", am_get_progname()); #endif /* not DEBUG */ break; case 'h': case '?': opterrs++; } /* need my pid before any dlog/plog */ am_set_mypid(); #ifdef DEBUG switch_option("debug"); #endif /* DEBUG */ /* * Terminate if did not ask to forcecache (-C) and hlfsd would not be able * to set the minimum cache intervals. */ #if !defined(MNT2_NFS_OPT_ACREGMIN) && !defined(MNT2_NFS_OPT_NOAC) && !defined(HAVE_NFS_ARGS_T_ACREGMIN) if (!forcecache) { fprintf(stderr, "%s: will not be able to turn off attribute caches.\n", am_get_progname()); exit(1); } #endif /* !defined(MNT2_NFS_OPT_ACREGMIN) && !defined(MNT2_NFS_OPT_NOAC) && !defined(HAVE_NFS_ARGS_T_ACREGMIN) */ switch (argc - optind) { case 2: home_subdir = argv[optind + 1]; case 1: dir_name = argv[optind]; case 0: break; default: opterrs++; } if (opterrs) usage(); /* ensure that only root can run hlfsd */ if (geteuid()) { fprintf(stderr, "hlfsd can only be run as root\n"); exit(1); } setbuf(stdout, (char *) NULL); umask(0); /* find gid for hlfs_group */ if ((grp = getgrnam(hlfs_group)) == (struct group *) NULL) { fprintf(stderr, "%s: cannot get gid for group \"%s\".\n", am_get_progname(), hlfs_group); } else { hlfs_gid = grp->gr_gid; } /* get hostname for logging and open log before we reset umask */ gethostname(hostname, sizeof(hostname)); hostname[sizeof(hostname) - 1] = '\0'; if ((dot = strchr(hostname, '.')) != NULL) *dot = '\0'; orig_umask = umask(0); if (logfile) switch_to_logfile(logfile, orig_umask, 0); #ifndef MOUNT_TABLE_ON_FILE if (amuDebug(D_MTAB)) dlog("-D mtab option ignored"); #endif /* not MOUNT_TABLE_ON_FILE */ /* avoid hanging on other NFS servers if started elsewhere */ if (chdir("/") < 0) fatal("cannot chdir to /: %m"); if (geteuid() != 0) fatal("must be root to mount filesystems"); /* * dir_name must match "^(/.*)/([^/]+)$", and is split at last '/' with * slinkname = `basename $dir_name` - requires dir_name be writable */ if (dir_name[0] != '/' || ((slinkname = strrchr(dir_name, '/')), *slinkname++ = '\0', (dir_name[0] == '\0' || slinkname[0] == '\0'))) { if (slinkname) *--slinkname = '/'; printf("%s: invalid mount directory/link %s\n", am_get_progname(), dir_name); exit(3); } if (!forcefast) { /* make sure mount point exists and is at least mode 555 */ if (stat(dir_name, &stmodes) < 0) if (errno != ENOENT || mkdirs(dir_name, 0555) < 0 || stat(dir_name, &stmodes) < 0) fatalerror(dir_name); if ((stmodes.st_mode & 0555) != 0555) { fprintf(stderr, "%s: directory %s not read/executable\n", am_get_progname(), dir_name); plog(XLOG_WARNING, "directory %s not read/executable", dir_name); } /* warn if extraneous stuff will be hidden by mount */ if ((mountdir = opendir(dir_name)) == NULL) fatalerror(dir_name); while ((direntry = readdir(mountdir)) != NULL) { if (!NSTREQ(".", direntry->d_name, NAMLEN(direntry)) && !NSTREQ("..", direntry->d_name, NAMLEN(direntry)) && !NSTREQ(slinkname, direntry->d_name, NAMLEN(direntry))) break; } if (direntry != NULL) { fprintf(stderr, "%s: %s/%s will be hidden by mount\n", am_get_progname(), dir_name, direntry->d_name); plog(XLOG_WARNING, "%s/%s will be hidden by mount\n", dir_name, direntry->d_name); } closedir(mountdir); /* make sure alternate spool dir exists */ if ((errno = mkdirs(alt_spooldir, OPEN_SPOOLMODE))) { fprintf(stderr, "%s: cannot create alternate dir ", am_get_progname()); perror(alt_spooldir); plog(XLOG_ERROR, "cannot create alternate dir %s: %m", alt_spooldir); } chmod(alt_spooldir, OPEN_SPOOLMODE); /* create failsafe link to alternate spool directory */ *(slinkname-1) = '/'; /* unsplit dir_name to include link */ if (lstat(dir_name, &stmodes) == 0 && (stmodes.st_mode & S_IFMT) != S_IFLNK) { fprintf(stderr, "%s: failsafe %s not a symlink\n", am_get_progname(), dir_name); plog(XLOG_WARNING, "failsafe %s not a symlink\n", dir_name); } else { unlink(dir_name); if (symlink(alt_spooldir, dir_name) < 0) { fprintf(stderr, "%s: cannot create failsafe symlink %s -> ", am_get_progname(), dir_name); perror(alt_spooldir); plog(XLOG_WARNING, "cannot create failsafe symlink %s -> %s: %m", dir_name, alt_spooldir); } } *(slinkname-1) = '\0'; /* resplit dir_name */ } /* end of "if (!forcefast) {" */ /* * Register hlfsd as an nfs service with the portmapper. */ #ifdef HAVE_TRANSPORT_TYPE_TLI ret = create_nfs_service(&soNFS, &nfs_port, &nfsxprt, nfs_program_2); #else /* not HAVE_TRANSPORT_TYPE_TLI */ ret = create_nfs_service(&soNFS, &nfs_port, &nfsxprt, nfs_program_2); #endif /* not HAVE_TRANSPORT_TYPE_TLI */ if (ret != 0) fatal("cannot create NFS service"); #ifdef HAVE_SIGACTION sa.sa_handler = proceed; sa.sa_flags = 0; sigemptyset(&(sa.sa_mask)); sigaddset(&(sa.sa_mask), SIGUSR2); sigaction(SIGUSR2, &sa, NULL); #else /* not HAVE_SIGACTION */ signal(SIGUSR2, proceed); #endif /* not HAVE_SIGACTION */ plog(XLOG_INFO, "Initializing hlfsd..."); hlfsd_init(); /* start up child (forking) to run svc_run */ #ifdef HAVE_SIGACTION sa.sa_handler = reaper; sa.sa_flags = 0; sigemptyset(&(sa.sa_mask)); sigaddset(&(sa.sa_mask), SIGCHLD); sigaction(SIGCHLD, &sa, NULL); #else /* not HAVE_SIGACTION */ signal(SIGCHLD, reaper); #endif /* not HAVE_SIGACTION */ /* * In the parent, if -D nodaemon, we don't need to * set this signal handler. */ if (amuDebug(D_DAEMON)) { s = -99; while (stoplight != SIGUSR2) { plog(XLOG_INFO, "parent waits for child to setup (stoplight=%d)", stoplight); #ifdef HAVE_SIGSUSPEND { sigset_t mask; sigemptyset(&mask); s = sigsuspend(&mask); /* wait for child to set up */ } #else /* not HAVE_SIGSUSPEND */ s = sigpause(0); /* wait for child to set up */ #endif /* not HAVE_SIGSUSPEND */ sleep(1); } } /* * setup options to mount table (/etc/{mtab,mnttab}) entry */ xsnprintf(hostpid_fs, sizeof(hostpid_fs), "%s:(pid%d)", hostname, masterpid); memset((char *) &mnt, 0, sizeof(mnt)); mnt.mnt_dir = dir_name; /* i.e., "/mail" */ mnt.mnt_fsname = hostpid_fs; if (mntopts) { mnt.mnt_opts = mntopts; } else { xstrlcpy(preopts, default_mntopts, sizeof(preopts)); /* * Turn off all kinds of attribute and symlink caches as * much as possible. Also make sure that mount does not * show up to df. */ #ifdef MNTTAB_OPT_INTR xstrlcat(preopts, ",", sizeof(preopts)); xstrlcat(preopts, MNTTAB_OPT_INTR, sizeof(preopts)); #endif /* MNTTAB_OPT_INTR */ #ifdef MNTTAB_OPT_IGNORE xstrlcat(preopts, ",", sizeof(preopts)); xstrlcat(preopts, MNTTAB_OPT_IGNORE, sizeof(preopts)); #endif /* MNTTAB_OPT_IGNORE */ #ifdef MNT2_GEN_OPT_CACHE xstrlcat(preopts, ",nocache", sizeof(preopts)); #endif /* MNT2_GEN_OPT_CACHE */ #ifdef MNT2_NFS_OPT_SYMTTL xstrlcat(preopts, ",symttl=0", sizeof(preopts)); #endif /* MNT2_NFS_OPT_SYMTTL */ mnt.mnt_opts = preopts; } /* * Make sure that amd's top-level NFS mounts are hidden by default * from df. * If they don't appear to support the either the "ignore" mnttab * option entry, or the "auto" one, set the mount type to "nfs". */ #ifdef HIDE_MOUNT_TYPE mnt.mnt_type = HIDE_MOUNT_TYPE; #else /* not HIDE_MOUNT_TYPE */ mnt.mnt_type = "nfs"; #endif /* not HIDE_MOUNT_TYPE */ /* some systems don't have a mount type, but a mount flag */ #ifndef HAVE_TRANSPORT_TYPE_TLI amu_get_myaddress(&localsocket.sin_addr, NULL); localsocket.sin_family = AF_INET; localsocket.sin_port = htons(nfsxprt->xp_port); #endif /* not HAVE_TRANSPORT_TYPE_TLI */ /* * Update hostname field. * Make some name prog:pid (i.e., hlfsd:174) for hostname */ xsnprintf(progpid_fs, sizeof(progpid_fs), "%s:%d", am_get_progname(), masterpid); /* Most kernels have a name length restriction. */ if ((int) strlen(progpid_fs) >= (int) MAXHOSTNAMELEN) xstrlcpy(progpid_fs + MAXHOSTNAMELEN - 3, "..", sizeof(progpid_fs) - MAXHOSTNAMELEN + 3); genflags = compute_mount_flags(&mnt); retry = hasmntval(&mnt, MNTTAB_OPT_RETRY); if (retry <= 0) retry = 1; /* XXX */ memmove(&anh.v2, root_fhp, sizeof(*root_fhp)); #ifdef HAVE_TRANSPORT_TYPE_TLI compute_nfs_args(&nfs_args, &mnt, genflags, nfsncp, NULL, /* remote host IP addr is set below */ NFS_VERSION, /* version 2 */ "udp", /* XXX: shouldn't this be "udp"? */ &anh, progpid_fs, /* host name for kernel */ hostpid_fs); /* filesystem name for kernel */ /* * IMPORTANT: set the correct IP address AFTERWARDS. It cannot * be done using the normal mechanism of compute_nfs_args(), because * that one will allocate a new address and use NFS_SA_DREF() to copy * parts to it, while assuming that the ip_addr passed is always * a "struct sockaddr_in". That assumption is incorrect on TLI systems, * because they define a special macro HOST_SELF which is DIFFERENT * than localhost (127.0.0.1)! */ nfs_args.addr = &nfsxprt->xp_ltaddr; #else /* not HAVE_TRANSPORT_TYPE_TLI */ compute_nfs_args(&nfs_args, &mnt, genflags, NULL, &localsocket, NFS_VERSION, /* version 2 */ "udp", /* XXX: shouldn't this be "udp"? */ &anh, progpid_fs, /* host name for kernel */ hostpid_fs); /* filesystem name for kernel */ #endif /* not HAVE_TRANSPORT_TYPE_TLI */ /************************************************************************* * NOTE: while compute_nfs_args() works ok for regular NFS mounts * * the toplvl one is not, and so some options must be corrected by hand * * more carefully, *after* compute_nfs_args() runs. * *************************************************************************/ compute_automounter_nfs_args(&nfs_args, &mnt); /* * For some reason, this mount may have to be done in the background, if I am * using -D daemon. I suspect that the actual act of mounting requires * calling to hlfsd itself to invoke one or more of its nfs calls, to stat * /mail. That means that even if you say -D daemon, at least the mount * of hlfsd itself on top of /mail will be done in the background. * The other alternative I have is to run svc_run, but set a special * signal handler to perform the mount in N seconds via some alarm. * -Erez Zadok. */ if (!amuDebug(D_DAEMON)) { /* Normal case */ plog(XLOG_INFO, "normal NFS mounting hlfsd service points"); if (mount_fs(&mnt, genflags, (caddr_t) &nfs_args, retry, type, 0, NULL, mnttab_file_name, 0) < 0) fatal("nfsmount: %m"); } else { /* asked for -D daemon */ if (fork() == 0) { /* child runs mount */ am_set_mypid(); foreground = 0; plog(XLOG_INFO, "child NFS mounting hlfsd service points"); if (mount_fs(&mnt, genflags, (caddr_t) &nfs_args, retry, type, 0, NULL, mnttab_file_name, 0) < 0) { fatal("nfsmount: %m"); } exit(0); /* all went well */ } else { /* fork failed or parent running */ plog(XLOG_INFO, "parent waiting 1sec for mount..."); } } #ifdef HAVE_TRANSPORT_TYPE_TLI /* * XXX: this free_knetconfig() was not done for hlfsd before, * and apparently there was a reason for it, but why? -Erez */ free_knetconfig(nfs_args.knconf); /* * local automounter mounts do not allocate a special address, so * no need to XFREE(nfs_args.addr) under TLI. */ #endif /* HAVE_TRANSPORT_TYPE_TLI */ if (printpid) printf("%d\n", masterpid); plog(XLOG_INFO, "hlfsd ready to serve"); /* * If asked not to fork a daemon (-D nodaemon), then hlfsd_init() * will not run svc_run. We must start svc_run here. */ if (!amuDebug(D_DAEMON)) { plog(XLOG_DEBUG, "starting no-daemon debugging svc_run"); svc_run(); } cleanup(0); /* should never happen here */ return (0); /* everything went fine? */ }