]> andersk Git - moira.git/blob - update/update_server.c
- Don't ifdef out auth_002; it breaks backward compatability.
[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   { "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
60 int 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
203 int 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
220 void 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
228 void fail(int conn, int err, char *msg)
229 {
230   com_err(whoami, err, msg);
231   close(conn);
232   exit(1);
233 }
234
235 void child_handler(int signal)
236 {
237   int status;
238
239   while (waitpid(-1, &status, WNOHANG) > 0)
240     ;
241 }
242
243 static 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 }
This page took 0.221822 seconds and 5 git commands to generate.