#include <limits.h>
#include <signal.h>
#include <unistd.h>
+#include <fcntl.h>
#include <string.h>
#include <getopt.h>
#include <rpc/rpc.h>
#include <sys/types.h>
#include <sys/socket.h>
+/* Added to enable specification of state directory path at run-time
+ * j_carlos_gomez@yahoo.com
+ */
+
+char * DIR_BASE = DEFAULT_DIR_BASE;
+
+char * SM_DIR = DEFAULT_SM_DIR;
+char * SM_BAK_DIR = DEFAULT_SM_BAK_DIR;
+char * SM_STAT_PATH = DEFAULT_SM_STAT_PATH;
+
+/* ----- end of state directory path stuff ------- */
short int restart = 0;
int run_mode = 0; /* foreground logging mode */
{ "version", 0, 0, 'v' },
{ "outgoing-port", 1, 0, 'o' },
{ "port", 1, 0, 'p' },
+ { "name", 1, 0, 'n' },
+ { "state-directory-path", 1, 0, 'P' },
+ { "notify-mode", 0, 0, 'N' },
{ NULL, 0, 0, 0 }
};
strcat(buf,"No-Daemon ");
if (run_mode & MODE_LOG_STDERR)
strcat(buf,"Log-STDERR ");
- /* future: IP aliasing
+
if (run_mode & MODE_NOTIFY_ONLY)
{
strcat(buf,"Notify-Only ");
- } */
+ }
log(L_WARNING,buf);
/* future: IP aliasing
if (run_mode & MODE_NOTIFY_ONLY)
fprintf(stderr," -p, --port Port to listen on\n");
fprintf(stderr," -o, --outgoing-port Port for outgoing connections\n");
fprintf(stderr," -V, -v, --version Display version information and exit.\n");
+ fprintf(stderr," -n, --name Specify a local hostname.\n");
+ fprintf(stderr," -P State directory path.\n");
+ fprintf(stderr," -N Run in notify only mode.\n");
}
/*
version_p = VERSION;
}
+ /* Set hostname */
+ MY_NAME = NULL;
+
/* Process command line switches */
- while ((arg = getopt_long(argc, argv, "h?vVFdp:o:", longopts, NULL)) != EOF) {
+ while ((arg = getopt_long(argc, argv, "h?vVFNdn:p:o:P:", longopts, NULL)) != EOF) {
switch (arg) {
case 'V': /* Version */
case 'v':
case 'F': /* Foreground/nodaemon mode */
run_mode |= MODE_NODAEMON;
break;
+ case 'N':
+ run_mode |= MODE_NOTIFY_ONLY;
+ break;
case 'd': /* No daemon only - log to stderr */
run_mode |= MODE_LOG_STDERR;
break;
exit(1);
}
break;
+ case 'n': /* Specify local hostname */
+ MY_NAME = xstrdup(optarg);
+ break;
+ case 'P':
+
+ if ((DIR_BASE = xstrdup(optarg)) == NULL) {
+ fprintf(stderr, "%s: xstrdup(%s) failed!\n",
+ argv[0], optarg);
+ exit(1);
+ }
+
+ SM_DIR = xmalloc(strlen(DIR_BASE) + 1 + sizeof("sm"));
+ SM_BAK_DIR = xmalloc(strlen(DIR_BASE) + 1 + sizeof("sm.bak"));
+ SM_STAT_PATH = xmalloc(strlen(DIR_BASE) + 1 + sizeof("state"));
+
+ if ((SM_DIR == NULL)
+ || (SM_BAK_DIR == NULL)
+ || (SM_STAT_PATH == NULL)) {
+
+ fprintf(stderr, "%s: xmalloc() failed!\n",
+ argv[0]);
+ exit(1);
+ }
+ if (DIR_BASE[strlen(DIR_BASE)-1] == '/') {
+ sprintf(SM_DIR, "%ssm", DIR_BASE );
+ sprintf(SM_BAK_DIR, "%ssm.bak", DIR_BASE );
+ sprintf(SM_STAT_PATH, "%sstate", DIR_BASE );
+ } else {
+ sprintf(SM_DIR, "%s/sm", DIR_BASE );
+ sprintf(SM_BAK_DIR, "%s/sm.bak", DIR_BASE );
+ sprintf(SM_STAT_PATH, "%s/state", DIR_BASE );
+ }
+ break;
case '?': /* heeeeeelllllllpppp? heh */
case 'h':
usage();
#endif
if (!(run_mode & MODE_NODAEMON)) {
- int filedes;
+ int filedes, fdmax, tempfd;
if ((pid = fork ()) < 0) {
perror ("Could not fork");
setsid ();
chdir (DIR_BASE);
- for (filedes = 0; filedes < sysconf (_SC_OPEN_MAX); filedes++) {
+ tempfd = open("/dev/null", O_RDWR);
+ close(0); dup2(tempfd, 0);
+ close(1); dup2(tempfd, 1);
+ close(2); dup2(tempfd, 2);
+ fdmax = sysconf (_SC_OPEN_MAX);
+ for (filedes = 3; filedes < fdmax; filedes++) {
close (filedes);
}
}
notify_hosts (); /* Send out notify requests */
++restart;
- /* future: IP aliasing
+ /* this registers both UDP and TCP services */
if (!(run_mode & MODE_NOTIFY_ONLY)) {
rpc_init("statd", SM_PROG, SM_VERS, sm_prog_1, port);
- } */
- /* this registers both UDP and TCP services */
- rpc_init("statd", SM_PROG, SM_VERS, sm_prog_1, port);
+ }
/*
* Handle incoming requests: SM_NOTIFY socket requests, as
* well as callbacks from lockd.
*/
my_svc_run(); /* I rolled my own, Olaf made it better... */
+
+ if ((run_mode & MODE_NOTIFY_ONLY))
+ break;
}
return 0;
}