text: /* This file contains the main message loop of the HGFS file system server.
   *
   * The entry points into this file are:
   *   main		main program function
   *
   * Created:
   *   April 2009 (D.C. van Moolenbroek)
   */
  
  #include "inc.h"
  
  #include "optset.h"
  
  #include <signal.h>
  #include <unistd.h>
  #include <stdlib.h>
  
  FORWARD _PROTOTYPE( int get_work, (endpoint_t *who_e)			);
  FORWARD _PROTOTYPE( void send_reply, (int err)				);
  
  PRIVATE struct optset optset_table[] = {
    { "prefix",   OPT_STRING, opt.prefix,       sizeof(opt.prefix) },
    { "uid",      OPT_INT,    &opt.uid,         10                 },
    { "gid",      OPT_INT,    &opt.gid,         10                 },
    { "fmask",    OPT_INT,    &opt.file_mask,   8                  },
    { "dmask",    OPT_INT,    &opt.dir_mask,    8                  },
    { "icase",    OPT_BOOL,   &opt.case_insens, TRUE               },
    { "noicase",  OPT_BOOL,   &opt.case_insens, FALSE              },
    { NULL                                                         }
  };
  
  /* SEF functions and variables. */
  FORWARD _PROTOTYPE( void sef_local_startup, (void) );
  FORWARD _PROTOTYPE( int sef_cb_init_fresh, (int type, sef_init_info_t *info) );
  FORWARD _PROTOTYPE( void sef_cb_signal_handler, (int signo) );
  EXTERN int env_argc;
  EXTERN char **env_argv;
  
  /*===========================================================================*
   *			      sef_cb_init_fresh				     *
   *===========================================================================*/
  PRIVATE int sef_cb_init_fresh(type, info)
  int type;
  sef_init_info_t *info;
  {
  /* Initialize this file server. Called at startup time.
   */
    message m;
    int i, r;
  
    /* Defaults */
    opt.prefix[0] = 0;
    opt.uid = 0;
    opt.gid = 0;
    opt.file_mask = 0755;
    opt.dir_mask = 0755;
    opt.case_insens = FALSE;
  
    /* If we have been given an options string, parse options from there. */
    for (i = 1; i < env_argc - 1; i++)
  	if (!strcmp(env_argv[i], "-o"))
  		optset_parse(optset_table, env_argv[++i]);
  
    /* Make sure that the given path prefix doesn't end with a slash. */
    for (i = strlen(opt.prefix); i > 0 && opt.prefix[i - 1] == '/'; i--);
    opt.prefix[i] = 0;
  
    /* Initialize the HGFS library. If this fails, exit immediately. */
    r = hgfs_init();
    if (r != OK && r != EAGAIN) {
  	printf("HGFS: unable to initialize HGFS library (%d)\n", r);
  
  	return r;
    }
  
    state.mounted = FALSE;
  
    /* Announce our presence to VFS. */
    m.m_type = FS_READY;
  
    if ((r = send(FS_PROC_NR, &m)) != OK) {
  	printf("HGFS: unable to login to VFS (%d)\n", r);
  
  	return r;
    }
  
    return OK;
  }
  
  /*===========================================================================*
   *		           sef_cb_signal_handler                             *
   *===========================================================================*/
  PRIVATE void sef_cb_signal_handler(int signo)
  {
    /* Only check for termination signal, ignore anything else. */
    if (signo != SIGTERM) return;
  
    if (state.mounted) {
        dprintf(("HGFS: got SIGTERM, still mounted\n"));
    }
    else {
        dprintf(("HGFS: got SIGTERM, shutting down\n"));
  
        /* Pass on the cleanup request to the HGFS library. */
        hgfs_cleanup();
        exit(0);
    }
  }
  
  /*===========================================================================*
   *				sef_local_startup			     *
   *===========================================================================*/
  PRIVATE void sef_local_startup()
  {
    /* Register init callbacks. */
    sef_setcb_init_fresh(sef_cb_init_fresh);
    sef_setcb_init_restart(sef_cb_init_fresh);
  
    /* No live update support yet. */
  
    /* Register signal callbacks. */
    sef_setcb_signal_handler(sef_cb_signal_handler);
  
    sef_startup();
  }
  
  /*===========================================================================*
   *				main					     *
   *===========================================================================*/
  PUBLIC int main(argc, argv)
  int argc;
  char *argv[];
  {
  /* The main function of this file server. After initializing, loop forever
   * receiving one request from VFS at a time, processing it, and sending a
   * reply back to VFS.
   */
    endpoint_t who_e;
    int call_nr, err;
  
    env_setargs(argc, argv);
    sef_local_startup();
  
    for (;;) {
  	call_nr = get_work(&who_e);
  
  	if (who_e != FS_PROC_NR) {
  		continue;
  	}
  
  	if (state.mounted || call_nr == REQ_READSUPER) {
  		call_nr -= VFS_BASE;
  
  		dprintf(("HGFS: call %d\n", call_nr));
  
  		if (call_nr >= 0 && call_nr < NREQS) {
  			err = (*call_vec[call_nr])();
  		} else {
  			err = ENOSYS;
  		}
  
  		dprintf(("HGFS: call %d result %d\n", call_nr, err));
  	}
  	else err = EINVAL;
  
  	send_reply(err);
    }
  
    return 0;
  }
  
  /*===========================================================================*
   *				get_work				     *
   *===========================================================================*/
  PRIVATE int get_work(who_e)
  endpoint_t *who_e;
  {
  /* Receive a request message from VFS. Return the request call number.
   */
    int r;
  
    if ((r = sef_receive(ANY, &m_in)) != OK)
  	panic("receive failed: %d", r);
  
    *who_e = m_in.m_source;
  
    return m_in.m_type;
  }
  
  /*===========================================================================*
   *				send_reply				     *
   *===========================================================================*/
  PRIVATE void send_reply(err)
  int err;				/* resulting error code */
  {
  /* Send a reply message to the requesting party, with the given error code.
   */
    int r;
  
    m_out.m_type = err;
  
    if ((r = send(m_in.m_source, &m_out)) != OK)
  	printf("HGFS: send failed (%d)\n", r);
  }
  
  