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