Exemple #1
0
static void
checkup_mem(void)
{
    struct mallinfo mi = mallinfo();
    u_long uordbytes = mi.uordblks * 4096;

    if (mem_bytes != uordbytes) {
        if (orig_mem_bytes == 0)
            mem_bytes = orig_mem_bytes = uordbytes;
        else {
            fprintf(logfp, "%s[%ld]: ", am_get_progname(), (long) am_mypid);
            if (mem_bytes < uordbytes) {
                fprintf(logfp, "ALLOC: %ld bytes", uordbytes - mem_bytes);
            } else {
                fprintf(logfp, "FREE: %ld bytes", mem_bytes - uordbytes);
            }
            mem_bytes = uordbytes;
            fprintf(logfp, ", making %d missing\n", mem_bytes - orig_mem_bytes);
        }
    }
    malloc_verify();
}
Exemple #2
0
/*
 * MAIN
 */
int
main(int argc, char *argv[])
{
  int opt_ch;
  int errs = 0;
  char *server;
  struct sockaddr_in server_addr;
  CLIENT *clnt = NULL;
  struct hostent *hp;
  int nodefault = 0;
  struct timeval tv;
  char *progname = NULL;

  /*
   * Compute program name
   */
  if (argv[0]) {
    progname = strrchr(argv[0], '/');
    if (progname && progname[1])
      progname++;
    else
      progname = argv[0];
  }
  if (!progname)
    progname = "amq";
  am_set_progname(progname);

  /*
   * Parse arguments
   */
  while ((opt_ch = getopt(argc, argv, "Hfh:l:msuvx:D:pP:TUw")) != -1)
    switch (opt_ch) {
    case 'H':
      goto show_usage;
      break;

    case 'f':
      flush_flag = 1;
      nodefault = 1;
      break;

    case 'h':
      def_server = optarg;
      break;

    case 'l':
      amq_logfile = optarg;
      nodefault = 1;
      break;

    case 'm':
      minfo_flag = 1;
      nodefault = 1;
      break;

    case 'p':
      getpid_flag = 1;
      nodefault = 1;
      break;

    case 's':
      stats_flag = 1;
      nodefault = 1;
      break;

    case 'u':
      unmount_flag = 1;
      nodefault = 1;
      break;

    case 'v':
      getvers_flag = 1;
      nodefault = 1;
      break;

    case 'x':
      xlog_optstr = optarg;
      nodefault = 1;
      break;

    case 'D':
      debug_opts = optarg;
      nodefault = 1;
      break;

    case 'P':
      amd_program_number = atoi(optarg);
      break;

    case 'T':
      use_tcp_flag = 1;
      break;

    case 'U':
      use_udp_flag = 1;
      break;

    case 'w':
      getpwd_flag = 1;
      break;

    default:
      errs = 1;
      break;
    }

  if (optind == argc) {
    if (unmount_flag)
      errs = 1;
  }
  if (errs) {
  show_usage:
    fprintf(stderr, "\
Usage: %s [-fmpsvwHTU] [-h hostname] [-l log_file|\"syslog\"]\n\
\t[-x log_options] [-D debug_options]\n\
\t[-P program_number] [[-u] directory ...]\n",
	    am_get_progname()
    );
    exit(1);
  }


  /* set use_udp and use_tcp flags both to on if none are defined */
  if (!use_tcp_flag && !use_udp_flag)
    use_tcp_flag = use_udp_flag = 1;

#if defined(HAVE_CLUSTER_H) && defined(HAVE_CNODEID) && defined(HAVE_GETCCENT)
  /*
   * Figure out root server of cluster
   */
  if (def_server == localhost)
    server = cluster_server();
  else
#endif /* defined(HAVE_CLUSTER_H) && defined(HAVE_CNODEID) && defined(HAVE_GETCCENT) */
    server = def_server;

  /*
   * Get address of server
   */
  if ((hp = gethostbyname(server)) == 0 && !STREQ(server, localhost)) {
    fprintf(stderr, "%s: Can't get address of %s\n",
	    am_get_progname(), server);
    exit(1);
  }
  memset(&server_addr, 0, sizeof(server_addr));
  /* as per POSIX, sin_len need not be set (used internally by kernel) */
  server_addr.sin_family = AF_INET;
  if (hp) {
    memmove((voidp) &server_addr.sin_addr, (voidp) hp->h_addr,
	    sizeof(server_addr.sin_addr));
  } else {
    /* fake "localhost" */
    server_addr.sin_addr.s_addr = htonl(0x7f000001);
  }

  /*
   * Create RPC endpoint
   */
  tv.tv_sec = 5;		/* 5 seconds for timeout or per retry */
  tv.tv_usec = 0;

  if (use_tcp_flag)	/* try tcp first */
    clnt = clnt_create(server, amd_program_number, AMQ_VERSION, "tcp");
  if (!clnt && use_udp_flag) {	/* try udp next */
    clnt = clnt_create(server, amd_program_number, AMQ_VERSION, "udp");
    /* if ok, set timeout (valid for connectionless transports only) */
    if (clnt)
      clnt_control(clnt, CLSET_RETRY_TIMEOUT, (char *) &tv);
  }
  if (!clnt) {
    fprintf(stderr, "%s: ", am_get_progname());
    clnt_pcreateerror(server);
    exit(1);
  }

  /*
   * Control debugging
   */
  if (debug_opts) {
    int *rc;
    amq_setopt opt;
    opt.as_opt = AMOPT_DEBUG;
    opt.as_str = debug_opts;
    rc = amqproc_setopt_1(&opt, clnt);
    if (rc && *rc < 0) {
      fprintf(stderr, "%s: daemon not compiled for debug\n",
	      am_get_progname());
      errs = 1;
    } else if (!rc || *rc > 0) {
      fprintf(stderr, "%s: debug setting for \"%s\" failed\n",
	      am_get_progname(), debug_opts);
      errs = 1;
    }
  }

  /*
   * Control logging
   */
  if (xlog_optstr) {
    int *rc;
    amq_setopt opt;
    opt.as_opt = AMOPT_XLOG;
    opt.as_str = xlog_optstr;
    rc = amqproc_setopt_1(&opt, clnt);
    if (!rc || *rc) {
      fprintf(stderr, "%s: setting log level to \"%s\" failed\n",
	      am_get_progname(), xlog_optstr);
      errs = 1;
    }
  }

  /*
   * Control log file
   */
  if (amq_logfile) {
    int *rc;
    amq_setopt opt;
    opt.as_opt = AMOPT_LOGFILE;
    opt.as_str = amq_logfile;
    rc = amqproc_setopt_1(&opt, clnt);
    if (!rc || *rc) {
      fprintf(stderr, "%s: setting logfile to \"%s\" failed\n",
	      am_get_progname(), amq_logfile);
      errs = 1;
    }
  }

  /*
   * Flush map cache
   */
  if (flush_flag) {
    int *rc;
    amq_setopt opt;
    opt.as_opt = AMOPT_FLUSHMAPC;
    opt.as_str = "";
    rc = amqproc_setopt_1(&opt, clnt);
    if (!rc || *rc) {
      fprintf(stderr, "%s: amd on %s cannot flush the map cache\n",
	      am_get_progname(), server);
      errs = 1;
    }
  }

  /*
   * getpwd info
   */
  if (getpwd_flag) {
    char path[MAXPATHLEN+1];
    char *wd = getcwd(path, MAXPATHLEN+1);
    amq_mount_tree_list *mlp = amqproc_export_1((voidp) 0, clnt);
    amq_mount_tree_p mt;
    u_int i;
    int flag;

    if (!wd) {
      perror("getcwd");
      exit(1);
    }
    for (i = 0; mlp && i < mlp->amq_mount_tree_list_len; i++) {
      mt = mlp->amq_mount_tree_list_val[i];
      while (1) {
	flag = 0;
	show_pwd(mt, path, sizeof(path), &flag);
	if (!flag) {
	  printf("%s\n", path);
	  break;
	}
      }
    }
    exit(0);
  }

  /*
   * Mount info
   */
  if (minfo_flag) {
    int dummy;
    amq_mount_info_list *ml = amqproc_getmntfs_1(&dummy, clnt);
    if (ml) {
      int mwid = 0, dwid = 0, twid = 0;
      show_mi(ml, Calc, &mwid, &dwid, &twid);
      mwid++;
      dwid++;
      twid++;
      show_mi(ml, Full, &mwid, &dwid, &twid);

    } else {
      fprintf(stderr, "%s: amd on %s cannot provide mount info\n",
	      am_get_progname(), server);
    }
  }

  /*
   * Get Version
   */
  if (getvers_flag) {
    amq_string *spp = amqproc_getvers_1((voidp) 0, clnt);
    if (spp && *spp) {
      fputs(*spp, stdout);
      XFREE(*spp);
    } else {
      fprintf(stderr, "%s: failed to get version information\n",
	      am_get_progname());
      errs = 1;
    }
  }

  /*
   * Get PID of amd
   */
  if (getpid_flag) {
    int *ip = amqproc_getpid_1((voidp) 0, clnt);
    if (ip && *ip) {
      printf("%d\n", *ip);
    } else {
      fprintf(stderr, "%s: failed to get PID of amd\n", am_get_progname());
      errs = 1;
    }
  }

  /*
   * Apply required operation to all remaining arguments
   */
  if (optind < argc) {
    do {
      char *fs = argv[optind++];
      if (unmount_flag) {
	/*
	 * Unmount request
	 */
	amqproc_umnt_1(&fs, clnt);
      } else {
	/*
	 * Stats request
	 */
	amq_mount_tree_p *mtp = amqproc_mnttree_1(&fs, clnt);
	if (mtp) {
	  amq_mount_tree *mt = *mtp;
	  if (mt) {
	    int mwid = 0, dwid = 0, twid = 0;
	    show_mt(mt, Calc, &mwid, &dwid, &twid);
	    mwid++;
	    dwid++, twid++;
	    printf("%-*.*s Uid   Getattr Lookup RdDir   RdLnk   Statfs Mounted@\n",
		   dwid, dwid, "What");
	    show_mt(mt, Stats, &mwid, &dwid, &twid);
	  } else {
	    fprintf(stderr, "%s: %s not automounted\n", am_get_progname(), fs);
	  }
	  xdr_pri_free((XDRPROC_T_TYPE) xdr_amq_mount_tree_p, (caddr_t) mtp);
	} else {
	  fprintf(stderr, "%s: ", am_get_progname());
	  clnt_perror(clnt, server);
	  errs = 1;
	}
      }
    } while (optind < argc);

  } else if (unmount_flag) {
    goto show_usage;

  } else if (stats_flag) {
    amq_mount_stats *ms = amqproc_stats_1((voidp) 0, clnt);
    if (ms) {
      show_ms(ms);
    } else {
      fprintf(stderr, "%s: ", am_get_progname());
      clnt_perror(clnt, server);
      errs = 1;
    }

  } else if (!nodefault) {
    amq_mount_tree_list *mlp = amqproc_export_1((voidp) 0, clnt);
    if (mlp) {
      enum show_opt e = Calc;
      int mwid = 0, dwid = 0, pwid = 0;

      while (e != ShowDone) {
	u_int i;
	for (i = 0; i < mlp->amq_mount_tree_list_len; i++) {
	  show_mt(mlp->amq_mount_tree_list_val[i],
		  e, &mwid, &dwid, &pwid);
	}
	mwid++;
	dwid++, pwid++;
	if (e == Calc)
	  e = Short;
	else if (e == Short)
	  e = ShowDone;
      }

    } else {
      fprintf(stderr, "%s: ", am_get_progname());
      clnt_perror(clnt, server);
      errs = 1;
    }
  }
  exit(errs);
  return errs; /* should never reach here */
}
Exemple #3
0
/*
 * Change current logfile
 */
