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