]>
Commit | Line | Data |
---|---|---|
7ac48069 | 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>. | |
de56407f | 6 | */ |
de56407f | 7 | |
546bc43b | 8 | #include <mit-copyright.h> |
7ac48069 | 9 | #include <moira.h> |
10 | #include "update_server.h" | |
11 | ||
12 | #include <sys/stat.h> | |
85330553 | 13 | #include <sys/utsname.h> |
cf0ec460 | 14 | #include <sys/wait.h> |
7ac48069 | 15 | |
85330553 | 16 | #include <netinet/in.h> |
ea0caf4a | 17 | #include <arpa/inet.h> |
85330553 | 18 | |
19 | #include <errno.h> | |
7ac48069 | 20 | #include <pwd.h> |
cf0ec460 | 21 | #include <signal.h> |
de56407f | 22 | #include <stdio.h> |
7da203a3 | 23 | #include <stdlib.h> |
698271c7 | 24 | #include <string.h> |
7ac48069 | 25 | #include <unistd.h> |
9d3d51ad | 26 | #include <syslog.h> |
de56407f | 27 | |
cb974713 | 28 | #ifdef HAVE_KRB4 |
7ac48069 | 29 | #include <des.h> |
cb974713 | 30 | #endif |
7ac48069 | 31 | #include "update.h" |
de56407f | 32 | |
7ac48069 | 33 | RCSID("$Header$"); |
de56407f | 34 | |
85330553 | 35 | char *whoami, *hostname; |
de56407f | 36 | |
45c91bf7 | 37 | int have_authorization = 0; |
cb974713 | 38 | #ifdef HAVE_KRB4 |
85330553 | 39 | des_cblock session; |
cb974713 | 40 | #endif |
529a5b0d | 41 | int uid = 0; |
45c91bf7 | 42 | |
cf0ec460 | 43 | void child_handler(int signal); |
9d3d51ad | 44 | static void syslog_com_err_proc(const char *progname, long code, |
45 | const char *fmt, va_list args); | |
cf0ec460 | 46 | |
de56407f | 47 | struct _dt { |
5eaef520 | 48 | char *str; |
85330553 | 49 | void (*proc)(int, char *); |
de56407f | 50 | } dispatch_table[] = { |
5eaef520 | 51 | { "AUTH_002", auth_002 }, |
991417e4 | 52 | { "AUTH_003", auth_003 }, |
5eaef520 | 53 | { "XFER_002", xfer_002 }, |
54 | { "XFER_003", xfer_003 }, | |
55 | { "EXEC_002", exec_002 }, | |
56 | { "quit", quit }, | |
85330553 | 57 | { NULL, (void (*)(int, char *))abort } |
de56407f | 58 | }; |
59 | ||
5eaef520 | 60 | int main(int argc, char **argv) |
de56407f | 61 | { |
85330553 | 62 | char *str, *p; |
63 | size_t len; | |
5eaef520 | 64 | struct _dt *d; |
85330553 | 65 | struct utsname name; |
66 | int s, conn; | |
cf0ec460 | 67 | struct sigaction sa; |
5eaef520 | 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 | } | |
5eaef520 | 88 | |
85330553 | 89 | uname(&name); |
90 | hostname = name.nodename; | |
5eaef520 | 91 | |
85330553 | 92 | umask(0022); |
93 | mr_init(); | |
5eaef520 | 94 | |
cf0ec460 | 95 | sigemptyset(&sa.sa_mask); |
96 | sa.sa_flags = SA_RESTART; | |
97 | sa.sa_handler = child_handler; | |
98 | sigaction(SIGCHLD, &sa, NULL); | |
99 | ||
5eaef520 | 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); | |
de56407f | 110 | exit(1); |
5eaef520 | 111 | } |
112 | uid = pw->pw_uid; | |
113 | } | |
de56407f | 114 | |
85330553 | 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 | ||
9d3d51ad | 128 | set_com_err_hook(syslog_com_err_proc); |
129 | openlog(whoami, LOG_PID, LOG_DAEMON); | |
130 | ||
85330553 | 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; | |
bcb7d888 | 149 | |
150 | close(conn); | |
85330553 | 151 | } |
152 | ||
5eaef520 | 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 | } | |
45c91bf7 | 164 | |
85330553 | 165 | com_err(whoami, 0, "got connection"); |
5eaef520 | 166 | |
5eaef520 | 167 | while (1) |
168 | { | |
85330553 | 169 | char *cp, *str; |
170 | size_t len; | |
171 | int code; | |
172 | ||
173 | code = recv_string(conn, &str, &len); | |
5eaef520 | 174 | if (code) |
175 | { | |
85330553 | 176 | com_err(whoami, code, "receiving command"); |
177 | close(conn); | |
5eaef520 | 178 | exit(1); |
179 | } | |
85330553 | 180 | |
181 | cp = strchr(str, ' '); | |
5eaef520 | 182 | if (cp) |
183 | *cp = '\0'; | |
184 | for (d = dispatch_table; d->str; d++) | |
185 | { | |
85330553 | 186 | if (!strcmp(d->str, str)) |
5eaef520 | 187 | { |
188 | if (cp) | |
189 | *cp = ' '; | |
85330553 | 190 | (d->proc)(conn, str); |
5eaef520 | 191 | goto ok; |
192 | } | |
193 | } | |
85330553 | 194 | com_err(whoami, 0, "unknown request received: %s", str); |
195 | code = send_int(conn, MR_UNKNOWN_PROC); | |
5eaef520 | 196 | if (code) |
85330553 | 197 | com_err(whoami, code, "sending UNKNOWN_PROC"); |
5eaef520 | 198 | ok: |
85330553 | 199 | free(str); |
5eaef520 | 200 | } |
de56407f | 201 | } |
202 | ||
85330553 | 203 | int send_ok(int conn) |
45c91bf7 | 204 | { |
85330553 | 205 | return send_int(conn, 0); |
45c91bf7 | 206 | } |
207 | ||
45c91bf7 | 208 | /* |
209 | * quit request: | |
210 | * | |
211 | * syntax: | |
212 | * >>> quit | |
213 | * <<< (int)0 | |
214 | * any arguments are ignored | |
215 | * | |
216 | * function: | |
2ad0a777 | 217 | * closes connection from MR |
45c91bf7 | 218 | */ |
85330553 | 219 | |
220 | void quit(int conn, char *str) | |
45c91bf7 | 221 | { |
85330553 | 222 | send_ok(conn); |
223 | close(conn); | |
224 | com_err(whoami, 0, "Closing connection."); | |
5eaef520 | 225 | exit(0); |
45c91bf7 | 226 | } |
227 | ||
85330553 | 228 | void fail(int conn, int err, char *msg) |
45c91bf7 | 229 | { |
85330553 | 230 | com_err(whoami, err, msg); |
231 | close(conn); | |
5eaef520 | 232 | exit(1); |
45c91bf7 | 233 | } |
cf0ec460 | 234 | |
235 | void child_handler(int signal) | |
236 | { | |
237 | int status; | |
238 | ||
239 | while (waitpid(-1, &status, WNOHANG) > 0) | |
240 | ; | |
241 | } | |
9d3d51ad | 242 | |
243 | static void syslog_com_err_proc(const char *progname, long code, | |
244 | const char *fmt, va_list args) | |
245 | { | |
995c29c0 | 246 | char buf[BUFSIZ + 1]; |
9d3d51ad | 247 | |
995c29c0 | 248 | buf[BUFSIZ] = '\0'; |
9d3d51ad | 249 | |
995c29c0 | 250 | vsnprintf(buf, BUFSIZ, fmt, args); |
908337d2 | 251 | syslog(LOG_NOTICE, "%s: %s %s", progname ? progname : "", |
252 | code ? error_message(code) : "", buf); | |
9d3d51ad | 253 | } |