]> andersk Git - moira.git/blob - update/update_server.c
6c5dc9a316c8bbf189499feda7efe85a472a644f
[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 #ifdef HAVE_KRB4
29 #include <des.h>
30 #endif
31 #include "update.h"
32
33 RCSID("$Header$");
34
35 char *whoami, *hostname;
36
37 int have_authorization = 0;
38 #ifdef HAVE_KRB4
39 des_cblock session;
40 #endif
41 int uid = 0;
42
43 void child_handler(int signal);
44 static void syslog_com_err_proc(const char *progname, long code,
45                                 const char *fmt, va_list args);
46
47 struct _dt {
48   char *str;
49   void (*proc)(int, char *);
50 } dispatch_table[] = {
51 #ifdef HAVE_KRB4
52   { "AUTH_002", auth_002 },
53 #endif
54   { "AUTH_003", auth_003 },
55   { "XFER_002", xfer_002 },
56   { "XFER_003", xfer_003 },
57   { "EXEC_002", exec_002 },
58   { "quit", quit },
59   { NULL, (void (*)(int, char *))abort }
60 };
61
62 int main(int argc, char **argv)
63 {
64   char *str, *p;
65   size_t len;
66   struct _dt *d;
67   struct utsname name;
68   int s, conn;
69   struct sigaction sa;
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   /* now loop waiting for connections */
134   while (1)
135     {
136       struct sockaddr_in client;
137       long len;
138       char *buf;
139
140       conn = mr_accept(s, &client);
141       if (conn == -1)
142         {
143           com_err(whoami, errno, "accepting on listening socket");
144           exit(1);
145         }
146       else if (conn == 0)
147         continue;
148
149       if (config_lookup("nofork") || (fork() <= 0))
150         break;
151
152       close(conn);
153     }
154
155   /* If the config file contains a line "chroot /dir/name", the
156    * daemon will run chrooted to that directory.
157    */
158   if ((p = config_lookup("chroot")))
159     {
160       if (chroot(p) < 0)
161         {
162           com_err(whoami, errno, "unable to chroot to %s", p);
163           exit(1);
164         }
165     }
166
167   com_err(whoami, 0, "got connection");
168
169   while (1)
170     {
171       char *cp, *str;
172       size_t len;
173       int code;
174
175       code = recv_string(conn, &str, &len);
176       if (code)
177         {
178           com_err(whoami, code, "receiving command");
179           close(conn);
180           exit(1);
181         }
182
183       cp = strchr(str, ' ');
184       if (cp)
185         *cp = '\0';
186       for (d = dispatch_table; d->str; d++)
187         {
188           if (!strcmp(d->str, str))
189             {
190               if (cp)
191                 *cp = ' ';
192               (d->proc)(conn, str);
193               goto ok;
194             }
195         }
196       com_err(whoami, 0, "unknown request received: %s", str);
197       code = send_int(conn, MR_UNKNOWN_PROC);
198       if (code)
199         com_err(whoami, code, "sending UNKNOWN_PROC");
200     ok:
201       free(str);
202     }
203 }
204
205 int send_ok(int conn)
206 {
207   return send_int(conn, 0);
208 }
209
210 /*
211  * quit request:
212  *
213  * syntax:
214  * >>> quit
215  * <<< (int)0
216  * any arguments are ignored
217  *
218  * function:
219  *      closes connection from MR
220  */
221
222 void quit(int conn, char *str)
223 {
224   send_ok(conn);
225   close(conn);
226   com_err(whoami, 0, "Closing connection.");
227   exit(0);
228 }
229
230 void fail(int conn, int err, char *msg)
231 {
232   com_err(whoami, err, msg);
233   close(conn);
234   exit(1);
235 }
236
237 void child_handler(int signal)
238 {
239   int status;
240
241   while (waitpid(-1, &status, WNOHANG) > 0)
242     ;
243 }
244
245 static void syslog_com_err_proc(const char *progname, long code,
246                                 const char *fmt, va_list args)
247 {
248   char buf[BUFSIZ + 1];
249
250   buf[BUFSIZ] = '\0';
251
252   vsnprintf(buf, BUFSIZ, fmt, args);
253   syslog(LOG_NOTICE, "%s: %s %s", progname ? progname : "",
254          code ? error_message(code) : "", buf);
255 }
This page took 0.066985 seconds and 3 git commands to generate.