]> andersk Git - moira.git/blob - update/update_server.c
985700d15862902a288cda9473f9a437aa1bd6c4
[moira.git] / update / update_server.c
1 /* $Id$
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 #include <des.h>
29 #include "update.h"
30
31 RCSID("$Header$");
32
33 char *whoami, *hostname;
34
35 int have_authorization = 0;
36 des_cblock session;
37 int uid = 0;
38
39 void child_handler(int signal);
40 static void syslog_com_err_proc(const char *progname, long code,
41                                 const char *fmt, va_list args);
42
43 struct _dt {
44   char *str;
45   void (*proc)(int, char *);
46 } dispatch_table[] = {
47   { "AUTH_002", auth_002 },
48   { "AUTH_003", auth_003 },
49   { "XFER_002", xfer_002 },
50   { "XFER_003", xfer_003 },
51   { "EXEC_002", exec_002 },
52   { "quit", quit },
53   { NULL, (void (*)(int, char *))abort }
54 };
55
56 int main(int argc, char **argv)
57 {
58   char *str, *p;
59   size_t len;
60   struct _dt *d;
61   struct utsname name;
62   int s, conn;
63   struct sigaction sa;
64
65   whoami = strrchr(argv[0], '/');
66   if (whoami)
67     whoami++;
68   else
69     whoami = argv[0];
70
71   /* interpret arguments here */
72   if (argc != 1)
73     {
74       fprintf(stderr, "Usage:  %s\n", whoami);
75       exit(1);
76     }
77
78   if (!config_lookup("nofork"))
79     {
80       if (fork())
81         exit(0);
82       setsid();
83     }
84
85   uname(&name);
86   hostname = name.nodename;
87
88   umask(0022);
89   mr_init();
90
91   sigemptyset(&sa.sa_mask);
92   sa.sa_flags = SA_RESTART;
93   sa.sa_handler = child_handler;
94   sigaction(SIGCHLD, &sa, NULL);
95
96   /* If the config file contains a line "user username", the
97    * daemon will run with that user's UID.
98    */
99   if ((p = config_lookup("user")))
100     {
101       struct passwd *pw;
102       pw = getpwnam(p);
103       if (!pw)
104         {
105           com_err(whoami, errno, "Unable to find user %s\n", p);
106           exit(1);
107         }
108       uid = pw->pw_uid;
109     }
110
111   /* If the config file contains a line "port portname", the daemon
112    * will listen on the named port rather than SERVICE_NAME ("moira_update")
113    */
114   if (!(p = config_lookup("port")))
115     p = SERVICE_NAME;
116
117   s = mr_listen(p);
118   if (s == -1)
119     {
120       com_err(whoami, errno, "creating listening socket");
121       exit(1);
122     }
123
124   set_com_err_hook(syslog_com_err_proc);
125   openlog(whoami, LOG_PID, LOG_DAEMON);
126
127   /* now loop waiting for connections */
128   while (1)
129     {
130       struct sockaddr_in client;
131       long len;
132       char *buf;
133
134       conn = mr_accept(s, &client);
135       if (conn == -1)
136         {
137           com_err(whoami, errno, "accepting on listening socket");
138           exit(1);
139         }
140       else if (conn == 0)
141         continue;
142
143       if (config_lookup("nofork") || (fork() <= 0))
144         break;
145
146       close(conn);
147     }
148
149   /* If the config file contains a line "chroot /dir/name", the
150    * daemon will run chrooted to that directory.
151    */
152   if ((p = config_lookup("chroot")))
153     {
154       if (chroot(p) < 0)
155         {
156           com_err(whoami, errno, "unable to chroot to %s", p);
157           exit(1);
158         }
159     }
160
161   com_err(whoami, 0, "got connection");
162
163   while (1)
164     {
165       char *cp, *str;
166       size_t len;
167       int code;
168
169       code = recv_string(conn, &str, &len);
170       if (code)
171         {
172           com_err(whoami, code, "receiving command");
173           close(conn);
174           exit(1);
175         }
176
177       cp = strchr(str, ' ');
178       if (cp)
179         *cp = '\0';
180       for (d = dispatch_table; d->str; d++)
181         {
182           if (!strcmp(d->str, str))
183             {
184               if (cp)
185                 *cp = ' ';
186               (d->proc)(conn, str);
187               goto ok;
188             }
189         }
190       com_err(whoami, 0, "unknown request received: %s", str);
191       code = send_int(conn, MR_UNKNOWN_PROC);
192       if (code)
193         com_err(whoami, code, "sending UNKNOWN_PROC");
194     ok:
195       free(str);
196     }
197 }
198
199 int send_ok(int conn)
200 {
201   return send_int(conn, 0);
202 }
203
204 /*
205  * quit request:
206  *
207  * syntax:
208  * >>> quit
209  * <<< (int)0
210  * any arguments are ignored
211  *
212  * function:
213  *      closes connection from MR
214  */
215
216 void quit(int conn, char *str)
217 {
218   send_ok(conn);
219   close(conn);
220   com_err(whoami, 0, "Closing connection.");
221   exit(0);
222 }
223
224 void fail(int conn, int err, char *msg)
225 {
226   com_err(whoami, err, msg);
227   close(conn);
228   exit(1);
229 }
230
231 void child_handler(int signal)
232 {
233   int status;
234
235   while (waitpid(-1, &status, WNOHANG) > 0)
236     ;
237 }
238
239 static void syslog_com_err_proc(const char *progname, long code,
240                                 const char *fmt, va_list args)
241 {
242   char buf[BUFSIZ + 1];
243
244   buf[BUFSIZ] = '\0';
245
246   vsnprintf(buf, BUFSIZ, fmt, args);
247   syslog(LOG_NOTICE, "%s: %s %s", progname ? progname : "",
248          code ? error_message(code) : "", buf);
249 }
This page took 0.056399 seconds and 3 git commands to generate.