summaryrefslogtreecommitdiffstats
path: root/utils/statd/statd.c
blob: 91cb3bc87005d07af1b67091e9906941eb6d8c25 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
/* 
 * Copyright (C) 1995, 1997-1999 Jeffrey A. Uphoff
 * Modified by Olaf Kirch, Oct. 1996.
 * Modified by H.J. Lu, 1998.
 *
 * NSM for Linux.
 */

#include "config.h"
#include <limits.h>
#include <signal.h>
#include <unistd.h>
#include <string.h>
#include <rpc/rpc.h>
#include <rpc/pmap_clnt.h>
#include "statd.h"
#include "version.h"

short int restart = 0;
int	_rpcpmstart = 0;	/* flags for tirpc rpcgen */
int	_rpcfdtype = 0;
int	_rpcsvcdirty = 0;

extern void sm_prog_1 (struct svc_req *, register SVCXPRT);

#ifdef SIMULATIONS
extern void simulator (int, char **);
#endif


/*
 * Signal handler.
 */
static void 
killer (int sig)
{
  log (L_FATAL, "Caught signal %d, un-registering and exiting.", sig);
  pmap_unset (SM_PROG, SM_VERS);
  exit (0);
}


/* 
 * Entry routine/main loop.
 */
int
main (int argc, char **argv)
{
  int pid;
  int foreground = 0;

  log_init (argv[0]);

  if (argc == 2 && strcmp (argv [1], "-F") == 0) {
    foreground = 1;
    argc--;
    argv++;
  }

#ifdef SIMULATIONS
  if (argc > 1)
    simulator (--argc, ++argv);	/* simulator() does exit() */
#endif
  
  if (!foreground) {
    int filedes;

    if ((pid = fork ()) < 0) {
      perror ("Could not fork");
      exit (1);
    } else if (pid != 0) {
      /* Parent. */
      exit (0);
    }
    /* Child.  */
    setsid ();
    chdir (DIR_BASE);

    for (filedes = 0; filedes < sysconf (_SC_OPEN_MAX); filedes++) {
      close (filedes);
    }
  }

  /* Child. */
  signal (SIGHUP, killer);
  signal (SIGINT, killer);
  signal (SIGTERM, killer);

  for (;;) {
    pmap_unset (SM_PROG, SM_VERS);
    change_state ();
    shuffle_dirs ();
    notify_hosts ();
    ++restart;
    do_regist (SM_PROG, sm_prog_1);
    my_svc_run ();		/* I rolled my own, Olaf made it better... */
  }
  return 0;
}


/*
 * Register services.
 */
void
do_regist(u_long prog, void (*sm_prog_1)())
/* do_regist(u_long prog, __dispatch_fn_t sm_prog_1) */
{
  SVCXPRT        *transp;

  if ((transp = svcudp_create(RPC_ANYSOCK)) == NULL)
    die("cannot create udp service.");

  if (!svc_register(transp, prog, SM_VERS, sm_prog_1, IPPROTO_UDP))
    die("unable to register (SM_PROG, SM_VERS, udp).");

  if ((transp = svctcp_create(RPC_ANYSOCK, 0, 0)) == NULL)
    die("cannot create tcp service.");

  if (!svc_register(transp, prog, SM_VERS, sm_prog_1, IPPROTO_TCP))
    die("unable to register (SM_PROG, SM_VERS, tcp).");
}