source: trunk/third/moira/update/update_server.c @ 26024

Revision 26024, 5.3 KB checked in by jdreed, 11 years ago (diff)
In moira: * Snapshot moira at r4113 to pick up new firewall-related changes
Line 
1/* $Id: update_server.c 4104 2013-04-08 20:35:44Z zacheiss $
2 *
3 * Copyright 1988-1998 by the Massachusetts Institute of Technology.
4 * For copying and distribution information, please see the file
5 * <mit-copyright.h>.
6 */
7
8#include <mit-copyright.h>
9#include <moira.h>
10#include "update_server.h"
11
12#include <sys/stat.h>
13#include <sys/utsname.h>
14#include <sys/wait.h>
15
16#include <netinet/in.h>
17#include <arpa/inet.h>
18
19#include <errno.h>
20#include <pwd.h>
21#include <signal.h>
22#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
25#include <unistd.h>
26#include <syslog.h>
27
28#ifdef HAVE_KRB4
29#include <des.h>
30#endif
31#include "update.h"
32
33RCSID("$HeadURL: svn+ssh://svn.mit.edu/moira/trunk/moira/update/update_server.c $ $Id: update_server.c 4104 2013-04-08 20:35:44Z zacheiss $");
34
35char *whoami, *hostname;
36
37int have_authorization = 0;
38#ifdef HAVE_KRB4
39des_cblock session;
40#endif
41int uid = 0;
42
43void child_handler(int signal);
44static void syslog_com_err_proc(const char *progname, long code,
45                                const char *fmt, va_list args);
46
47struct _dt {
48  char *str;
49  void (*proc)(int, char *);
50} dispatch_table[] = {
51  { "AUTH_002", auth_002 },
52  { "AUTH_003", auth_003 },
53  { "XFER_002", xfer_002 },
54  { "XFER_003", xfer_003 },
55  { "EXEC_002", exec_002 },
56  { "quit", quit },
57  { NULL, (void (*)(int, char *))abort }
58};
59
60int main(int argc, char **argv)
61{
62  char *str, *p;
63  size_t len;
64  struct _dt *d;
65  struct utsname name;
66  int s, conn;
67  struct sigaction sa;
68  FILE *pid_file;
69  char *pid_path = NULL;
70
71  whoami = strrchr(argv[0], '/');
72  if (whoami)
73    whoami++;
74  else
75    whoami = argv[0];
76
77  /* interpret arguments here */
78  if (argc != 1)
79    {
80      fprintf(stderr, "Usage:  %s\n", whoami);
81      exit(1);
82    }
83
84  if (!config_lookup("nofork"))
85    {
86      if (fork())
87        exit(0);
88      setsid();
89    }
90
91  uname(&name);
92  hostname = name.nodename;
93
94  umask(0022);
95  mr_init();
96
97  sigemptyset(&sa.sa_mask);
98  sa.sa_flags = SA_RESTART;
99  sa.sa_handler = child_handler;
100  sigaction(SIGCHLD, &sa, NULL);
101
102  /* If the config file contains a line "user username", the
103   * daemon will run with that user's UID.
104   */
105  if ((p = config_lookup("user")))
106    {
107      struct passwd *pw;
108      pw = getpwnam(p);
109      if (!pw)
110        {
111          com_err(whoami, errno, "Unable to find user %s\n", p);
112          exit(1);
113        }
114      uid = pw->pw_uid;
115    }
116
117  /* If the config file contains a line "port portname", the daemon
118   * will listen on the named port rather than SERVICE_NAME ("moira_update")
119   */
120  if (!(p = config_lookup("port")))
121    p = SERVICE_NAME;
122
123  s = mr_listen(p);
124  if (s == -1)
125    {
126      com_err(whoami, errno, "creating listening socket");
127      exit(1);
128    }
129
130  set_com_err_hook(syslog_com_err_proc);
131  openlog(whoami, LOG_PID, LOG_DAEMON);
132
133  if ((pid_path = malloc(strlen(PIDFILEPATH) + strlen(whoami) + 6)) != NULL)
134    {
135      sprintf(pid_path, "%s/%s.pid", PIDFILEPATH, whoami);
136      pid_file = fopen(pid_path, "w");
137      if (pid_file)
138        {
139          fprintf(pid_file, "%d\n", getpid ());
140          fclose(pid_file);
141        }
142      else
143        {
144          com_err(whoami, errno, "Unable to write PID file %s", pid_path);
145          exit(1);
146        }
147      free(pid_path);
148    }
149  else
150    {
151      com_err(whoami, errno, "Could not allocate memory for pidfile path");
152      exit(1);
153    }
154
155  /* now loop waiting for connections */
156  while (1)
157    {
158      struct sockaddr_in client;
159      long len;
160      char *buf;
161
162      conn = mr_accept(s, &client);
163      if (conn == -1)
164        {
165          com_err(whoami, errno, "accepting on listening socket");
166          exit(1);
167        }
168      else if (conn == 0)
169        continue;
170
171      if (config_lookup("nofork") || (fork() <= 0))
172        break;
173
174      close(conn);
175    }
176
177  /* If the config file contains a line "chroot /dir/name", the
178   * daemon will run chrooted to that directory.
179   */
180  if ((p = config_lookup("chroot")))
181    {
182      if (chroot(p) < 0)
183        {
184          com_err(whoami, errno, "unable to chroot to %s", p);
185          exit(1);
186        }
187    }
188
189  com_err(whoami, 0, "got connection");
190
191  while (1)
192    {
193      char *cp, *str;
194      size_t len;
195      int code;
196
197      code = recv_string(conn, &str, &len);
198      if (code)
199        {
200          com_err(whoami, code, "receiving command");
201          close(conn);
202          exit(1);
203        }
204
205      cp = strchr(str, ' ');
206      if (cp)
207        *cp = '\0';
208      for (d = dispatch_table; d->str; d++)
209        {
210          if (!strcmp(d->str, str))
211            {
212              if (cp)
213                *cp = ' ';
214              (d->proc)(conn, str);
215              goto ok;
216            }
217        }
218      com_err(whoami, 0, "unknown request received: %s", str);
219      code = send_int(conn, MR_UNKNOWN_PROC);
220      if (code)
221        com_err(whoami, code, "sending UNKNOWN_PROC");
222    ok:
223      free(str);
224    }
225}
226
227int send_ok(int conn)
228{
229  return send_int(conn, 0);
230}
231
232/*
233 * quit request:
234 *
235 * syntax:
236 * >>> quit
237 * <<< (int)0
238 * any arguments are ignored
239 *
240 * function:
241 *      closes connection from MR
242 */
243
244void quit(int conn, char *str)
245{
246  send_ok(conn);
247  close(conn);
248  com_err(whoami, 0, "Closing connection.");
249  exit(0);
250}
251
252void fail(int conn, int err, char *msg)
253{
254  com_err(whoami, err, "%s", msg);
255  close(conn);
256  exit(1);
257}
258
259void child_handler(int signal)
260{
261  int status;
262
263  while (waitpid(-1, &status, WNOHANG) > 0)
264    ;
265}
266
267static void syslog_com_err_proc(const char *progname, long code,
268                                const char *fmt, va_list args)
269{
270  char buf[BUFSIZ + 1];
271
272  buf[BUFSIZ] = '\0';
273
274  vsnprintf(buf, BUFSIZ, fmt, args);
275  syslog(LOG_NOTICE, "%s: %s %s", progname ? progname : "",
276         code ? error_message(code) : "", buf);
277}
Note: See TracBrowser for help on using the repository browser.