int
switch_to_logfile(char *logfile, int old_umask, int truncate_log)
{
  FILE *new_logfp = stderr;

  if (logfile) {
#ifdef HAVE_SYSLOG
    syslogging = 0;
#endif /* HAVE_SYSLOG */

    if (STREQ(logfile, "/dev/stderr"))
      new_logfp = stderr;
    else if (NSTREQ(logfile, "syslog", strlen("syslog"))) {

#ifdef HAVE_SYSLOG
      syslogging = 1;
      new_logfp = stderr;
      openlog(am_get_progname(),
	      LOG_PID
# ifdef LOG_NOWAIT
	      | LOG_NOWAIT
# endif /* LOG_NOWAIT */
# ifdef LOG_DAEMON
	      , get_syslog_facility(logfile)
# endif /* LOG_DAEMON */
	      );
#else /* not HAVE_SYSLOG */
      plog(XLOG_WARNING, "syslog option not supported, logging unchanged");
#endif /* not HAVE_SYSLOG */

    } else {			/* regular log file */
      (void) umask(old_umask);
      if (truncate_log)
	__IGNORE(truncate(logfile, 0));
      new_logfp = fopen(logfile, "a");
      umask(0);
    }
  }

  /*
   * If we couldn't open a new file, then continue using the old.
   */
  if (!new_logfp && logfile) {
    plog(XLOG_USER, "%s: Can't open logfile: %m", logfile);
    return 1;
  }

  /*
   * Close the previous file
   */
  if (logfp && logfp != stderr)
    (void) fclose(logfp);
  logfp = new_logfp;

  if (logfile)
    plog(XLOG_INFO, "switched to logfile \"%s\"", logfile);
  else
    plog(XLOG_INFO, "no logfile defined; using stderr");

  return 0;
}
Exemple #4
0
/*
 * Output the time of day and hostname to the logfile
 */
