-/*
- * $Source$
- * $Header$
+/* $Id$
+ *
+ * Copyright 1988-1998 by the Massachusetts Institute of Technology.
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
*/
-/* (c) Copyright 1988 by the Massachusetts Institute of Technology. */
-/* For copying and distribution information, please see the file */
-/* <mit-copyright.h>. */
-
-#ifndef lint
-static char *rcsid_dispatch_c = "$Header$";
-#endif lint
#include <mit-copyright.h>
-#include <stdio.h>
-#include <gdb.h>
-#include <errno.h>
-#include <strings.h>
-#include <sms.h>
-#include <sys/file.h>
-#include <sys/ioctl.h>
-#include "update.h"
+#include <moira.h>
+#include "update_server.h"
-/* XXX */
-#include "kludge.h"
-/* XXX */
+#include <sys/stat.h>
+#include <sys/utsname.h>
+#include <sys/wait.h>
-extern int auth_001(), inst_001();
-extern int xfer_002(), exec_002();
+#include <netinet/in.h>
+#include <arpa/inet.h>
-extern int sync_proc(), quit();
+#include <errno.h>
+#include <pwd.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <syslog.h>
-extern void gdb_debug();
-extern int exit(), abort(), errno;
-extern STRING instructions;
+#ifdef HAVE_KRB4
+#include <des.h>
+#endif
+#include "update.h"
-CONNECTION conn;
-int code;
-char *whoami;
+RCSID("$Header$");
-int have_authorization = 0;
-int have_file = 0;
-int have_instructions = 0;
-int done = 0;
+char *whoami, *hostname;
+int have_authorization = 0;
+#ifdef HAVE_KRB4
+des_cblock session;
+#endif
+int uid = 0;
-#define send_int(n) \
- (_send_int=(n),send_object(conn,(char *)&_send_int,INTEGER_T))
-int _send_int;
+void child_handler(int signal);
+static void syslog_com_err_proc(const char *progname, long code,
+ const char *fmt, va_list args);
struct _dt {
- char *str;
- int (*proc)();
+ char *str;
+ void (*proc)(int, char *);
} dispatch_table[] = {
- { "INST_001", inst_001 },
- { "AUTH_001", auth_001 },
- { "XFER_002", xfer_002 },
- { "EXEC_002", exec_002 },
- { "quit", quit },
- { (char *)NULL, abort }
+ { "AUTH_002", auth_002 },
+ { "AUTH_003", auth_003 },
+ { "XFER_002", xfer_002 },
+ { "XFER_003", xfer_003 },
+ { "EXEC_002", exec_002 },
+ { "quit", quit },
+ { NULL, (void (*)(int, char *))abort }
};
-/*
- * general scratch space -- useful for building
- * error messages et al...
- */
-char buf[BUFSIZ];
-err(code, fmt)
- int code;
- char *fmt;
+int main(int argc, char **argv)
{
- sprintf(buf, fmt, error_message(code));
- sms_log_error(buf);
-}
+ char *str, *p;
+ size_t len;
+ struct _dt *d;
+ struct utsname name;
+ int s, conn;
+ struct sigaction sa;
+
+ whoami = strrchr(argv[0], '/');
+ if (whoami)
+ whoami++;
+ else
+ whoami = argv[0];
+
+ /* interpret arguments here */
+ if (argc != 1)
+ {
+ fprintf(stderr, "Usage: %s\n", whoami);
+ exit(1);
+ }
-main(argc, argv)
- int argc;
- char **argv;
-{
- STRING str;
- struct _dt *d;
- int n;
-
-#ifdef DEBUG
- gdb_debug(GDB_NOFORK);
-#endif /* DEBUG */
-
- whoami = rindex(argv[0], '/');
- if (whoami)
- whoami++;
- else
- whoami = argv[0];
-
- /* interpret arguments here */
- if (argc != 1) {
- fprintf(stderr, "Usage: %s\n", whoami);
+ if (!config_lookup("nofork"))
+ {
+ if (fork())
+ exit(0);
+ setsid();
+ }
+
+ uname(&name);
+ hostname = name.nodename;
+
+ umask(0022);
+ mr_init();
+
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = SA_RESTART;
+ sa.sa_handler = child_handler;
+ sigaction(SIGCHLD, &sa, NULL);
+
+ /* If the config file contains a line "user username", the
+ * daemon will run with that user's UID.
+ */
+ if ((p = config_lookup("user")))
+ {
+ struct passwd *pw;
+ pw = getpwnam(p);
+ if (!pw)
+ {
+ com_err(whoami, errno, "Unable to find user %s\n", p);
exit(1);
- }
- /* well, sort of... */
-
-#ifndef DEBUG
- if (fork())
- exit(0);
- n = open("/dev/tty", O_RDWR|O_NDELAY);
- if (n > 0) {
- (void) ioctl(n, TIOCNOTTY, (char *)NULL);
- (void) close(n);
- }
-#endif
+ }
+ uid = pw->pw_uid;
+ }
- umask(0022);
- init_sms_err_tbl();
- init_krb_err_tbl();
- sms_update_initialize();
+ /* If the config file contains a line "port portname", the daemon
+ * will listen on the named port rather than SERVICE_NAME ("moira_update")
+ */
+ if (!(p = config_lookup("port")))
+ p = SERVICE_NAME;
+
+ s = mr_listen(p);
+ if (s == -1)
+ {
+ com_err(whoami, errno, "creating listening socket");
+ exit(1);
+ }
+
+ set_com_err_hook(syslog_com_err_proc);
+ openlog(whoami, LOG_PID, LOG_DAEMON);
- /* wait for connection */
- gdb_init();
- conn = create_forking_server(SERVICE_NAME, 0);
- if (!conn) {
- err(errno, "%s: can't get connection");
+ /* now loop waiting for connections */
+ while (1)
+ {
+ struct sockaddr_in client;
+ long len;
+ char *buf;
+
+ conn = mr_accept(s, &client);
+ if (conn == -1)
+ {
+ com_err(whoami, errno, "accepting on listening socket");
exit(1);
- }
- if (connection_status(conn) == CON_STOPPED) {
- com_err(whoami, connection_errno(conn), ": can't get connection");
- exit(1);
- }
-
- sms_log_info("got connection");
- /* got a connection; loop forever */
- while (1) {
- register char *cp;
- code = receive_object(conn, (char *)&str, STRING_T);
- if (code) {
- err(connection_errno(conn), "%s: receiving command");
- sever_connection(conn);
- exit(1);
- }
- cp = index(STRING_DATA(str), ' ');
- if (cp)
- *cp = '\0';
- for (d = dispatch_table; d->str; d++) {
- if (!strcmp(d->str, STRING_DATA(str))) {
- if (cp)
- *cp = ' ';
-#ifdef DEBUG
- printf("got request: %s\n", STRING_DATA(str));
-#endif /* DEBUG */
- (void)(d->proc)(STRING_DATA(str));
- goto ok;
- }
- }
- sprintf(buf, "unknown request received: %s\n", STRING_DATA(str));
- sms_log_error(buf);
- code = send_int(SMS_UNKNOWN_PROC);
- if (code) {
- err(connection_errno(conn), "%s: sending UNKNOWN_PROC");
- }
- ok:
- string_free(&str);
- }
-}
+ }
+ else if (conn == 0)
+ continue;
-int
-send_ok()
-{
- static int zero = 0;
- return((code = send_object(conn, (char *)&zero, INTEGER_T)));
-}
+ if (config_lookup("nofork") || (fork() <= 0))
+ break;
+ close(conn);
+ }
-initialize()
-{
- /* keep have_authorization around */
- have_file = 0;
- have_instructions = 0;
- done = 0;
- if (STRING_DATA(instructions) != (char *)NULL)
- string_free(&instructions);
+ /* If the config file contains a line "chroot /dir/name", the
+ * daemon will run chrooted to that directory.
+ */
+ if ((p = config_lookup("chroot")))
+ {
+ if (chroot(p) < 0)
+ {
+ com_err(whoami, errno, "unable to chroot to %s", p);
+ exit(1);
+ }
+ }
+
+ com_err(whoami, 0, "got connection");
+
+ while (1)
+ {
+ char *cp, *str;
+ size_t len;
+ int code;
+
+ code = recv_string(conn, &str, &len);
+ if (code)
+ {
+ com_err(whoami, code, "receiving command");
+ close(conn);
+ exit(1);
+ }
+
+ cp = strchr(str, ' ');
+ if (cp)
+ *cp = '\0';
+ for (d = dispatch_table; d->str; d++)
+ {
+ if (!strcmp(d->str, str))
+ {
+ if (cp)
+ *cp = ' ';
+ (d->proc)(conn, str);
+ goto ok;
+ }
+ }
+ com_err(whoami, 0, "unknown request received: %s", str);
+ code = send_int(conn, MR_UNKNOWN_PROC);
+ if (code)
+ com_err(whoami, code, "sending UNKNOWN_PROC");
+ ok:
+ free(str);
+ }
}
+int send_ok(int conn)
+{
+ return send_int(conn, 0);
+}
/*
* quit request:
* any arguments are ignored
*
* function:
- * closes connection from SMS
+ * closes connection from MR
*/
-int
-quit(str)
- char *str;
+
+void quit(int conn, char *str)
{
-#ifdef lint
- str = (char *)NULL;
-#endif /* lint */
- (void) send_ok();
- sever_connection(conn);
- sms_log_info("Closing connection.");
- exit(0);
+ send_ok(conn);
+ close(conn);
+ com_err(whoami, 0, "Closing connection.");
+ exit(0);
}
-
-/*
- * lose(msg)
- *
- * put <msg> to log as error, break connection, and exit
- */
-
-lose(msg)
- char *msg;
+void fail(int conn, int err, char *msg)
{
- sprintf(buf, "%s: %s", error_message(code), msg);
- sms_log_error(buf);
- if (conn)
- sever_connection(conn);
- exit(1);
+ com_err(whoami, err, msg);
+ close(conn);
+ exit(1);
}
-/*
- * report_error(msg)
- *
- * send back (external) <code>; if error, punt big with <lose(msg)>
- */
-
-report_error(msg)
- char *msg;
+void child_handler(int signal)
{
- code = send_object(conn, (char *)&code, INTEGER_T);
- if (code) {
- code = connection_errno(conn);
- lose(msg);
- }
-}
+ int status;
-/*
- * reject_call(c)
- *
- * set (external) <code> to <c> and call <report_error>
- */
+ while (waitpid(-1, &status, WNOHANG) > 0)
+ ;
+}
-reject_call(c)
- int c;
+static void syslog_com_err_proc(const char *progname, long code,
+ const char *fmt, va_list args)
{
- code = c;
- report_error("call rejected");
+ char buf[BUFSIZ + 1];
+
+ buf[BUFSIZ] = '\0';
+
+ vsnprintf(buf, BUFSIZ, fmt, args);
+ syslog(LOG_NOTICE, "%s: %s %s", progname ? progname : "",
+ code ? error_message(code) : "", buf);
}