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

Revision 24319, 4.7 KB checked in by broder, 15 years ago (diff)
New Moira snapshot from SVN.
Line 
1/* $Id: update_server.c 3956 2010-01-05 20:56:56Z 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 3956 2010-01-05 20:56:56Z 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
69  whoami = strrchr(argv[0], '/');
70  if (whoami)
71    whoami++;
72  else
73    whoami = argv[0];
74
75  /* interpret arguments here */
76  if (argc != 1)
77    {
78      fprintf(stderr, "Usage:  %s\n", whoami);
79      exit(1);
80    }
81
82  if (!config_lookup("nofork"))
83    {
84      if (fork())
85        exit(0);
86      setsid();
87    }
88
89  uname(&name);
90  hostname = name.nodename;
91
92  umask(0022);
93  mr_init();
94
95  sigemptyset(&sa.sa_mask);
96  sa.sa_flags = SA_RESTART;
97  sa.sa_handler = child_handler;
98  sigaction(SIGCHLD, &sa, NULL);
99
100  /* If the config file contains a line "user username", the
101   * daemon will run with that user's UID.
102   */
103  if ((p = config_lookup("user")))
104    {
105      struct passwd *pw;
106      pw = getpwnam(p);
107      if (!pw)
108        {
109          com_err(whoami, errno, "Unable to find user %s\n", p);
110          exit(1);
111        }
112      uid = pw->pw_uid;
113    }
114
115  /* If the config file contains a line "port portname", the daemon
116   * will listen on the named port rather than SERVICE_NAME ("moira_update")
117   */
118  if (!(p = config_lookup("port")))
119    p = SERVICE_NAME;
120
121  s = mr_listen(p);
122  if (s == -1)
123    {
124      com_err(whoami, errno, "creating listening socket");
125      exit(1);
126    }
127
128  set_com_err_hook(syslog_com_err_proc);
129  openlog(whoami, LOG_PID, LOG_DAEMON);
130
131  /* now loop waiting for connections */
132  while (1)
133    {
134      struct sockaddr_in client;
135      long len;
136      char *buf;
137
138      conn = mr_accept(s, &client);
139      if (conn == -1)
140        {
141          com_err(whoami, errno, "accepting on listening socket");
142          exit(1);
143        }
144      else if (conn == 0)
145        continue;
146
147      if (config_lookup("nofork") || (fork() <= 0))
148        break;
149
150      close(conn);
151    }
152
153  /* If the config file contains a line "chroot /dir/name", the
154   * daemon will run chrooted to that directory.
155   */
156  if ((p = config_lookup("chroot")))
157    {
158      if (chroot(p) < 0)
159        {
160          com_err(whoami, errno, "unable to chroot to %s", p);
161          exit(1);
162        }
163    }
164
165  com_err(whoami, 0, "got connection");
166
167  while (1)
168    {
169      char *cp, *str;
170      size_t len;
171      int code;
172
173      code = recv_string(conn, &str, &len);
174      if (code)
175        {
176          com_err(whoami, code, "receiving command");
177          close(conn);
178          exit(1);
179        }
180
181      cp = strchr(str, ' ');
182      if (cp)
183        *cp = '\0';
184      for (d = dispatch_table; d->str; d++)
185        {
186          if (!strcmp(d->str, str))
187            {
188              if (cp)
189                *cp = ' ';
190              (d->proc)(conn, str);
191              goto ok;
192            }
193        }
194      com_err(whoami, 0, "unknown request received: %s", str);
195      code = send_int(conn, MR_UNKNOWN_PROC);
196      if (code)
197        com_err(whoami, code, "sending UNKNOWN_PROC");
198    ok:
199      free(str);
200    }
201}
202
203int send_ok(int conn)
204{
205  return send_int(conn, 0);
206}
207
208/*
209 * quit request:
210 *
211 * syntax:
212 * >>> quit
213 * <<< (int)0
214 * any arguments are ignored
215 *
216 * function:
217 *      closes connection from MR
218 */
219
220void quit(int conn, char *str)
221{
222  send_ok(conn);
223  close(conn);
224  com_err(whoami, 0, "Closing connection.");
225  exit(0);
226}
227
228void fail(int conn, int err, char *msg)
229{
230  com_err(whoami, err, msg);
231  close(conn);
232  exit(1);
233}
234
235void child_handler(int signal)
236{
237  int status;
238
239  while (waitpid(-1, &status, WNOHANG) > 0)
240    ;
241}
242
243static void syslog_com_err_proc(const char *progname, long code,
244                                const char *fmt, va_list args)
245{
246  char buf[BUFSIZ + 1];
247
248  buf[BUFSIZ] = '\0';
249
250  vsnprintf(buf, BUFSIZ, fmt, args);
251  syslog(LOG_NOTICE, "%s: %s %s", progname ? progname : "",
252         code ? error_message(code) : "", buf);
253}
Note: See TracBrowser for help on using the repository browser.