static void
show_time_host_and_name(int lvl)
{
  static time_t last_t = 0;
  static char *last_ctime = NULL;
  time_t t;
#if defined(HAVE_CLOCK_GETTIME) && defined(DEBUG)
  struct timespec ts;
#endif /* defined(HAVE_CLOCK_GETTIME) && defined(DEBUG) */
  char nsecs[11];		/* '.' + 9 digits + '\0' */
  char *sev;

  nsecs[0] = '\0';

#if defined(HAVE_CLOCK_GETTIME) && defined(DEBUG)
  /*
   * Some systems (AIX 4.3) seem to implement clock_gettime() as stub
   * returning ENOSYS.
   */
  if (clock_gettime(CLOCK_REALTIME, &ts) == 0) {
    t = ts.tv_sec;
    if (amuDebug(D_HRTIME))
      xsnprintf(nsecs, sizeof(nsecs), ".%09ld", ts.tv_nsec);
  }
  else
#endif /* defined(HAVE_CLOCK_GETTIME) && defined(DEBUG) */
    t = clocktime(NULL);

  if (t != last_t) {
    last_ctime = ctime(&t);
    last_t = t;
  }

  switch (lvl) {
  case XLOG_FATAL:
    sev = "fatal:";
    break;
  case XLOG_ERROR:
    sev = "error:";
    break;
  case XLOG_USER:
    sev = "user: "******"warn: ";
    break;
  case XLOG_INFO:
    sev = "info: ";
    break;
  case XLOG_DEBUG:
    sev = "debug:";
    break;
  case XLOG_MAP:
    sev = "map:  ";
    break;
  case XLOG_STATS:
    sev = "stats:";
    break;
  default:
    sev = "hmm:  ";
    break;
  }
  fprintf(logfp, "%15.15s%s %s %s[%ld]/%s ",
	  last_ctime + 4, nsecs, am_get_hostname(),
	  am_get_progname(),
	  (long) am_mypid,
	  sev);
}
Exemple #5
0
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++;
    }

  /* set some default debugging options */
  if (xlog_level_init == ~0)
    switch_option("");
  /* 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);

#if defined(DEBUG) && !defined(MOUNT_TABLE_ON_FILE)
  if (debug_flags & D_MTAB)
    dlog("-D mtab option ignored");
#endif /* defined(DEBUG) && !defined(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);
  }

  clock_valid = 0;		/* invalidate logging clock */

  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 */

