2 * Copyright (C) 1995, 1997-1999 Jeffrey A. Uphoff
3 * Modified by Olaf Kirch, Oct. 1996.
4 * Modified by H.J. Lu, 1998.
5 * Modified by L. Hohberger of Mission Critical Linux, 2000.
18 #include <rpc/pmap_clnt.h>
23 /* Socket operations */
24 #include <sys/types.h>
25 #include <sys/socket.h>
27 /* Added to enable specification of state directory path at run-time
28 * j_carlos_gomez@yahoo.com
31 char * DIR_BASE = DEFAULT_DIR_BASE;
33 char * SM_DIR = DEFAULT_SM_DIR;
34 char * SM_BAK_DIR = DEFAULT_SM_BAK_DIR;
35 char * SM_STAT_PATH = DEFAULT_SM_STAT_PATH;
37 /* ----- end of state directory path stuff ------- */
39 short int restart = 0;
40 int run_mode = 0; /* foreground logging mode */
42 /* LH - I had these local to main, but it seemed silly to have
43 * two copies of each - one in main(), one static in log.c...
44 * It also eliminates the 256-char static in log.c */
46 char *version_p = NULL;
48 static struct option longopts[] =
50 { "foreground", 0, 0, 'F' },
51 { "no-syslog", 0, 0, 'd' },
52 { "help", 0, 0, 'h' },
53 { "version", 0, 0, 'v' },
54 { "outgoing-port", 1, 0, 'o' },
55 { "port", 1, 0, 'p' },
56 { "name", 1, 0, 'n' },
57 { "state-directory-path", 1, 0, 'P' },
58 { "notify-mode", 0, 0, 'N' },
62 extern void sm_prog_1 (struct svc_req *, register SVCXPRT *);
63 extern int statd_get_socket(int port);
66 extern void simulator (int, char **);
70 #ifdef HAVE_TCP_WRAPPER
71 #include "tcpwrapper.h"
74 sm_prog_1_wrapper (struct svc_req *rqstp, register SVCXPRT *transp)
76 /* remote host authorization check */
77 if (!check_default("statd", svc_getcaller(transp),
78 rqstp->rq_proc, SM_PROG)) {
79 svcerr_auth (transp, AUTH_FAILED);
83 sm_prog_1 (rqstp, transp);
86 #define sm_prog_1 sm_prog_1_wrapper
95 log (L_FATAL, "Caught signal %d, un-registering and exiting.", sig);
96 pmap_unset (SM_PROG, SM_VERS);
101 * Startup information.
103 static void log_modes(void)
105 char buf[128]; /* watch stack size... */
107 /* No flags = no message */
108 if (!run_mode) return;
111 sprintf(buf,"Flags: ");
112 if (run_mode & MODE_NODAEMON)
113 strcat(buf,"No-Daemon ");
114 if (run_mode & MODE_LOG_STDERR)
115 strcat(buf,"Log-STDERR ");
117 if (run_mode & MODE_NOTIFY_ONLY)
119 strcat(buf,"Notify-Only ");
122 /* future: IP aliasing
123 if (run_mode & MODE_NOTIFY_ONLY)
125 dprintf(L_DEBUG,"Notify IP: %s",svr_addr);
130 * Since we do more than standard statd stuff, we might need to
131 * help the occasional admin.
136 fprintf(stderr,"usage: %s [options]\n", name_p);
137 fprintf(stderr," -h, -?, --help Print this help screen.\n");
138 fprintf(stderr," -F, --foreground Foreground (no-daemon mode)\n");
139 fprintf(stderr," -d, --no-syslog Verbose logging to stderr. Foreground mode only.\n");
140 fprintf(stderr," -p, --port Port to listen on\n");
141 fprintf(stderr," -o, --outgoing-port Port for outgoing connections\n");
142 fprintf(stderr," -V, -v, --version Display version information and exit.\n");
143 fprintf(stderr," -n, --name Specify a local hostname.\n");
144 fprintf(stderr," -P State directory path.\n");
145 fprintf(stderr," -N Run in notify only mode.\n");
149 * Entry routine/main loop.
151 int main (int argc, char **argv)
156 int port = 0, out_port = 0;
158 /* Default: daemon mode, no other options */
161 /* Set the basename */
162 if ((name_p = strrchr(argv[0],'/')) != NULL) {
168 /* Get the version */
169 if ((version_p = strrchr(VERSION,' ')) != NULL) {
178 /* Process command line switches */
179 while ((arg = getopt_long(argc, argv, "h?vVFNdn:p:o:P:", longopts, NULL)) != EOF) {
181 case 'V': /* Version */
183 printf("%s version %s\n",name_p,version_p);
185 case 'F': /* Foreground/nodaemon mode */
186 run_mode |= MODE_NODAEMON;
189 run_mode |= MODE_NOTIFY_ONLY;
191 case 'd': /* No daemon only - log to stderr */
192 run_mode |= MODE_LOG_STDERR;
195 out_port = atoi(optarg);
196 if (out_port < 1 || out_port > 65535) {
197 fprintf(stderr, "%s: bad port number: %s\n",
205 if (port < 1 || port > 65535) {
206 fprintf(stderr, "%s: bad port number: %s\n",
212 case 'n': /* Specify local hostname */
213 MY_NAME = xstrdup(optarg);
217 if ((DIR_BASE = xstrdup(optarg)) == NULL) {
218 fprintf(stderr, "%s: xstrdup(%s) failed!\n",
223 SM_DIR = xmalloc(strlen(DIR_BASE) + 1 + sizeof("sm"));
224 SM_BAK_DIR = xmalloc(strlen(DIR_BASE) + 1 + sizeof("sm.bak"));
225 SM_STAT_PATH = xmalloc(strlen(DIR_BASE) + 1 + sizeof("state"));
228 || (SM_BAK_DIR == NULL)
229 || (SM_STAT_PATH == NULL)) {
231 fprintf(stderr, "%s: xmalloc() failed!\n",
235 if (DIR_BASE[strlen(DIR_BASE)-1] == '/') {
236 sprintf(SM_DIR, "%ssm", DIR_BASE );
237 sprintf(SM_BAK_DIR, "%ssm.bak", DIR_BASE );
238 sprintf(SM_STAT_PATH, "%sstate", DIR_BASE );
240 sprintf(SM_DIR, "%s/sm", DIR_BASE );
241 sprintf(SM_BAK_DIR, "%s/sm.bak", DIR_BASE );
242 sprintf(SM_STAT_PATH, "%s/state", DIR_BASE );
245 case '?': /* heeeeeelllllllpppp? heh */
249 default: /* oh dear ... heh */
255 if (port == out_port && port != 0) {
256 fprintf(stderr, "Listening and outgoing ports cannot be the same!\n");
260 if (!(run_mode & MODE_NODAEMON)) {
261 run_mode &= ~MODE_LOG_STDERR; /* Never log to console in
265 log_init (name_p,version_p);
271 /* LH - I _really_ need to update simulator... */
272 simulator (--argc, ++argv); /* simulator() does exit() */
275 if (!(run_mode & MODE_NODAEMON)) {
276 int filedes, fdmax, tempfd;
278 if ((pid = fork ()) < 0) {
279 perror ("Could not fork");
281 } else if (pid != 0) {
289 tempfd = open("/dev/null", O_RDWR);
290 close(0); dup2(tempfd, 0);
291 close(1); dup2(tempfd, 1);
292 close(2); dup2(tempfd, 2);
293 fdmax = sysconf (_SC_OPEN_MAX);
294 for (filedes = 3; filedes < fdmax; filedes++) {
300 signal (SIGHUP, killer);
301 signal (SIGINT, killer);
302 signal (SIGTERM, killer);
303 /* WARNING: the following works on Linux and SysV, but not BSD! */
304 signal(SIGCHLD, SIG_IGN);
306 /* initialize out_port */
307 statd_get_socket(out_port);
310 pmap_unset (SM_PROG, SM_VERS);
312 shuffle_dirs (); /* Move directory names around */
313 notify_hosts (); /* Send out notify requests */
316 /* this registers both UDP and TCP services */
317 if (!(run_mode & MODE_NOTIFY_ONLY)) {
318 rpc_init("statd", SM_PROG, SM_VERS, sm_prog_1, port);
322 * Handle incoming requests: SM_NOTIFY socket requests, as
323 * well as callbacks from lockd.
325 my_svc_run(); /* I rolled my own, Olaf made it better... */
327 if ((run_mode & MODE_NOTIFY_ONLY))