#ifdef DEBUG
  /*
   * In the parent, if -D nodaemon (or -D daemon) , we don't need to
   * set this signal handler.
   */
  amuDebug(D_DAEMON) {
#endif /* DEBUG */
    /* XXX: port to use pure svr4 signals */
    s = -99;
    while (stoplight != SIGUSR2) {
      plog(XLOG_INFO, "parent waits for child to setup (stoplight=%d)", stoplight);
      s = sigpause(0);		/* wait for child to set up */
      sleep(1);
    }
#ifdef DEBUG
  }
#endif /* DEBUG */

  /*
   * setup options to mount table (/etc/{mtab,mnttab}) entry
   */
  sprintf(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 {
    strcpy(preopts, default_mntopts);
    /*
     * 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
    strcat(preopts, ",");
    strcat(preopts, MNTTAB_OPT_INTR);
#endif /* MNTTAB_OPT_INTR */
#ifdef MNTTAB_OPT_IGNORE
    strcat(preopts, ",");
    strcat(preopts, MNTTAB_OPT_IGNORE);
#endif /* MNTTAB_OPT_IGNORE */
#ifdef MNT2_GEN_OPT_CACHE
    strcat(preopts, ",nocache");
#endif /* MNT2_GEN_OPT_CACHE */
#ifdef MNT2_NFS_OPT_SYMTTL
    strcat(preopts, ",symttl=0");
#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);
  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
   */
  sprintf(progpid_fs, "%s:%d", am_get_progname(), masterpid);

  /* Most kernels have a name length restriction. */
  if ((int) strlen(progpid_fs) >= (int) MAXHOSTNAMELEN)
    strcpy(progpid_fs + MAXHOSTNAMELEN - 3, "..");

  genflags = compute_mount_flags(&mnt);

  retry = hasmntval(&mnt, MNTTAB_OPT_RETRY);
  if (retry <= 0)
    retry = 1;			/* XXX */

  memmove(&anh.v2.fhs_fh, 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);

  clock_valid = 0;		/* invalidate logging clock */

/*
 * The following code could be cleverly ifdef-ed, but I duplicated the
 * mount_fs call three times for simplicity and readability.
 */
#ifdef DEBUG
/*
 * For some reason, this mount may have to be done in the background, if I am
 * using -D nodebug.  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 nodaemon, 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.
 */
  amuDebug(D_DAEMON) {	/* asked for -D daemon */
    plog(XLOG_INFO, "parent NFS mounting hlfsd service points");
    if (mount_fs2(&mnt, dir_name, genflags, (caddr_t) &nfs_args, retry, type, 0, NULL, mnttab_file_name) < 0)
      fatal("nfsmount: %m");
  } else {			/* asked for -D nodaemon */
    if (fork() == 0) {		/* child runs mount */
Exemple #6
0
void
get_args(int argc, char *argv[])
{
    int opt_ch;
    FILE *fp = stdin;
    char getopt_arguments[] = "+nprvSa:c:d:k:l:o:t:w:x:y:C:D:F:T:O:HA:";
    char *getopt_args;

#ifdef HAVE_GNU_GETOPT
    getopt_args = getopt_arguments;
#else /* ! HAVE_GNU_GETOPT */
    getopt_args = &getopt_arguments[1];
#endif /* HAVE_GNU_GETOPT */

    /* if no arguments were passed, try to use /etc/amd.conf file */
    if (argc <= 1)
        use_conf_file = 1;

    while ((opt_ch = getopt(argc, argv, getopt_args)) != -1)
        switch (opt_ch) {

        case 'a':
            if (*optarg != '/') {
                fprintf(stderr, "%s: -a option must begin with a '/'\n",
                        am_get_progname());
                exit(1);
            }
            gopt.auto_dir = optarg;
            break;

        case 'c':
            gopt.am_timeo = atoi(optarg);
            if (gopt.am_timeo <= 0)
                gopt.am_timeo = AM_TTL;
            break;

        case 'd':
            gopt.sub_domain = optarg;
            break;

        case 'k':
            gopt.karch = optarg;
            break;

        case 'l':
            gopt.logfile = optarg;
            break;

        case 'n':
            gopt.flags |= CFM_NORMALIZE_HOSTNAMES;
            break;

        case 'o':
            gopt.op_sys_ver = optarg;
            break;

        case 'p':
            gopt.flags |= CFM_PRINT_PID;
            break;

        case 'r':
            gopt.flags |= CFM_RESTART_EXISTING_MOUNTS;
            break;

        case 't':
            /* timeo.retrans */
        {
            char *dot = strchr(optarg, '.');
            if (dot)
                *dot = '\0';
            if (*optarg) {
                gopt.amfs_auto_timeo = atoi(optarg);
            }
            if (dot) {
                gopt.amfs_auto_retrans = atoi(dot + 1);
                *dot = '.';
            }
        }
        break;

        case 'v':
            fputs(get_version_string(), stderr);
            exit(0);
            break;

        case 'w':
            gopt.am_timeo_w = atoi(optarg);
            if (gopt.am_timeo_w <= 0)
                gopt.am_timeo_w = AM_TTL_W;
            break;

        case 'x':
            usage += switch_option(optarg);
            break;

        case 'y':
#ifdef HAVE_MAP_NIS
            gopt.nis_domain = optarg;
#else /* not HAVE_MAP_NIS */
            plog(XLOG_USER, "-y: option ignored.  No NIS support available.");
#endif /* not HAVE_MAP_NIS */
            break;

        case 'A':
            gopt.arch = optarg;
            break;

        case 'C':
            gopt.cluster = optarg;
            break;

        case 'D':
#ifdef DEBUG
            usage += debug_option(optarg);
#else /* not DEBUG */
            fprintf(stderr, "%s: not compiled with DEBUG option -- sorry.\n",
                    am_get_progname());
#endif /* not DEBUG */
            break;

        case 'F':
            conf_file = optarg;
            use_conf_file = 1;
            break;

        case 'H':
            goto show_usage;
            break;

        case 'O':
            gopt.op_sys = optarg;
            break;

        case 'S':
            gopt.flags &= ~CFM_PROCESS_LOCK; /* turn process locking off */
            break;

        case 'T':
            conf_tag = optarg;
            break;

        default:
            usage = 1;
            break;
        }

    /*
     * amd.conf file: if not command-line arguments were used, or if -F was
     * specified, then use that amd.conf file.  If the file cannot be opened,
     * abort amd.  If it can be found, open it, parse it, and then close it.
     */
    if (use_conf_file && conf_file) {
        fp = fopen(conf_file, "r");
        if (!fp) {
            char buf[128];
            sprintf(buf, "Amd configuration file (%s)", conf_file);
            perror(buf);
            exit(1);
        }
        yyin = fp;
        yyparse();
        fclose(fp);
        if (process_last_regular_map() != 0)
            exit(1);
    }

    /* make sure there are some default options defined */
    if (xlog_level_init == ~0) {
        switch_option("");
    }
#ifdef DEBUG
    usage += switch_option("debug");
#endif /* DEBUG */

    /* log information regarding amd.conf file */
    if (use_conf_file && conf_file)
        plog(XLOG_INFO, "using configuration file %s", conf_file);

#ifdef HAVE_MAP_LDAP
    /* ensure that if ldap_base is specified, that also ldap_hostports is */
    if (gopt.ldap_hostports && !gopt.ldap_base) {
        fprintf(stderr, "must specify both ldap_hostports and ldap_base\n");
        exit(1);
    }
#endif /* HAVE_MAP_LDAP */

    if (usage)
        goto show_usage;

    while (optind <= argc - 2) {
        char *dir = argv[optind++];
        char *map = argv[optind++];
        char *opts = "";
        if (argv[optind] && *argv[optind] == '-')
            opts = &argv[optind++][1];

        root_newmap(dir, opts, map, NULL);
    }

    if (optind == argc) {
        /*
         * Append domain name to hostname.
         * sub_domain overrides hostdomain
         * if given.
         */
        if (gopt.sub_domain)
            hostdomain = gopt.sub_domain;
        if (*hostdomain == '.')
            hostdomain++;
        strcat(hostd, ".");
        strcat(hostd, hostdomain);

#ifdef MOUNT_TABLE_ON_FILE
#ifdef DEBUG
        amuDebug(D_MTAB)
        mnttab_file_name = DEBUG_MNTTAB;
        else
#endif /* DEBUG */
            mnttab_file_name = MNTTAB_FILE_NAME;
#else /* not MOUNT_TABLE_ON_FILE */
        amuDebug(D_MTAB)
        dlog("-D mtab option ignored");
# ifdef MNTTAB_FILE_NAME
        mnttab_file_name = MNTTAB_FILE_NAME;
# endif /* MNTTAB_FILE_NAME */
#endif /* not MOUNT_TABLE_ON_FILE */

        if (switch_to_logfile(gopt.logfile, orig_umask) != 0)
            plog(XLOG_USER, "Cannot switch logfile");

        /*
         * If the kernel architecture was not specified
         * then use the machine architecture.
         */
        if (gopt.karch == 0)
            gopt.karch = gopt.arch;

        if (gopt.cluster == 0)
            gopt.cluster = hostdomain;

        if (gopt.amfs_auto_timeo <= 0)
            gopt.amfs_auto_timeo = AMFS_AUTO_TIMEO;
        if (gopt.amfs_auto_retrans <= 0)
            gopt.amfs_auto_retrans = AMFS_AUTO_RETRANS;
        if (gopt.amfs_auto_retrans <= 0)
            gopt.amfs_auto_retrans = 3;	/* XXX */
        return;
    }