]> andersk Git - moira.git/commitdiff
Initial revision
authorwesommer <wesommer>
Sat, 22 Aug 1987 16:34:57 +0000 (16:34 +0000)
committerwesommer <wesommer>
Sat, 22 Aug 1987 16:34:57 +0000 (16:34 +0000)
22 files changed:
backup/copy_backups.c [new file with mode: 0644]
clients/Makefile [new file with mode: 0644]
gen/hesiod.sh [new file with mode: 0644]
gen/nfs.sh [new file with mode: 0644]
lib/Makefile [new file with mode: 0644]
lib/fixname.c [new file with mode: 0644]
lib/mr_ops.c [new file with mode: 0644]
server/meinitlst.c [new file with mode: 0644]
server/mr_smalloc.c [new file with mode: 0644]
update/Makefile [new file with mode: 0644]
update/auth_001.c [new file with mode: 0644]
update/checksum.c [new file with mode: 0644]
update/client.c [new file with mode: 0644]
update/exec_002.c [new file with mode: 0644]
update/get_file.c [new file with mode: 0644]
update/hostname.c [new file with mode: 0644]
update/inst_001.c [new file with mode: 0644]
update/log.c [new file with mode: 0644]
update/send_file.c [new file with mode: 0644]
update/ticket.c [new file with mode: 0644]
update/update_server.c [new file with mode: 0644]
update/xfer_002.c [new file with mode: 0644]

diff --git a/backup/copy_backups.c b/backup/copy_backups.c
new file mode 100644 (file)
index 0000000..a92eb7e
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ *     $Source$
+ *     $Author$
+ *     $Header$
+ *
+ *     Copyright (C) 1987 by the Massachusetts Institute of Technology
+ *
+ *     $Log$
+ *     Revision 1.1  1987-08-22 17:03:18  wesommer
+ *     Initial revision
+ *
+ */
+
+#ifndef lint
+static char *rcsid_copy_backups_c = "$Header$";
+#endif lint
+#include <stdio.h>
+#include <strings.h>
+#include <sys/types.h>
+#include "update.h"
+
+char *whoami;
+char host[BUFSIZ];
+char buf[BUFSIZ];
+
+static struct update_desc info = {
+     42,                        /* last_time_tried */
+     1,                         /* success */
+     12,                        /* interval */
+     "backup",                 /* service_name */
+     "ZEUS.MIT.EDU",           /* host_name */
+     "/tmp/frobnicate",         /* target_path */
+     2,                         /* override */
+     1,                         /* enable */
+     "/dev/null"
+                                /* instructions */
+};
+
+extern char *error_message();
+#include <sys/dir.h>
+
+main(argc,argv)
+    int argc;
+    char **argv;
+{
+    int rc;
+    DIR *pd, *sd;
+    struct direct *pde, *sde;
+    
+    whoami = rindex(argv[0], '/');
+    if (whoami)
+        whoami++;
+    else
+        whoami = argv[0];
+    whoami = argv[0];
+    if (chdir ("/u3/sms_backup") < 0) {
+       perror("can't change to /u3/sms_backup");
+       exit(1);
+    }
+    
+    pd = opendir(".");
+    if (pd == NULL) {
+       perror("can't open sms_backup directory");
+       exit(1);
+    }
+
+    while ( (pde = readdir(pd)) != NULL ) {
+       char *dir_name = pde->d_name;
+       printf("Directory: %s\n", dir_name);
+
+       if (dir_name[0] == '.') continue; /* ignore hidden files */
+       
+       if (chdir(dir_name) < 0) {
+           perror(dir_name);
+           continue;
+       }
+       sd = opendir (".");
+       if (sd == NULL) {
+           perror("Can't open .");
+           goto dotdot;
+       }
+       while ( (sde = readdir(sd)) != NULL ) {
+           if (sde->d_name[0] == '.') continue;
+           
+           sprintf(buf, "/site/sms/sms_backup/%s/%s", dir_name, sde->d_name);
+           printf("Updating: %s\n", buf);
+           info.target_path = buf;
+           rc = sms_update_server(&info, sde->d_name);
+           if (rc) printf("return code: %s\n", error_message(rc));
+       }
+       closedir(sd);
+       
+    dotdot:
+       chdir("..");
+    }
+    closedir(pd);
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-indent-level: 4
+ * c-continued-statement-offset: 4
+ * c-brace-offset: -4
+ * c-argdecl-indent: 4
+ * c-label-offset: -4
+ * End:
+ */
diff --git a/clients/Makefile b/clients/Makefile
new file mode 100644 (file)
index 0000000..9195bb3
--- /dev/null
@@ -0,0 +1,23 @@
+# Makefile for first release of SMS.
+#
+#      $Source$
+#      $Header$
+#      $Author$
+#
+
+DESTDIR=
+
+SUBDIRS= aliasbld finger listmaint madm rvdmaint servermaint usermaint userreg
+
+all:
+       for i in ${SUBDIRS}; do \
+               (cd $$i; make ${MFLAGS} all); done
+
+install:
+       for i in ${SUBDIRS}; do \
+               (cd $$; make ${MFLAGS} install); done
+
+clean:
+       for i in ${SUBDIRS}; do \
+               (cd $$i; make ${MFLAGS} clean); done
+
diff --git a/gen/hesiod.sh b/gen/hesiod.sh
new file mode 100644 (file)
index 0000000..4d8a6bc
--- /dev/null
@@ -0,0 +1,33 @@
+#! /bin/sh
+TARFILE=/tmp/hesiod
+SRC_DIR=/etc/athena/_nameserver
+DEST_DIR=/etc/athena/nameserver
+if [ ! -d $SRC_DIR ]; then
+       /bin/rm -f $SRC_DIR
+       /bin/mkdir $SRC_DIR
+       /bin/chmod 755 $SRC_DIR
+fi
+#if [ ! -d $DEST_DIR ]; then
+#      /bin/rm -f $DEST_DIR
+#      /bin/mkdir $DEST_DIR
+#      /bin/chmod 755 $DEST_DIR
+#fi
+cd $SRC_DIR
+for file in `/bin/tar tf $TARFILE`; do 
+       if [ ./ = $file ]; then continue; fi
+       /bin/tar xf $TARFILE $file
+       if [ -s $file ]; then
+               /bin/mv -f $file $DEST_DIR
+       else
+               /bin/rm -f $file
+       fi
+done
+#/bin/rm -f $TARFILE
+#kill -HUP `/bin/cat /etc/named.pid`
+
+
+exit
+#
+#      $Source$
+#      $Header$
+#
diff --git a/gen/nfs.sh b/gen/nfs.sh
new file mode 100644 (file)
index 0000000..99ec36e
--- /dev/null
@@ -0,0 +1,9 @@
+mkdir /tmp/nfs.dir
+cd /tmp/nfs.dir
+tar xf /tmp/nfs
+chmod 775 /tmp/nfs.dir
+exit
+#
+#      $Source$
+#      $Header$
+#
diff --git a/lib/Makefile b/lib/Makefile
new file mode 100644 (file)
index 0000000..14c96b6
--- /dev/null
@@ -0,0 +1,163 @@
+#      $Source$
+#      $Author$
+#      $Header$
+#
+#      Makefile for SMS library.
+#
+LIBSRC=sms_auth.c sms_call.c sms_connect.c sms_data.c sms_init.c \
+       sms_shutdown.c sms_query.c sms_param.c sms_access.c sms_misc.c \
+       sms_al_filsys.c sms_al_pobox.c menu.c admin_call.c admin_util_new.c \
+       sms_do_update.c fixname.c
+
+CFILES=${LIBSRC}
+
+LIBOBJ=sms_auth.o sms_call.o sms_connect.o sms_data.o sms_et.o \
+       sms_init.o sms_shutdown.o sms_query.o sms_param.o sms_access.o \
+       sms_misc.o sms_al_filsys.o sms_al_pobox.o krb_et.o menu.o \
+       admin_call.o admin_util_new.o admin_err.o sms_do_update.o \
+       fixname.o
+
+COPTS= -O
+
+INCDIRS=-I../include
+
+CFLAGS= ${INCDIRS} ${COPTS}
+LINTFLAGS= -uhv
+
+ALL=libsms.a llib-lsms.ln libsms_p.a
+
+.c.o:
+       ${CC} -c -pg ${CFLAGS} $*.c
+       ld -x -r $*.o
+       mv a.out profiled/$*.o
+       ${CC} -c ${CFLAGS} $*.c
+       ld -x -r $*.o
+       mv a.out $*.o
+
+all: ${ALL}
+
+libsms.a: ${LIBOBJ}
+       ar cruv $@ ${LIBOBJ}
+       ranlib $@
+       (cd profiled; ar cruv ../libsms_p.a ${LIBOBJ}; ranlib ../libsms_p.a)
+
+smslib.dvi: smslib.tex
+       latex smslib.tex
+
+krb_et.o: krb_et.et
+       compile_et krb_et.et
+       cp krb_et.o profiled/krb_et.o
+
+sms_et.o: sms_et.et
+       compile_et sms_et.et
+       cp sms_et.o profiled/sms_et.o
+
+sms_et.h: sms_et.o
+
+admin_err.o: admin_err.et
+       compile_et admin_err.et
+       cp admin_err.o profiled/admin_err.o
+
+admin_err.h: admin_err.o
+
+../include/sms_et.h: sms_et.h
+
+clean:
+       rm -f ${ALL}
+       rm -f *.o *~ admin_err.h sms_et.h krb_et.h profiled/*.o \#*
+       rm -f *.PS *.aux *.dvi *.log
+       rm -f *.bak
+
+
+install:
+       install -m 644 libsms.a ${DESTDIR}/usr/athena/lib/libsms.a
+       ranlib ${DESTDIR}/usr/athena/lib/libsms.a
+       install -m 644 libsms_p.a ${DESTDIR}/usr/athena/lib/libsms_p.a
+       ranlib ${DESTDIR}/usr/athena/lib/libsms_p.a
+       -mkdir ${DESTDIR}/usr/athena/lib/lint
+       install -m 644 llib-lsms.ln ${DESTDIR}/usr/athena/lib/lint/llib-lsms.ln
+
+TAGS:  $(CFILES)
+       -etags $(CFILES)
+
+lint:  ${CFILES} llib-lsms.ln
+       lint ${LINTFLAGS} ${INCDIRS} sms_main.c llib-lsms.ln
+
+llib-lsms.ln:  ${LIBSRC}
+       lint -Csms $(LINTFLAGS) $(INCDIRS) ${LIBSRC}
+
+depend: $(CFILES) sms_et.h admin_err.h
+       $(CC) -M $(CFLAGS) $(CFILES) | \
+       sed -e 's; ./; ;' \
+           -e ':loop' \
+           -e 's/\.\.\/[^ /]*\/\.\./../' \
+           -e 't loop' | \
+       awk ' { if ($$1 != prev) { print rec; rec = $$0; prev = $$1; } \
+               else { if (length(rec $$2) > 78) { print rec; rec = $$0; } \
+                      else rec = rec " " $$2 } } \
+             END { print rec } ' > makedep
+       echo '/^# DO NOT DELETE THIS LINE/+1,$$d' >eddep
+       echo '$$r makedep' >>eddep
+       echo 'w' >>eddep
+       cp Makefile Makefile.bak
+       ed - Makefile < eddep
+       rm eddep makedep
+#
+# the last constant line in the makefile should be...
+# DO NOT DELETE THIS LINE
+
+sms_auth.o: sms_auth.c sms_private.h sms_proto.h /usr/include/stdio.h
+sms_auth.o: ../include/gdb.h /usr/include/sys/types.h /usr/include/sys/time.h
+sms_auth.o: /usr/include/time.h ../include/sms.h ../include/sms_et.h
+sms_auth.o: /usr/include/krb.h /usr/include/des.h
+sms_call.o: sms_call.c sms_private.h sms_proto.h /usr/include/stdio.h
+sms_call.o: ../include/gdb.h /usr/include/sys/types.h /usr/include/sys/time.h
+sms_call.o: /usr/include/time.h ../include/sms.h ../include/sms_et.h
+sms_connect.o: sms_connect.c sms_private.h sms_proto.h /usr/include/stdio.h
+sms_connect.o: ../include/gdb.h /usr/include/sys/types.h
+sms_connect.o: /usr/include/sys/time.h /usr/include/time.h ../include/sms.h
+sms_connect.o: ../include/sms_et.h
+sms_data.o: sms_data.c sms_private.h sms_proto.h /usr/include/stdio.h
+sms_data.o: ../include/gdb.h /usr/include/sys/types.h /usr/include/sys/time.h
+sms_data.o: /usr/include/time.h ../include/sms.h ../include/sms_et.h
+sms_init.o: sms_init.c sms_private.h sms_proto.h /usr/include/stdio.h
+sms_init.o: ../include/gdb.h /usr/include/sys/types.h /usr/include/sys/time.h
+sms_init.o: /usr/include/time.h ../include/sms.h ../include/sms_et.h
+sms_shutdown.o: sms_shutdown.c sms_private.h sms_proto.h /usr/include/stdio.h
+sms_shutdown.o: ../include/gdb.h /usr/include/sys/types.h
+sms_shutdown.o: /usr/include/sys/time.h /usr/include/time.h ../include/sms.h
+sms_shutdown.o: ../include/sms_et.h
+sms_query.o: sms_query.c sms_private.h sms_proto.h /usr/include/stdio.h
+sms_query.o: ../include/gdb.h /usr/include/sys/types.h /usr/include/sys/time.h
+sms_query.o: /usr/include/time.h ../include/sms.h ../include/sms_et.h
+sms_param.o: sms_param.c /usr/include/sys/types.h /usr/include/netinet/in.h
+sms_param.o: sms_private.h sms_proto.h /usr/include/stdio.h ../include/gdb.h
+sms_param.o: /usr/include/sys/types.h /usr/include/sys/time.h
+sms_param.o: /usr/include/time.h ../include/sms.h ../include/sms_et.h
+sms_access.o: sms_access.c sms_private.h sms_proto.h /usr/include/stdio.h
+sms_access.o: ../include/gdb.h /usr/include/sys/types.h /usr/include/sys/time.h
+sms_access.o: /usr/include/time.h ../include/sms.h ../include/sms_et.h
+sms_misc.o: sms_misc.c /usr/include/strings.h
+sms_al_filsys.o: sms_al_filsys.c ../include/sms_et.h /usr/include/stdio.h
+sms_al_pobox.o: sms_al_pobox.c ../include/sms_et.h /usr/include/stdio.h
+sms_al_pobox.o: /usr/include/ctype.h
+menu.o: menu.c /usr/include/stdio.h /usr/include/curses.h /usr/include/stdio.h
+menu.o: /usr/include/sgtty.h /usr/include/sys/ioctl.h
+menu.o: /usr/include/sys/ttychars.h /usr/include/sys/ttydev.h
+menu.o: /usr/include/ctype.h ../include/menu.h
+admin_call.o: admin_call.c /usr/include/sys/errno.h /usr/include/sys/types.h
+admin_call.o: /usr/include/sys/time.h /usr/include/time.h
+admin_call.o: /usr/include/sys/ioctl.h /usr/include/sys/ttychars.h
+admin_call.o: /usr/include/sys/ttydev.h /usr/include/sys/socket.h
+admin_call.o: /usr/include/netinet/in.h /usr/include/netdb.h
+admin_call.o: /usr/include/strings.h /usr/include/stdio.h admin_err.h
+admin_call.o: admin_server.h prot.h /usr/include/krb.h /usr/include/des.h
+admin_util_new.o: admin_util_new.c /usr/include/sys/types.h
+admin_util_new.o: /usr/include/sys/errno.h /usr/include/sys/ioctl.h
+admin_util_new.o: /usr/include/sys/ttychars.h /usr/include/sys/ttydev.h
+admin_util_new.o: /usr/include/sys/signal.h /usr/include/sys/file.h
+admin_util_new.o: /usr/include/sys/param.h /usr/include/machine/machparam.h
+admin_util_new.o: /usr/include/signal.h /usr/include/sys/types.h
+admin_util_new.o: /usr/include/stdio.h /usr/include/strings.h
+admin_util_new.o: /usr/include/krb.h /usr/include/des.h /usr/include/setjmp.h
+admin_util_new.o: /usr/include/pwd.h admin_server.h prot.h admin_err.h
diff --git a/lib/fixname.c b/lib/fixname.c
new file mode 100644 (file)
index 0000000..91d53d0
--- /dev/null
@@ -0,0 +1,174 @@
+/*
+ *     $Source$
+ *     $Author$
+ *     $Header$
+ *
+ *     Copyright (C) 1987 by the Massachusetts Institute of Technology
+ *
+ *     $Log$
+ *     Revision 1.1  1987-08-22 17:14:30  wesommer
+ *     Initial revision
+ *
+ */
+
+#ifndef lint
+static char *rcsid_fixname_c = "$Header$";
+#endif lint
+
+#include <strings.h>
+#include <ctype.h>
+
+#define LAST_LEN               15
+#define FIRST_LEN              15
+
+void FixName(ilnm, ifnm, last, first, middle)
+       char *ilnm, *ifnm;
+       char *first, *last, *middle;
+{
+       int ends_jr=0, ends_iii=0, ends_iv=0;
+
+       Upcase(ilnm);
+       Upcase(ifnm);
+       
+       /* Last name ... */
+
+       TrimTrailingSpace(ilnm);
+       LookForJrAndIII(ilnm, &ends_jr, &ends_iii, &ends_iv);
+       LookForSt(ilnm);
+       LookForO(ilnm);
+       FixCase(ilnm);
+       strncpy(last, ilnm, LAST_LEN);
+
+               /* First name  & middle initial ... */
+
+       TrimTrailingSpace(ifnm);
+       LookForJrAndIII(ifnm, &ends_jr, &ends_iii, &ends_iv);
+
+        GetMidInit(ifnm, middle);
+
+       FixCase(ifnm);
+#ifdef notdef
+               /* okay, finish up first name */
+       AppendJrOrIII(ifnm, &ends_jr, &ends_iii, &ends_iv);
+#endif notdef
+       strncpy(first, ifnm, FIRST_LEN);
+}
+#ifdef notdef
+AppendJrOrIII(nm, phas_jr, phas_iii, phas_iv)
+register char *nm;
+register int *phas_jr;
+register int *phas_iii;
+register int *phas_iv;
+{
+    if (*phas_jr) {
+       strcat(nm, ", Jr.");
+    }
+    else if (*phas_iii) {
+       strcat(nm, " III");
+    }
+    else if (*phas_iv) {
+       strcat(nm, " IV");
+    }
+}
+#endif notdef
+FixCase(p)
+register char *p;
+{
+    register int cflag;        /* convert to lcase, unless at start or following */
+                       /* a space or punctuation mark (e.g., '-') */
+
+    for (cflag = 0; *p; p++) {
+       if (cflag && isupper(*p)) {
+           *p = tolower(*p);
+       }
+       else if (isspace(*p) || ispunct(*p)) {
+           cflag = 0;
+       }
+       else {
+           cflag = 1;
+       }
+    }
+}
+
+LookForJrAndIII(nm, pends_jr, pends_iii, pends_iv)
+register char *nm;
+register int *pends_jr;
+register int *pends_iii;
+register int *pends_iv;
+{
+    register int len = strlen(nm);
+
+    if (len >= 4 && !strcmp(nm + len - 3, " JR")) {
+       *pends_jr = 1;
+       nm[len - 3] = '\0';
+    }
+    else if (len >= 4 && !strcmp(nm + len - 3, " IV")) {
+       *pends_iv = 1;
+       nm[len - 3] = '\0';
+    }
+    else if (len >= 5 && !strcmp(nm + len - 4, " JR.")) {
+       *pends_jr = 1;
+       nm[len - 4] = '\0';
+    }
+    else if (len >= 5 && !strcmp(nm + len - 4, " III")) {
+       *pends_iii = 1;
+       nm[len - 4] = '\0';
+    }
+}
+
+LookForSt(nm)          /* ST PIERRE, etc. */
+register char *nm;
+{
+    char temp[256];
+
+    if (!strcmp(nm,"ST ")) {
+       strcpy(temp, nm + 3);
+       strcpy(nm, "ST. ");
+       strcat(nm, temp);
+    }
+}
+
+LookForO(nm)           /* O BRIEN, etc. */
+register char *nm;
+{
+    if (!strcmp(nm, "O ") && isalpha(nm[2])) {
+       nm[1] = '\'';
+    }
+}
+
+TrimTrailingSpace(ip)
+register char *ip;
+{
+    register char *p;
+    for (p = ip + strlen(ip) - 1; p >= ip && isspace(*p); p--) {
+       *p = '\0';
+    }
+}
+
+Upcase(cp)
+       char *cp;
+{
+       register int c;
+       
+       for ( ; c= *cp; cp++)
+               if (islower(c)) *cp = toupper(c);
+}
+
+GetMidInit(nm, mi)
+register char *nm;     /* truncate at first space, if any such */
+register char *mi;     /* set to first char after first space, if any such */
+{
+    while (*nm && !isspace(*nm)) {
+       nm++;
+    }
+    if (*nm) {
+       *nm++ = '\0';
+    }
+    while (*nm && isspace(*nm)) {
+       nm++;
+    }
+    if (*nm) {
+       *mi++ = *nm;
+    }
+    *mi = '\0';
+}
diff --git a/lib/mr_ops.c b/lib/mr_ops.c
new file mode 100644 (file)
index 0000000..63d194f
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ *     $Source$
+ *     $Author$
+ *     $Header$
+ *
+ *     Copyright (C) 1987 by the Massachusetts Institute of Technology
+ *     
+ *     This routine is part of the client library.  It handles
+ * creating a connection to the sms server.
+ */
+
+#ifndef lint
+static char *rcsid_sms_do_update_c = "$Header$";
+#endif lint
+
+#include "sms_private.h"
+
+int sms_do_update()
+{
+    int status;
+    sms_params param_st;
+    struct sms_params *params = NULL;
+    struct sms_params *reply = NULL;
+
+    CHECK_CONNECTED;
+    params = &param_st;
+    params->sms_procno = SMS_DO_UPDATE;
+    params->sms_argc = 0;
+    params->sms_argl = NULL;
+    params->sms_argv = NULL;
+       
+    if ((status = sms_do_call(params, &reply)) == 0)
+       status = reply->sms_status;
+       
+    sms_destroy_reply(reply);
+
+    return status;
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-indent-level: 4
+ * c-continued-statement-offset: 4
+ * c-brace-offset: -4
+ * c-argdecl-indent: 4
+ * c-label-offset: -4
+ * End:
+ */
diff --git a/server/meinitlst.c b/server/meinitlst.c
new file mode 100644 (file)
index 0000000..5e93c17
--- /dev/null
@@ -0,0 +1,170 @@
+/*
+ *     $Source$
+ *     $Author$
+ *     $Header$
+ *
+ *     Copyright (C) 1987 by the Massachusetts Institute of Technology
+ *
+ *     This code is a reverse-engineered version of
+ *     ~rtingres/lib/compatlib(meinitlst.o) with a better malloc and
+ *     free.
+ *     $Log$
+ *     Revision 1.1  1987-08-22 17:29:33  wesommer
+ *     Initial revision
+ *
+ */
+
+#ifndef lint
+static char *rcsid_meinitlst_c = "$Header$";
+#endif lint
+
+#include <sys/errno.h>
+#include <sys/types.h>
+
+/*
+ * entry points:
+ *     MEinitLists()
+ *     calloc()
+ *     free()
+ *     malloc()
+ *     memalign()
+ *     realloc()
+ *     valloc()
+ */
+
+struct cons {
+       char *car;
+       char *cdr;
+};
+extern int Status;
+extern char MEsetup;
+extern struct cons MElist, MEfreelist;
+extern short ME_pid;
+extern char *MElistHead, *MEfreeHead;
+
+MEinitLists()
+{
+       Status = 0;
+       MEsetup = 1;
+       MElist.car = 0;
+       MElist.cdr = MElistHead;
+       MEfreelist.car = 0;
+       MEfreelist.cdr = MEfreeHead;
+       ME_pid = getpid() & 0x7fff;
+       return 0;
+}
+#ifdef notdef
+free(addr)
+{
+       return MEfree(addr);
+}
+
+caddr_t malloc(size)
+       u_int size;
+{
+       char *temp;
+       if(MEalloc(1, size, &temp)) return 0;
+       else return temp;
+}
+
+caddr_t calloc(a1, a2)
+       int a1, a2;
+{
+       char *temp;
+       if (MEcalloc(a1, a2, &temp)) return 0;
+       else return temp;
+}
+
+caddr_t realloc(adr, nsize)
+       char *adr;
+       u_int nsize;
+{
+       char *new_addr;
+       u_int cur_size;
+       if (MEsize(adr, &cur_size)) return 0;
+       if (cur_size >= nsize) return adr;
+       if ( (new_addr = malloc(nsize)) == 0) return 0;
+       (void) MEcopy(adr, cur_size, new_addr);
+       (void) free(adr);
+       return new_addr;
+}
+#endif notdef
+#ifdef notdef
+valloc(size)
+       int size;
+{
+       static int pagesize;
+       if (pagesize == 0) pagesize = getpagesize();
+       return memalign(pagesize, size);
+}
+
+memalign(alignment, size)
+{
+       int temp1;
+       int temp2;
+       int temp3;
+       int temp4;
+       if (!size || alignment & 1) {
+               errno = EINVAL;
+               return 0;
+       }
+       if (alignment < 4) alignment = 4;
+
+/*
+_memalign:      fc0
+_memalign+2:    subl2   $10,sp
+_memalign+5:    tstl    8(ap)
+_memalign+8:    beql    _memalign+e
+_memalign+a:    blbc    4(ap),_memalign+18
+>_memalign+e:    movl    $16,_errno
+>_memalign+15:   clrf    r0
+_memalign+17:   ret
+>_memalign+18:   cmpl    4(ap),$4
+_memalign+1c:   bgequ   _memalign+22
+_memalign+1e:   movl    $4,4(ap)
+>_memalign+22:   pushl   $4
+_memalign+24:   addl3   $3,8(ap),-(sp)
+_memalign+29:   calls   $2,udiv
+_memalign+30:   ashl    $2,r0,8(ap)
+_memalign+35:   addl3   4(ap),8(ap),r0
+_memalign+3b:   addl3   $20,r0,-4(fp)
+_memalign+40:   pushl   -4(fp)
+_memalign+43:   calls   $1,_malloc
+_memalign+4a:   movl    r0,r11
+_memalign+4d:   beql    _memalign+15
+_memalign+4f:   subl3   $10,r11,r10
+_memalign+53:   ashl    $0,4(r10),r8
+_memalign+58:   pushl   4(ap)
+_memalign+5b:   subl3   $1,4(ap),r0
+_memalign+60:   addl3   r11,r0,-(sp)
+_memalign+64:   calls   $2,udiv
+_memalign+6b:   mull3   4(ap),r0,-c(fp)
+_memalign+71:   movl    -c(fp),r7
+_memalign+75:   subl3   $10,r7,r6
+_memalign+79:   subl3   r10,r6,-8(fp)
+_memalign+7e:   subl2   -8(fp),r8
+_memalign+82:   cmpl    -8(fp),$10
+_memalign+86:   bgequ   _memalign+a7
+_memalign+88:   pushl   8(ap)
+_memalign+8b:   pushl   4(ap)
+_memalign+8e:   calls   $2,_memalign
+_memalign+95:   movl    r0,-10(fp)
+_memalign+99:   pushl   r11
+_memalign+9b:   calls   $1,_free
+_memalign+a2:   movl    -10(fp),r0
+_memalign+a6:   ret
+>_memalign+a7:   movl    -8(fp),r0
+_memalign+ab:   extzv   $0,$20,r0,4(r10)
+_memalign+b1:   extzv   $0,$20,r8,4(r6)
+_memalign+b7:   movl    (r10),(r6)
+_memalign+ba:   movw    8(r10),8(r6)
+_memalign+bf:   movl    r6,_MElist
+_memalign+c6:   cmpl    _MElist+4,r10
+_memalign+cd:   bneq    _memalign+d6
+_memalign+cf:   movl    r6,_MElist+4
+>_memalign+d6:   pushl   r10
+_memalign+d8:   calls   $1,_MEf_add
+_memalign+df:   addl3   $10,r6,r0
+_memalign+e3:   ret
+*/
+#endif notdef
diff --git a/server/mr_smalloc.c b/server/mr_smalloc.c
new file mode 100644 (file)
index 0000000..9909f18
--- /dev/null
@@ -0,0 +1,784 @@
+#include <stdio.h>
+botch(message)
+       char *message;
+{
+       fprintf(stderr, "Malloc botch: %s\n", message);
+       abort();
+}      
+
+#define rcheck
+/****************************************************************
+ *                                                             *
+ *             Storage Allocator for Foundation.               *
+ *             Built from gnuemacs storage allocator           *
+ *                                                             *
+ ****************************************************************/
+
+/*   Copyright (C) 1985 Richard M. Stallman,
+    based mostly on the public domain work of others.
+
+This program is distributed in the hope that it will be useful,
+but without any warranty.  No author or distributor
+accepts responsibility to anyone for the consequences of using it
+or for whether it serves any particular purpose or works at all,
+unless he says so in writing.
+
+   Permission is granted to anyone to distribute verbatim copies
+   of this program's source code as received, in any medium, provided that
+   the copyright notice, the nonwarraty notice above
+   and this permission notice are preserved,
+   and that the distributor grants the recipient all rights
+   for further redistribution as permitted by this notice,
+   and informs him of these rights.
+
+   Permission is granted to distribute modified versions of this
+   program's source code, or of portions of it, under the above
+   conditions, plus the conditions that all changed files carry
+   prominent notices stating who last changed them and that the
+   derived material, including anything packaged together with it and
+   conceptually functioning as a modification of it rather than an
+   application of it, is in its entirety subject to a permission
+   notice identical to this one.
+
+   Permission is granted to distribute this program (verbatim or
+   as modified) in compiled or executable form, provided verbatim
+   redistribution is permitted as stated above for source code, and
+    A.  it is accompanied by the corresponding machine-readable
+      source code, under the above conditions, or
+    B.  it is accompanied by a written offer, with no time limit,
+      to distribute the corresponding machine-readable source code,
+      under the above conditions, to any one, in return for reimbursement
+      of the cost of distribution.   Verbatim redistribution of the
+      written offer must be permitted.  Or,
+    C.  it is distributed by someone who received only the
+      compiled or executable form, and is accompanied by a copy of the
+      written offer of source code which he received along with it.
+
+   Permission is granted to distribute this program (verbatim or as modified)
+   in executable form as part of a larger system provided that the source
+   code for this program, including any modifications used,
+   is also distributed or offered as stated in the preceding paragraph.
+
+In other words, you are welcome to use, share and improve this program.
+You are forbidden to forbid anyone else to use, share and improve
+what you give them.   Help stamp out software-hoarding!  */
+\f
+/****************************************************************
+ *                                                             *
+ *             Helpful historical comments                     *
+ *                                                             *
+ ****************************************************************/
+
+/*
+ * @(#)nmalloc.c 1 (Caltech) 2/21/82
+ *
+ *     U of M Modified: 20 Jun 1983 ACT: strange hacks for Emacs
+ *
+ *     Nov 1983, Mike@BRL, Added support for 4.1C/4.2 BSD.
+ *
+ * This is a very fast storage allocator.  It allocates blocks of a small 
+ * number of different sizes, and keeps free lists of each size.  Blocks
+ * that don't exactly fit are passed up to the next larger size.  In this 
+ * implementation, the available sizes are (2^n)-4 (or -16) bytes long.
+ * This is designed for use in a program that uses vast quantities of
+ * memory, but bombs when it runs out.  To make it a little better, it
+ * warns the user when he starts to get near the end.
+ *
+ * June 84, ACT: modified rcheck code to check the range given to malloc,
+ * rather than the range determined by the 2-power used.
+ *
+ * Jan 85, RMS: calls malloc_warning to issue warning on nearly full.
+ * No longer Emacs-specific; can serve as all-purpose malloc for GNU.
+ * You should call malloc_init to reinitialize after loading dumped Emacs.
+ * Call malloc_stats to get info on memory stats if MSTATS turned on.
+ * realloc knows how to return same block given, just changing its size,
+ * if the power of 2 is correct.
+ *
+ * Jan 86, WDC: Removed Emacs specific stuff, and neatened a few comments.
+ *
+ * March 86 WDC: Added in code by Eichin for Scribble checking of blocks
+ * Scribble check writes a known pattern into the free blocks, checks it
+ * to see if it is still undamaged before allocating it.  It writes a
+ * different pattern into the space beyond the end of an allocated block,
+ * and tests it for damage when expanding the block's bounds in realloc.
+ * Note, this check takes *TIME* and should not be compiled in by default.
+ *
+ * Berkeley UNIX 4.3 has a storage allocator that shares a common
+ * ancestor with this one.  It handles realloc compatibly with the
+ * archaic use of realloc on an already freed block to "compact"
+ * storage.  It uses a pagesize system call rather than assuming the
+ * page size is 1024 bytes.  Finally it guarantees that a freed block
+ * is not munged by the allocator itself, incase someone wants to fiddle
+ * with freed space after freeing it but before allocating more.
+ *
+ * This particular storage allocator would benefit from having a
+ * non-hardwired pagesize.  But because of the scribble check it would
+ * not be useful to keep the free pointer in the header.  SO: When you
+ * free something allocated with this allocator, DONT TRY TO USE IT.
+ * It is GUARANTEED to be damaged by the freeing process.
+ *
+ * For interfacing to systems that want to be able to ask the size of
+ * the allocated block, rather than remembering it, the m_blocksize
+ * function, rips open the block and tells you how big it is.  The size
+ * returned is nbytes, the number of bytes asked for, NOT the actual
+ * amount of space in the block.
+ */
+\f
+/****************************************************************
+ *                                                             *
+ *      Includes, declarations, and definitions                *
+ *                                                             *
+ ****************************************************************/
+
+/* Determine which kind of system this is.  */
+#include <signal.h>
+#ifndef SIGTSTP
+#define USG
+#else /* SIGTSTP */
+#ifdef SIGIO
+#define BSD42
+#endif /* SIGIO */
+#endif /* SIGTSTP */
+
+#ifndef BSD42
+#ifndef USG
+#include <sys/vlimit.h>                /* warn the user when near the end */
+#endif
+#else /* if BSD42 */
+#include <sys/time.h>
+#include <sys/resource.h>
+#endif /* BSD42 */
+
+#ifdef scribblecheck
+#define rcheck
+#endif /* we need to have range data to use block boundary checking */
+
+#ifdef rcheck
+/*
+ * To implement range checking, we write magic values in at the
+ * beginning and end of each allocated block, and make sure they
+ * are undisturbed whenever a free or a realloc occurs.
+ */
+
+/* Written in each of the 4 bytes following the block's real space */
+#define MAGIC1 0x55
+#define MAGICFREE 0x69         /* 0110 1001 Magic value for Free blocks */
+
+/* Written in the 4 bytes before the block's real space */
+#define MAGIC4 0x55555555
+#define MAGICFREE4 0x69696969
+
+#define ASSERT(p) if (!(p)) botch("p"); else
+#define EXTRA  4               /* 4 bytes extra for MAGIC1s */
+#else
+#define ASSERT(p)
+#define EXTRA  0
+#endif /* rcheck */
+
+#define ISALLOC ((char) 0xf7)  /* magic byte that implies allocation */
+#define ISFREE ((char) 0x54)   /* magic byte that implies free block */
+                               /* this is for error checking only */
+
+/* If range checking is not turned on, all we have is a flag
+ * indicating whether memory is allocated, an index in nextf[],
+ * and a field that tells how many bytes.
+ * To realloc() memory we copy nbytes.
+ * 16 bits of header space is unused.
+ */
+struct mhead {
+       char     mh_alloc;      /* ISALLOC or ISFREE */
+       char     mh_index;      /* index in nextf[] */
+       unsigned short mh_extra;/* Currently wasted 16 bits */
+/* Remainder are valid only when block is allocated */
+       unsigned mh_nbytes;     /* number of bytes allocated */
+#ifdef rcheck
+       int      mh_magic4;     /* should be == MAGIC4 */
+#endif /* rcheck */
+};
+
+/*
+ * Access free-list pointer of a block.
+ * It is stored at block + 4.
+ * This is not a field in the mhead structure because we want
+ * sizeof (struct mhead) to describe the overhead for when the
+ * block is in use, and we do not want the free-list pointer
+ * to count in that.
+ */
+#define CHAIN(a) \
+  (*(struct mhead **) (sizeof (char *) + (char *) (a)))
+
+\f
+/****************************************************************
+ *                                                             *
+ *             Variable Creations                              *
+ *                                                             *
+ ****************************************************************/
+
+extern char etext;
+extern char *start_of_data ();  /* This seems necessary for USG */
+
+#ifdef notdef
+
+/* These two are for user programs to look at, when they are interested.  */
+
+int malloc_sbrk_used;       /* amount of data space used now */
+int malloc_sbrk_unused;     /* amount more we can have */
+#endif notdef
+/* start of data space; can be changed by calling init_malloc */
+static char *data_space_start;
+
+#ifdef MSTATS
+/*
+ * nmalloc[i] is the difference between the number of mallocs and frees
+ * for a given block size.
+ */
+static int nmalloc[30];
+static int nmal, nfre;
+#endif /* MSTATS */
+
+/*
+ * nextf[i] is the pointer to the next free block of size 2^(i+3).  The
+ * smallest allocatable block is 8 bytes.  The overhead information will
+ * go in the first int of the block, and the returned pointer will point
+ * to the second.
+ */
+static struct mhead *nextf[30];
+
+/* Number of bytes of writable memory we can expect to be able to get */
+static int lim_data;
+/* Level number of warnings already issued.
+ * 0 -- no warnings issued.
+ * 1 -- 75% warning already issued.
+ * 2 -- 85% warning already issued.
+ */
+static int warnlevel;
+
+#ifdef notdef
+/* nonzero once initial bunch of free blocks made */
+static int gotpool;
+#endif notdef
+\f
+/****************************************************************
+ *                                                             *
+ *             Start of procedures                             *
+ *                                                             *
+ *     malloc_init, m_blocksize                                *
+ *                                                             *
+ ****************************************************************/
+
+/*
+ * Cause reinitialization based on job parameters;
+ * also declare where the end of pure storage is.
+ */
+malloc_init (start)
+     char *start;
+{
+  data_space_start = start;
+  lim_data = 0;
+  warnlevel = 0;
+}
+
+int m_blocksize(a_block)
+     char *a_block;
+{
+  return(((struct mhead *)a_block-1)->mh_nbytes);
+}
+extern int MEinitLists();
+
+static int (*foo)() = MEinitLists;
+       
+\f
+/****************************************************************
+ *                                                             *
+ *    morecore - Ask the system for more memory                        *
+ *                                                             *
+ ****************************************************************/
+
+static
+morecore (nu)                  /* ask system for more memory */
+     register int nu;          /* size index to get more of  */
+{
+  char *sbrk ();
+  register char *cp;
+  register int nblks;
+  register int siz;
+
+#ifdef notdef
+  if (!data_space_start)
+    {
+#if defined(USG)
+      data_space_start = start_of_data ();
+#else /* not USG */
+      data_space_start = &etext;
+#endif /* not USG */
+    }
+
+  if (lim_data == 0)
+    get_lim_data ();
+
+  /* On initial startup, get two blocks of each size up to 1k bytes */
+  if (!gotpool)
+    getpool (), getpool (), gotpool = 1;
+
+  /* Find current end of memory and issue warning if getting near max */
+
+  cp = sbrk (0);
+  siz = cp - data_space_start;
+  malloc_sbrk_used = siz;
+  malloc_sbrk_unused = lim_data - siz;
+
+  switch (warnlevel)
+    {
+    case 0: 
+      if (siz > (lim_data / 4) * 3)
+       {
+         warnlevel++;
+         malloc_warning ("Warning: past 75% of memory limit");
+       }
+      break;
+    case 1: 
+      if (siz > (lim_data / 20) * 17)
+       {
+         warnlevel++;
+         malloc_warning ("Warning: past 85% of memory limit");
+       }
+      break;
+    case 2: 
+      if (siz > (lim_data / 20) * 19)
+       {
+         warnlevel++;
+         malloc_warning ("Warning: past 95% of memory limit");
+       }
+      break;
+    }
+
+  if ((int) cp & 0x3ff)        /* land on 1K boundaries */
+    sbrk (1024 - ((int) cp & 0x3ff));
+#endif notdef
+  
+  /* Take at least 2k, and figure out how many blocks of the desired size
+    we're about to get */
+  nblks = 1;
+  if ((siz = nu) < 8)
+    nblks = 1 << ((siz = 8) - nu);
+#ifdef notdef
+  if ((cp = sbrk (1 << (siz + 3))) == (char *) -1)
+    return;                    /* no more room! */
+#endif notdef
+  {
+     char *tcp;          
+     if (MEalloc(1, 1 << (siz+3), &tcp))
+       return;                 /* No more room! */
+     cp = tcp;
+  }
+  if ((int) cp & 7)
+    {          /* shouldn't happen, but just in case */
+      cp = (char *) (((int) cp + 8) & ~7);
+      nblks--;
+    }
+
+  /* save new header and link the nblks blocks together */
+  nextf[nu] = (struct mhead *) cp;
+  siz = 1 << (nu + 3);
+  while (1)
+    {
+      ((struct mhead *) cp) -> mh_alloc = ISFREE;
+      ((struct mhead *) cp) -> mh_index = nu;
+#ifdef rcheck
+      ((struct mhead *) cp) -> mh_magic4 = MAGICFREE4;
+#endif /* rcheck */
+#ifdef scribblecheck
+    {
+      /* Check that upper stuff was still MAGIC1 */
+      register char *m = (char *)((struct mhead *)cp+1);
+      register char *en = (8<<nu) + cp;
+      /* Fill whole block with MAGICFREE */
+      while (m<en) *m++ = MAGICFREE;
+    }
+#endif /* scribblecheck */
+
+      /* Clear newly allocated blocks, to match free ones */
+      if (--nblks <= 0) break;
+      CHAIN ((struct mhead *) cp) = (struct mhead *) (cp + siz);
+      cp += siz;
+    }
+  CHAIN ((struct mhead *) cp) = 0;
+}
+\f
+/****************************************************************
+ *                                                             *
+ *     getpool - Get initial pools of small blocks             *
+ *                                                             *
+ ****************************************************************/
+#ifdef notdef
+static
+getpool ()
+{
+  register int nu;
+  register char *cp = sbrk (0);
+
+  if ((int) cp & 0x3ff)        /* land on 1K boundaries */
+    sbrk (1024 - ((int) cp & 0x3ff));
+
+  /* Get 2k of storage */
+
+  cp = sbrk (04000);
+  if (cp == (char *) -1)
+    return;
+
+  /* Divide it into an initial 8-word block
+     plus one block of size 2**nu for nu = 3 ... 10.  */
+
+  CHAIN (cp) = nextf[0];
+  nextf[0] = (struct mhead *) cp;
+  ((struct mhead *) cp) -> mh_alloc = ISFREE;
+  ((struct mhead *) cp) -> mh_index = 0;
+#ifdef rcheck
+      ((struct mhead *) cp) -> mh_magic4 = MAGICFREE4;
+#endif /* rcheck */
+  cp += 8;
+
+  for (nu = 0; nu < 7; nu++)
+    {
+      CHAIN (cp) = nextf[nu];
+      nextf[nu] = (struct mhead *) cp;
+      ((struct mhead *) cp) -> mh_alloc = ISFREE;
+      ((struct mhead *) cp) -> mh_index = nu;
+#ifdef rcheck
+      ((struct mhead *) cp) -> mh_magic4 = MAGICFREE4;
+#endif /* rcheck */
+#ifdef scribblecheck
+    {
+      register char *m = (char *)((struct mhead *)cp+1);
+      register char *en = (8<<nu) + cp;
+      /* Fill whole block with MAGICFREE */
+      while (m<en) *m++ = MAGICFREE;
+    }
+#endif /* scribblecheck */
+      cp += 8 << nu;
+    }
+}
+#endif notdef
+\f
+/****************************************************************
+ *                                                             *
+ *     malloc - get a block of space from a pool               *
+ *                                                             *
+ ****************************************************************/
+
+char *
+malloc (n)             /* get a block */
+     unsigned n;
+{
+  register struct mhead *p;
+  register unsigned int nbytes;
+  register int nunits = 0;
+
+  /* Figure out how many bytes are required, rounding up to the nearest
+     multiple of 4, then figure out which nextf[] area to use */
+  nbytes = (n + sizeof *p + EXTRA + 3) & ~3;
+  {
+    register unsigned int   shiftr = (nbytes - 1) >> 2;
+
+    while (shiftr >>= 1)
+      nunits++;
+  }
+
+  /* If there are no blocks of the appropriate size, go get some */
+  /* COULD SPLIT UP A LARGER BLOCK HERE ... ACT */
+  if (nextf[nunits] == 0)
+    morecore (nunits);
+
+  /* Get one block off the list, and set the new list head */
+  if ((p = nextf[nunits]) == 0)
+    return 0;
+  nextf[nunits] = CHAIN (p);
+
+  /* Check for free block clobbered */
+  /* If not for this check, we would gobble a clobbered free chain ptr */
+  /* and bomb out on the NEXT allocate of this size block */
+  if (p -> mh_alloc != ISFREE || p -> mh_index != nunits)
+#ifdef rcheck
+    botch ("block on free list clobbered");
+#else /* not rcheck */
+    abort ();
+#endif /* not rcheck */
+#ifdef rcheck
+  if (p -> mh_magic4 != MAGICFREE4)
+    botch ("Magic in block on free list clobbered");
+#endif /* rcheck */
+#ifdef scribblecheck
+  /* Check for block filled with magic numbers, then change to zeros */
+  {
+    register char  *m = (char *) (p + 1);
+    register char *en = (8<<p->mh_index) + (char *) p;
+    register int  block_valid = 0;
+    while(m<en && (block_valid=(*m==MAGICFREE)))
+      *m++=(char)0;
+    /* so, status comes out as 1 if ok, 0 if terminated */
+    if (!block_valid) botch ("data on free list damaged");
+  }
+#endif /* scribblecheck */
+  /* Fill in the info, and if range checking, set up the magic numbers */
+  p -> mh_alloc = ISALLOC;
+  p -> mh_nbytes = n;
+#ifdef rcheck
+  p -> mh_magic4 = MAGIC4;
+  {
+    register char  *m = (char *) (p + 1) + n;
+#ifdef scribblecheck
+    register char *en = (8<<p->mh_index)+(char *)p;
+    /* point to end of block */
+    while (m<en) *m++ = MAGIC1;
+#else /* scribblecheck */
+    *m++ = MAGIC1, *m++ = MAGIC1, *m++ = MAGIC1, *m = MAGIC1; 
+#endif /* scribblecheck */
+  }
+#endif /* not rcheck */
+#ifdef MSTATS
+  nmalloc[nunits]++;
+  nmal++;
+#endif /* MSTATS */
+  return (char *) (p + 1);
+}
+\f
+/****************************************************************
+ *                                                             *
+ *     free - Free a block of space                            *
+ *                                                             *
+ ****************************************************************/
+
+free (mem)
+     char *mem;
+{
+  register struct mhead *p;
+  {
+    register char *ap = mem;
+
+    ASSERT (ap != 0);
+    p = (struct mhead *) ap - 1;
+    ASSERT (p -> mh_alloc == ISALLOC);
+#ifdef rcheck
+    ASSERT (p -> mh_magic4 == MAGIC4);
+    ap += p -> mh_nbytes;
+    p->mh_magic4 = MAGICFREE4;
+    ASSERT (*ap++ == MAGIC1); ASSERT (*ap++ == MAGIC1);
+    ASSERT (*ap++ == MAGIC1); ASSERT (*ap   == MAGIC1);
+#endif /* rcheck */
+  }
+  {
+    register int nunits = p -> mh_index;
+
+    ASSERT (nunits <= 29);
+#ifdef scribblecheck
+    {
+      /* Check that upper stuff was still MAGIC1 */
+      register char  *m = (char *) (p + 1) + p->mh_nbytes;
+      register char *en = (8<<p->mh_index) + (char *) p;
+      register int  block_valid = 0;
+      while(m<en && (block_valid=(*m++==MAGIC1)));
+      if (!block_valid) botch ("block freed with data out of bounds");
+      /* Fill whole block with MAGICFREE */
+      m = (char *) (p + 1);
+      while (m<en) *m++ = MAGICFREE;
+    }
+#endif /* scribblecheck */
+    p -> mh_alloc = ISFREE;
+    CHAIN (p) = nextf[nunits];
+    nextf[nunits] = p;
+#ifdef MSTATS
+    nmalloc[nunits]--;
+    nfre++;
+#endif /* MSTATS */
+  }
+}
+\f
+/****************************************************************
+ *                                                             *
+ *     realloc - resize a block, copy if necessary             *
+ *                                                             *
+ ****************************************************************/
+
+char *
+realloc (mem, n)
+     char *mem;
+     register unsigned n;
+{
+  register struct mhead *p;
+  register unsigned int tocopy;
+  register int nbytes;
+  register int nunits;
+
+  if ((p = (struct mhead *) mem) == 0)
+    return malloc (n);
+  p--;
+  nunits = p -> mh_index;
+  ASSERT (p -> mh_alloc == ISALLOC);
+  tocopy = p -> mh_nbytes;
+#ifdef rcheck
+  ASSERT (p -> mh_magic4 == MAGIC4);
+  {
+    register char *m = mem + tocopy;
+#ifdef scribblecheck
+    register char *en = (8<<p->mh_index) + (char *)p;
+    register int block_valid = 0;
+    while(m<en && (block_valid=(*m++==MAGIC1)));
+    if (!block_valid) botch ("out of bounds data on realloc");
+#else /* scribblecheck */
+    ASSERT (*m++ == MAGIC1); ASSERT (*m++ == MAGIC1);
+    ASSERT (*m++ == MAGIC1); ASSERT (*m   == MAGIC1);
+#endif /* scribblecheck */
+  }
+#endif /* not rcheck */
+
+  /* See if desired size rounds to same power of 2 as actual size. */
+  nbytes = (n + sizeof *p + EXTRA + 7) & ~7;
+
+  /* If ok, use the same block, just marking its size as changed.  */
+  if (nbytes > (4 << nunits) && nbytes <= (8 << nunits))
+    {
+      /* Here we check on realloc if we are grabbing unused space */
+#ifdef rcheck
+      register char *m = mem + tocopy;
+#ifdef scribblecheck
+      register char *en = (8<<p->mh_index) + (char *) p;
+      while (m<en) *m++=(char)0;
+#else /* scribblecheck */
+      *m++ = 0;  *m++ = 0;  *m++ = 0;  *m++ = 0;
+#endif /* scribblecheck */
+      m = mem + n;
+#ifdef scribblecheck
+      while(m<en) *m++ = MAGIC1;
+#else /* scribblecheck */
+      *m++ = MAGIC1;  *m++ = MAGIC1;  *m++ = MAGIC1;  *m++ = MAGIC1;
+#endif /* scribblecheck */
+#endif /* not rcheck */
+      p-> mh_nbytes = n;
+      return mem;
+    }
+
+  if (n < tocopy)
+    tocopy = n;
+  {
+    register char *new;
+
+    if ((new = malloc (n)) == 0)
+      return 0;
+    bcopy (mem, new, tocopy);
+    free (mem);
+    return new;
+  }
+}
+\f
+/****************************************************************
+ *                                                             *
+ *     Memory Statistics stuff                                 *
+ *                                                             *
+ ****************************************************************/
+
+#ifdef MSTATS
+/* Return statistics describing allocation of blocks of size 2**n. */
+
+struct mstats_value
+  {
+    int blocksize;
+    int nfree;
+    int nused;
+  };
+
+struct mstats_value
+malloc_stats (size)
+     int size;
+{
+  struct mstats_value v;
+  register int i;
+  register struct mhead *p;
+
+  v.nfree = 0;
+
+  if (size < 0 || size >= 30)
+    {
+      v.blocksize = 0;
+      v.nused = 0;
+      return v;
+    }
+
+  v.blocksize = 1 << (size + 3);
+  v.nused = nmalloc[size];
+
+  for (p = nextf[size]; p; p = CHAIN (p))
+    v.nfree++;
+
+  return v;
+}
+#endif /* MSTATS */
+\f
+#ifdef notdef
+/****************************************************************
+ *                                                             *
+ *     Stuff having to do with determining memory limits       *
+ *                                                             *
+ ****************************************************************/
+
+/*
+ *     This function returns the total number of bytes that the process
+ *     will be allowed to allocate via the sbrk(2) system call.  On
+ *     BSD systems this is the total space allocatable to stack and
+ *     data.  On USG systems this is the data space only.
+ */
+
+#ifdef USG
+
+get_lim_data ()
+{
+  extern long ulimit ();
+    
+  lim_data = ulimit (3, 0);
+  lim_data -= (long) data_space_start;
+}
+
+#else /* not USG */
+#ifndef BSD42
+
+get_lim_data ()
+{
+  lim_data = vlimit (LIM_DATA, -1);
+}
+
+#else /* BSD42 */
+
+get_lim_data ()
+{
+  struct rlimit XXrlimit;
+
+  getrlimit (RLIMIT_DATA, &XXrlimit);
+  lim_data = XXrlimit.rlim_cur;                /* soft limit */
+}
+
+#endif /* BSD42 */
+#endif /* not USG */
+#endif notdef
+
+/*
+ * Calloc - allocate and clear memory block
+ */
+char *
+calloc(num, size)
+        register unsigned num, size;
+{
+        extern char *malloc();
+        register char *p;
+
+        size *= num;
+        if (p = malloc(size))
+                bzero(p, size);
+        return (p);
+}
+
+cfree(p, num, size)
+        char *p;
+        unsigned num;
+        unsigned size;
+{
+        free(p);
+}
diff --git a/update/Makefile b/update/Makefile
new file mode 100644 (file)
index 0000000..30f6362
--- /dev/null
@@ -0,0 +1,170 @@
+#
+#      $Source$
+#      $Header$
+#
+
+#
+# Makefile for 'update' directory.
+#
+
+CC=    cc
+INCS=  -I../include
+DEFS=
+CFLAGS=        -g ${INCS} ${DEFS}
+LINTFLAGS= ${INCS}
+LDFLAGS= -x
+
+# server object files
+SOBJS= dispatch.o initialize_server.o \
+       quit.o xfer_001.o misc.o inst_001.o sync.o auth_001.o \
+       exec_001.o get_file.o xfer_002.o exec_002.o
+
+# client object files
+COBJS= client2.o ticket.o send_file.o
+
+# common object files
+COMOBJS= log_error.o hostname.o smsu_int.o log.o checksum.o
+
+SSRCS= dispatch.c initialize_server.c \
+       quit.c xfer_001.c misc.c inst_001.c sync.c auth_001.c \
+       exec_001.c get_file.c xfer_002.c exec_002.c
+
+CSRCS= client.c ticket.c send_file.c client2.c
+
+COMSRCS= log_error.c hostname.c log.c checksum.c
+
+# libmisc.a includes libcom_err.a and a working malloc()
+LIBS=  -L../lib -lgdb -lkrb -ldes -lcom_err
+
+all:   server sms_update.o test
+
+clean: 
+       -rm -f ${COBJS} ${SOBJS} ${COMOBJS}
+       -rm -f server sms_update.o test test.o smsu_int.h
+       -rm -f core a.out *~ \#*
+
+lint:
+       lint ${LINTFLAGS} ${SSRCS} ${COMSRCS}
+       lint ${LINTFLAGS} ${CSRCS} ${COMSRCS}
+
+server:        ${SOBJS} ${COMOBJS}
+       rm -f server
+       ${CC} ${CFLAGS} -o server ${SOBJS} ${COMOBJS} ${LIBS}
+
+sms_update.o:  ${COBJS} ${COMOBJS}
+       ld ${LDFLAGS} -r -o sms_update.o ${COBJS} ${COMOBJS}
+       -chmod -x sms_update.o
+
+smsu_int.o smsu_int.h: smsu_int.et
+       ../lib/et/compile_et smsu_int
+
+test.o: test.c
+       -rm -f test.o
+       ${CC} ${CFLAGS} -c test.c
+
+test:  test.o sms_update.o
+       rm -f test
+       ${CC} ${CFLAGS} -o test test.o sms_update.o ${LIBS}
+
+SRCS=  ${SSRCS} ${CSRCS} ${COMSRCS}
+depend:        smsu_int.h
+       -rm -f eddep makedep
+       ${CC} -M ${CFLAGS} ${SRCS} | \
+       sed -e 's; ./; ;' \
+           -e ':loop' \
+           -e 's/\.\.\/[^ /]*\/\.\./../' \
+           -e 't loop' | \
+       awk ' { if ($$1 != prev) { print rec; rec = $$0; prev = $$1; } \
+               else { if (length(rec $$2) > 78) { print rec; rec = $$0; } \
+                      else rec = rec " " $$2 } } \
+             END { print rec } ' > makedep
+       echo '/^# DO NOT DELETE THIS LINE/+1,$$d' >eddep
+       echo '$$r makedep' >>eddep
+       echo 'w' >>eddep
+       -rm -f Makefile.bak
+       cp Makefile Makefile.bak
+       ed - Makefile < eddep
+       rm -f eddep makedep
+#
+# the last line in the makefile should be...
+# DO NOT DELETE THIS LINE
+
+dispatch.o: dispatch.c /usr/include/stdio.h ../include/gdb.h
+dispatch.o: /usr/include/sys/types.h /usr/include/sys/time.h
+dispatch.o: /usr/include/time.h /usr/include/errno.h /usr/include/strings.h
+dispatch.o: ../include/update.h sms_update_int.h smsu_int.h kludge.h
+initialize_server.o: initialize_server.c /usr/include/stdio.h ../include/gdb.h
+initialize_server.o: /usr/include/sys/types.h /usr/include/sys/time.h
+initialize_server.o: /usr/include/time.h
+quit.o: quit.c /usr/include/stdio.h ../include/gdb.h /usr/include/sys/types.h
+quit.o: /usr/include/sys/time.h /usr/include/time.h
+xfer_001.o: xfer_001.c /usr/include/stdio.h /usr/include/strings.h
+xfer_001.o: ../include/gdb.h /usr/include/sys/types.h /usr/include/sys/time.h
+xfer_001.o: /usr/include/time.h /usr/include/ctype.h /usr/include/sys/param.h
+xfer_001.o: /usr/include/machine/machparam.h /usr/include/signal.h
+xfer_001.o: /usr/include/sys/types.h /usr/include/sys/file.h smsu_int.h
+xfer_001.o: kludge.h
+misc.o: misc.c /usr/include/stdio.h ../include/gdb.h /usr/include/sys/types.h
+misc.o: /usr/include/sys/time.h /usr/include/time.h sms_update_int.h kludge.h
+misc.o: /usr/include/sys/param.h /usr/include/machine/machparam.h
+misc.o: /usr/include/signal.h /usr/include/sys/types.h smsu_int.h
+inst_001.o: inst_001.c /usr/include/stdio.h ../include/gdb.h
+inst_001.o: /usr/include/sys/types.h /usr/include/sys/time.h
+inst_001.o: /usr/include/time.h kludge.h sms_update_int.h
+sync.o: sync.c /usr/include/stdio.h ../include/gdb.h /usr/include/sys/types.h
+sync.o: /usr/include/sys/time.h /usr/include/time.h kludge.h smsu_int.h
+auth_001.o: auth_001.c /usr/include/stdio.h /usr/include/strings.h
+auth_001.o: ../include/gdb.h /usr/include/sys/types.h /usr/include/sys/time.h
+auth_001.o: /usr/include/time.h smsu_int.h kludge.h /usr/include/krb.h
+auth_001.o: /usr/include/des.h /usr/include/netinet/in.h /usr/include/errno.h
+exec_001.o: exec_001.c /usr/include/stdio.h ../include/gdb.h
+exec_001.o: /usr/include/sys/types.h /usr/include/sys/time.h
+exec_001.o: /usr/include/time.h sms_update_int.h kludge.h smsu_int.h
+get_file.o: get_file.c /usr/include/stdio.h ../include/gdb.h
+get_file.o: /usr/include/sys/types.h /usr/include/sys/time.h
+get_file.o: /usr/include/time.h /usr/include/ctype.h /usr/include/sys/param.h
+get_file.o: /usr/include/machine/machparam.h /usr/include/signal.h
+get_file.o: /usr/include/sys/types.h /usr/include/sys/file.h
+get_file.o: ../include/update.h smsu_int.h kludge.h
+xfer_002.o: xfer_002.c /usr/include/stdio.h ../include/gdb.h
+xfer_002.o: /usr/include/sys/types.h /usr/include/sys/time.h
+xfer_002.o: /usr/include/time.h /usr/include/ctype.h /usr/include/sys/param.h
+xfer_002.o: /usr/include/machine/machparam.h /usr/include/signal.h
+xfer_002.o: /usr/include/sys/types.h /usr/include/sys/file.h smsu_int.h
+xfer_002.o: kludge.h /usr/include/strings.h
+exec_002.o: exec_002.c /usr/include/stdio.h /usr/include/sys/wait.h
+exec_002.o: ../include/gdb.h /usr/include/sys/types.h /usr/include/sys/time.h
+exec_002.o: /usr/include/time.h ../include/update.h sms_update_int.h kludge.h
+exec_002.o: smsu_int.h
+client.o: client.c /usr/include/stdio.h ../include/gdb.h
+client.o: /usr/include/sys/types.h /usr/include/sys/time.h /usr/include/time.h
+client.o: /usr/include/sys/stat.h /usr/include/sys/file.h
+client.o: /usr/include/sys/param.h /usr/include/machine/machparam.h
+client.o: /usr/include/signal.h /usr/include/sys/types.h ../include/update.h
+client.o: /usr/include/errno.h sms_update_int.h smsu_int.h /usr/include/krb.h
+client.o: /usr/include/des.h kludge.h
+stubs.o: stubs.c ../include/update.h
+ticket.o: ticket.c /usr/include/stdio.h /usr/include/krb.h /usr/include/des.h
+ticket.o: /usr/include/sys/types.h /usr/include/sys/stat.h
+ticket.o: /usr/include/strings.h sms_update_int.h ../include/com_err.h
+ticket.o: ../include/mit-sipb-copyright.h kludge.h
+send_file.o: send_file.c /usr/include/stdio.h ../include/com_err.h
+send_file.o: ../include/mit-sipb-copyright.h ../include/gdb.h
+send_file.o: /usr/include/sys/types.h /usr/include/sys/time.h
+send_file.o: /usr/include/time.h smsu_int.h /usr/include/sys/file.h
+send_file.o: ../include/update.h sms_update_int.h kludge.h
+client2.o: client2.c /usr/include/stdio.h /usr/include/strings.h
+client2.o: ../include/gdb.h /usr/include/sys/types.h /usr/include/sys/time.h
+client2.o: /usr/include/time.h /usr/include/sys/stat.h /usr/include/sys/file.h
+client2.o: /usr/include/sys/param.h /usr/include/machine/machparam.h
+client2.o: /usr/include/signal.h /usr/include/sys/types.h ../include/update.h
+client2.o: /usr/include/errno.h sms_update_int.h smsu_int.h /usr/include/krb.h
+client2.o: /usr/include/des.h kludge.h
+log_error.o: log_error.c /usr/include/stdio.h /usr/include/syslog.h
+hostname.o: hostname.c /usr/include/stdio.h /usr/include/sys/types.h
+hostname.o: /usr/include/netinet/in.h /usr/include/netdb.h /usr/include/ctype.h
+hostname.o: /usr/include/strings.h
+log.o: log.c /usr/include/stdio.h ../include/com_err.h
+log.o: ../include/mit-sipb-copyright.h /usr/include/varargs.h
+log.o: ../include/update.h /usr/include/krb.h /usr/include/des.h
+checksum.o: checksum.c /usr/include/stdio.h /usr/include/sys/file.h
diff --git a/update/auth_001.c b/update/auth_001.c
new file mode 100644 (file)
index 0000000..47c9df5
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ *     $Source$
+ *     $Header$
+ */
+
+#ifndef lint
+static char *rcsid_auth_001_c = "$Header$";
+#endif lint
+
+#include <stdio.h>
+#include <strings.h>
+#include "gdb.h"
+#include "smsu_int.h"
+#include "kludge.h"
+#include <krb.h>
+#include <netinet/in.h>
+#include <errno.h>
+
+extern char buf[BUFSIZ];
+extern int have_authorization;
+extern struct sockaddr_in *client_address();
+extern CONNECTION conn;
+int code;
+extern char *PrincipalHostname();
+static char sms[] = "sms";
+static char qmark[] = "???";
+
+/*
+ * authentication request auth_001:
+ *
+ * >>> (STRING) "auth_001"
+ * <<< (int) 0
+ * >>> (STRING) ticket
+ * <<< (int) code
+ *
+ */
+
+int
+auth_001(str)
+     char *str;
+{
+    STRING data;
+    char host[BUFSIZ];
+    AUTH_DAT ad;
+    char realm[REALM_SZ];
+    KTEXT_ST ticket_st;
+
+    if (send_ok())
+       lose("sending okay for authorization (auth_001)");
+    code = receive_object(conn, (char *)&data, STRING_T);
+    if (code) {
+       code = connection_errno(conn);
+       lose("awaiting Kerberos authenticators");
+    }
+    gethostname(host, BUFSIZ);
+    ticket_st.mbz = 0;
+    ticket_st.length = MAX_STRING_SIZE(data);
+    bcopy(STRING_DATA(data), ticket_st.dat, MAX_STRING_SIZE(data));
+    code = rd_ap_req(&ticket_st, sms,
+                    PrincipalHostname(host), 0,
+                    &ad, "/etc/srvtab");
+    if (code) {
+       code = krb_err_frob(code);
+       strcpy(ad.pname, qmark);
+       strcpy(ad.pinst, qmark);
+       strcpy(ad.prealm, qmark);
+       goto auth_failed;
+    }
+    if (get_krbrlm(realm,0))
+       realm[0] = '\0';
+    code = EPERM;
+    if (strcmp(sms, ad.pname))
+       goto auth_failed;
+    if (ad.pinst[0] != '\0')
+       goto auth_failed;
+    if (strcmp(realm, ad.prealm))
+       goto auth_failed;
+    if (send_ok())
+       lose("sending approval of authorization");
+    have_authorization = 1;
+    return(0);
+auth_failed:
+    sprintf(buf, "auth for %s.%s@%s failed: %s",
+           ad.pname, ad.pinst, ad.prealm, error_message(code));
+    {
+       register int rc;
+       rc = send_object(conn, (char *)&code, INTEGER_T);
+       code = rc;
+    }
+    if (code)
+       lose("sending rejection of authenticator");
+    return(EPERM);
+}
diff --git a/update/checksum.c b/update/checksum.c
new file mode 100644 (file)
index 0000000..c2336aa
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ *     $Source$
+ *     $Header$
+ */
+
+#ifndef lint
+static char *rcsid_checksum_c = "$Header$";
+#endif lint
+
+#include <stdio.h>
+#include <sys/file.h>
+
+/*
+ * checksum_fd(fd)
+ * returns 24-bit checksum of bytes in file
+ */
+
+int
+checksum_fd(fd1)
+    int fd1;
+{
+    int fd;
+    register int sum;
+    register int ch;
+    register FILE *f;
+
+    fd = dup(fd1);
+    sum = 0;
+    (void) lseek(fd, 0, L_SET);
+    f = fdopen(fd, "r");
+    while ((ch = getc(f)) != EOF) {
+       sum = (sum + ch) & ((1<<24)-1);
+    }
+    fclose(f);
+    return(sum);
+}
diff --git a/update/client.c b/update/client.c
new file mode 100644 (file)
index 0000000..3c11518
--- /dev/null
@@ -0,0 +1,421 @@
+/*
+ *     $Source$
+ *     $Header$
+ */
+
+#ifndef lint
+static char *rcsid_client2_c = "$Header$";
+#endif lint
+
+/*
+ * MODULE IDENTIFICATION:
+ *     $Header$
+ *     Copyright 1987 MIT Project Athena.
+ * DESCRIPTION:
+ *     This code handles the actual distribution of data files
+ *     to servers in the SMS server-update program.
+ * AUTHOR:
+ *     Ken Raeburn (spook@athena.MIT.EDU),
+ *             MIT Project Athena/MIT Information Systems.
+ * DEFINED VALUES:
+ *     conn
+ *     update_info
+ *     sms_update_server
+ * VERSION HISTORY:
+ *     $Log$
+ *     Revision 1.1  1987-08-22 17:53:46  wesommer
+ *     Initial revision
+ *
+ */
+
+#include <stdio.h>
+#include <strings.h>
+#include "gdb.h"
+#include <sys/stat.h>
+#include <sys/file.h>
+#include <sys/param.h>
+#include "update.h"
+#include <errno.h>
+#include "sms_update_int.h"
+#include "smsu_int.h"
+#include <krb.h>
+
+extern char *malloc(), *error_message();
+extern int errno;
+
+/* XXX */
+#include "kludge.h"
+/* XXX */
+
+static char buf[BUFSIZ];
+
+CONNECTION conn;
+struct update_desc *info;
+
+static int code;
+
+/*
+ * FUNCTION:
+ *     initialize()
+ * DESCRIPTION:
+ *     Insures that various libraries have a chance to get
+ *     initialized.
+ * INPUT:
+ * OUTPUT:
+ * RETURN VALUE:
+ *     void
+ * SIDE EFFECTS:
+ *     Initializes GDB library and SMSU error table.
+ * PROBLEMS:
+ *
+ */
+static
+void
+initialize()
+{
+    static int initialized = 0;
+    if (!initialized) {
+       gdb_init();
+       init_smsU_err_tbl();
+       initialized++;
+    }
+}
+
+/*
+ * FUNCTION:
+ *     sms_update_server(info)
+ * DESCRIPTION:
+ *     Attempts to perform an update based on the information
+ *     contained in the data structure pointed to by "info".
+ *     Errors in performing the update are logged with the
+ *     sms_log* routines; the 'override' field may be updated
+ *     to cause updates to occur other than on the regular
+ *     schedule (generally to force an earlier retry).
+ * INPUT:
+ *     info->service_name
+ *             Name of service to be updated; used to find
+ *             the source data file in the SMS data directory.
+ *     info->host_name
+ *     info->target_path
+ *             Location to install the file.
+ *     info->enable
+ *             Must be non-zero.
+ *     info->instructions
+ *             Sequence of commands to execute on remote
+ *             machine to effect the installation.
+ * OUTPUT:
+ *     info->last_time
+ *             Set to the current time if the update was
+ *             attempted.
+ *     info->success
+ *             Set to non-zero if the update succeeded, set
+ *             to zero otherwise.
+ *     info->override
+ *             Set to -1 if the update succeeds, to (possibly)
+ *             some other value otherwise.
+ * RETURN VALUE:
+ *     int:
+ *             Error code, or zero if no error was detected
+ *             in the data supplied to this routine.
+ * SIDE EFFECTS:
+ *     May write information to logs.
+ * PROBLEMS:
+ *
+ */
+
+int
+sms_update_server(update_info, pathname)
+    struct update_desc *update_info;
+    char *pathname;
+{
+#define ASSERT(condition,amsg) \
+    if (!(condition)) { msg = amsg; code = 0; goto local_error; }
+#define NONNULL(str) \
+    (((str) != (char *)NULL) && ((size = strlen(str)) != 0))
+#define        IO_ERROR(msg) \
+    {log_priority=log_ERROR;com_err(whoami,connection_errno(conn),msg);goto io_error;}
+
+    char *service_address;
+    char *service_updated;
+    char *msg;
+    register char *cp;
+    STRING string_data, string2;
+    int size, num;
+    int fd = -1;
+    struct stat statb;
+    
+    /* variable initializations */
+    code = 0;
+    info = update_info;
+    service_updated = (char *)NULL;
+    STRING_DATA(string_data) = (char *)NULL;
+
+    /* pessimism */
+    info->success = 0;
+
+    /* some sanity checking of arguments while we build data */
+    strcpy(buf, "???:???");
+    ASSERT(NONNULL(info->host_name), "null host name");
+    /* XXX -- check length here */
+    strcpy(buf, info->host_name);
+    for (cp = buf; *cp; cp++)
+       ;
+    strcpy(cp, ":???");
+    ASSERT(NONNULL(info->service_name), "null service name");
+    /* XXX -- check length here */
+    strcpy(++cp, info->service_name);
+    service_updated = malloc(strlen(buf)+1);
+    /* XXX -- check allocation succeeded */
+    strcpy(service_updated, buf);
+    service_address = malloc(strlen(SERVICE_NAME)+strlen(info->host_name)+1);
+    if (!service_address) {
+       code = errno;
+       info->override = -1;
+       return(code);
+    }
+    strcpy(service_address, info->host_name);
+    strcat(service_address, ":");
+    strcat(service_address, SERVICE_NAME);
+    ASSERT(info->enable, "server is disabled");
+    ASSERT(NONNULL(info->target_path), "null target pathname");
+    ASSERT(size < MAXPATHLEN, "target pathname too long");
+    ASSERT(info->target_path[0] == '/', "non-absolute pathname supplied");
+    
+    initialize();
+    
+    string_alloc(&string2, BUFSIZ);
+    
+    sprintf(buf, "starting update for %s", service_updated);
+    sms_log_info(buf);
+    
+    fd = open(pathname, O_RDONLY, 0);
+    if (fd < 0) {
+       code = errno;
+       msg = pathname;
+       goto local_error;
+    }
+    if (fstat(fd, &statb)) {
+       code = errno;
+       close(fd); fd = -1;
+       strcat(buf, ": can't fstat:");
+       strcat(buf, error_message(code));
+       sms_log_error(buf);
+       goto error_exit;
+    }
+    size = statb.st_size;
+    
+    /* open connection */
+    conn = start_server_connection(service_address, 0);
+    if (!conn) {
+       com_err(whoami, 0, "can't connect to update %s", service_address);
+    connect_failed:
+       if (info->override<0 || info->override>INTERVAL_connection_failed)
+           info->override = INTERVAL_connection_failed;
+       return(0);
+    }
+    else if (connection_status(conn) == CON_STOPPED) {
+       com_err(whoami, connection_errno(conn), ": can't connect to update %s",
+               service_address);
+       goto connect_failed;
+    }
+    
+    
+    /* send authenticators */
+    code = send_auth();
+    if (code) {
+       sprintf(buf, "authorization attempt to %s failed: %s\n",
+               service_updated, error_message(code));
+       goto update_failed;
+    }
+    
+    /* send file over */
+    fd = open(pathname, O_RDONLY, 0);
+    if (fd < 0) {
+       code = errno;
+       msg = pathname;
+       goto local_error;
+    }
+    sprintf(STRING_DATA(string2), "XFER_002 %d %d %s",
+           size, checksum_fd(fd), info->target_path);
+    code = send_object(conn, (char *)&string2, STRING_T);
+    if (code)
+       IO_ERROR("%s: sending XFER_002 request");
+    code = receive_object(conn, (char *)&num, INTEGER_T);
+    if (code)
+       IO_ERROR("%s: getting reply from XFER_002 request");
+    if (num) {
+       sprintf(buf, "transfer request to %s (XFER_002) rejected: %s",
+               service_updated, error_message(num));
+    update_failed:
+       sms_log_error(buf);
+       /*
+        *         * if the update fails, something is probably wrong on
+        *         * the remote side; we'll have to let a maintainer
+        *         * take care of it.  don't bother trying again any sooner
+        *         * than INTERVAL_update_failed minutes
+        *         */
+    update_failed_1:
+       if (info->override < INTERVAL_update_failed && info->override != -1)
+           info->override = INTERVAL_update_failed;
+       goto do_quit;
+    }
+    /* send actual data */
+    code = send_file(pathname, size);
+    if (code)
+       goto update_failed_1;
+    string_free(&string_data);
+    close(fd);
+    
+    /* send instructions for installation */
+    strcpy(buf, "/tmp/sms-update.XXXXXX");
+    mktemp(buf);
+    fd = open(info->instructions, O_RDONLY, 0);
+    if (fd < 0) {
+       code = errno;
+       log_priority = log_ERROR;
+       com_err(whoami, code, ": can't open %s", info->instructions);
+       send_quit();
+       info->override = INTERVAL_local_error;
+       goto error_exit;
+    }
+    if (fstat(fd, &statb)) {
+       code = errno;
+       close(fd);
+       fd = -1;
+       log_priority = log_ERROR;
+       com_err(whoami, code, ": can't fstat %s", info->instructions);
+       goto error_exit;
+    }
+    sprintf(STRING_DATA(string2), "XFER_002 %d %d %s",
+           statb.st_size, checksum_fd(fd), buf);
+    code = send_object(conn, (char *)&string2, STRING_T);
+    if (code)
+       IO_ERROR("%s: sending request for transfer of instructions");
+    code = receive_object(conn, (char *)&num, INTEGER_T);
+    if (code)
+       IO_ERROR("%s: lost reply from installation script request");
+    if (num) {
+       com_err(whoami, num, ": transfer request rejected for %s", buf);
+       goto update_failed_1;
+    }
+    code = send_file(info->instructions, statb.st_size);
+    if (code)
+       goto update_failed_1;
+    
+    /* perform installation */
+    code = execute(buf);
+    if (code) {
+       sprintf(buf, "installation of %s failed: %s", service_updated,
+               error_message(code));
+       sms_log_error(buf);
+    }
+    
+    /* clear override timer and indicate success */
+    info->override = -1;
+    info->success = 1;
+
+    /* finished updates */
+do_quit:
+    send_quit();
+    
+    /* fall through */
+EGRESS:
+    code = 0;
+error_exit:
+    info->last_time = time((long *)0);
+    if (STRING_DATA(string2))
+       string_free(&string2);
+    if (STRING_DATA(string_data))
+       string_free(&string_data);
+    conn = sever_connection(conn);
+    return(code);
+    
+local_error:
+    log_priority = log_ERROR;
+    com_err(whoami, code, code ? ": %s" : "%s", msg);
+    return(SMSU_INTERNAL_ERROR);
+    
+io_error:
+    sms_log_error(buf);
+    if (info->override== -1 || info->override > INTERVAL_connection_lost)
+       info->override = INTERVAL_connection_lost;
+    goto EGRESS;
+    
+#undef IO_ERROR
+#undef NONNULL
+#undef ASSERT
+}
+
+static
+send_auth()
+{
+    KTEXT_ST ticket_st;
+    KTEXT ticket = &ticket_st;
+    STRING data;
+    register int code;
+    int response;
+    
+    code = get_sms_update_ticket(info->host_name, ticket);
+    if (code) {
+       return(code);
+    }
+    STRING_DATA(data) = "AUTH_001";
+    MAX_STRING_SIZE(data) = 9;
+    code = send_object(conn, (char *)&data, STRING_T);
+    if (code) {
+       return(connection_errno(conn));
+    }
+    code = receive_object(conn, (char *)&response, INTEGER_T);
+    if (code) {
+       return(connection_errno(conn));
+    }
+    if (response) {
+       return(response);
+    }
+    STRING_DATA(data) = (char *)ticket->dat;
+    MAX_STRING_SIZE(data) = ticket->length;
+    code = send_object(conn, (char *)&data, STRING_T);
+    if (code) {
+       return(connection_errno(conn));
+    }
+    code = receive_object(conn, (char *)&response, INTEGER_T);
+    if (code) {
+       return(connection_errno(conn));
+    }
+    if (response) {
+       return(response);
+    }
+    return(0);
+}
+
+static
+execute(path)
+    char *path;
+{
+    int response;
+    STRING data;
+    register int code;
+    
+    string_alloc(&data, BUFSIZ);
+    sprintf(STRING_DATA(data), "EXEC_002 %s", path);
+    code = send_object(conn, (char *)&data, STRING_T);
+    if (code)
+       return(connection_errno(conn));
+    code = receive_object(conn, (char *)&response, INTEGER_T);
+    if (code)
+       return(connection_errno(conn));
+    if (response)
+       return(response);
+    return(0);
+}
+
+send_quit()
+{
+    STRING str;
+    if (!conn)
+       return;
+    string_alloc(&str, 5);
+    (void) strcpy(STRING_DATA(str), "quit");
+    (void) send_object(conn, (char *)&str, STRING_T);
+    string_free(&str);
+}
diff --git a/update/exec_002.c b/update/exec_002.c
new file mode 100644 (file)
index 0000000..4f4d06c
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ *     $Source$
+ *     $Header$
+ */
+
+#ifndef lint
+static char *rcsid_exec_002_c = "$Header$";
+#endif lint
+
+#include <stdio.h>
+#include <sys/wait.h>
+#include "gdb.h"
+#include "update.h"
+#include "sms_update_int.h"
+#include "kludge.h"
+#include "smsu_int.h"
+
+extern CONNECTION conn;
+extern int code, errno;
+
+int
+exec_002(str)
+    char *str;
+{
+    union wait waitb;
+    int n, pid;
+
+    str += 8;
+    while (*str == ' ')
+       str++;
+    pid = fork();
+    switch (pid) {
+    case -1:
+       n = errno;
+       log_priority = log_ERROR;
+       com_err(whoami, errno, ": can't fork to run install script");
+       code = send_object(conn, (char *)&n, INTEGER_T);
+       if (code)
+           exit(1);
+       return;
+    case 0:
+       execlp(str, str, (char *)NULL);
+       n = errno;
+       log_priority = log_ERROR;
+       com_err(whoami, n, ": %s", str);
+       (void) send_object(conn, (char *)&n, INTEGER_T);
+       exit(1);
+    default:
+       do {
+           n = wait(&waitb);
+       } while (n != -1 && n != pid);
+       if (waitb.w_status) {
+           log_priority = log_ERROR;
+           com_err(whoami, 0, "child exited with status %d", waitb.w_status);
+           code = send_object(conn, (char *)&n, INTEGER_T);
+           if (code)
+               exit(1);
+       }
+       else {
+           code = send_ok();
+           if (code)
+               exit(1);
+       }
+    }
+}
diff --git a/update/get_file.c b/update/get_file.c
new file mode 100644 (file)
index 0000000..8495caa
--- /dev/null
@@ -0,0 +1,190 @@
+/*
+ *     $Source$
+ *     $Header$
+ */
+
+#ifndef lint
+static char *rcsid_get_file_c = "$Header$";
+#endif lint
+
+#include <stdio.h>
+#include "gdb.h"
+#include <ctype.h>
+#include <sys/param.h>
+#include <sys/file.h>
+#include "update.h"
+#include "smsu_int.h"
+#include "kludge.h"
+
+extern CONNECTION conn;
+char buf[BUFSIZ];
+
+extern int code, errno;
+
+extern int have_authorization, have_file, done;
+
+int get_block();
+
+/*
+ * get_file()
+ *
+ * arguments:
+ *     char *pathname
+ *             file to receive
+ *     int file_size
+ *             number of bytes
+ *     int checksum
+ *             linear checksum of bytes
+ *
+ * syntax:
+ * (initial protocol already done)
+ * <<< (int)code       (can we accept the file?)
+ * >>> (STRING)data
+ * <<< (int)code
+ * >>> (STRING)data
+ * <<< (int)code
+ * ...
+ * >>> (STRING)data    (last data block)
+ * <<< (int)code       (from read, write, checksum verify)
+ *
+ * returns:
+ *     int
+ *             0 for success, 1 for failure
+ *
+ * function:
+ *     perform initial preparations and receive file as
+ * a single string, storing it into <pathname>
+ *
+ */
+
+int
+get_file(pathname, file_size, checksum)
+    char *pathname;
+    int file_size;
+    int checksum;
+{
+    int fd, n_written;
+    int found_checksum;
+    
+    if (!have_authorization) {
+       reject_call(SMSU_NO_AUTH);
+       return(1);
+    }
+    if (done)                  /* re-initialize data */
+       initialize();
+    /* unlink old file */
+    (void) unlink(pathname);
+    /* open file descriptor */
+    fd = open(pathname, O_CREAT|O_EXCL|O_WRONLY, 0700);
+    if (fd == -1) {
+       code = errno;
+       sprintf(buf, "%s: creating file %s (get_file)",
+               error_message(code), pathname);
+       sms_log_error(buf);
+       report_error("reporting file creation error (get_file)");
+       return(1);
+    }
+    /* check to see if we've got the disk space */
+    n_written = 0;
+    while (n_written < file_size) {
+       register int n_wrote;
+       n_wrote = write(fd, buf, sizeof(buf));
+       if (n_wrote == -1) {
+           code = errno;
+           sprintf(buf, "%s: verifying free disk space for %s (get_file)",
+                   error_message(code), pathname);
+           sms_log_error(buf);
+           /* do all we can to free the space */
+           (void) unlink(pathname);
+           (void) ftruncate(fd, 0);
+           (void) close(fd);
+           report_error("reporting test-write error (get_file)");
+           return(1);
+       }
+       n_written += n_wrote;
+    }
+    lseek(fd, 0, L_SET);
+    if (send_ok())
+       lose("sending okay for file transfer (get_file)");
+    n_written = 0;
+    while (n_written < file_size && code == 0) {
+       int n_got = get_block(fd, file_size - n_written);
+       if (n_got == -1) {
+           /* get_block has already printed a message */
+           unlink(pathname);
+           return(1);
+       }
+       n_written += n_got;
+       if (n_written != file_size)
+           if (send_ok())
+               lose("receiving data");
+    }
+    if (code) {
+       code = connection_errno(conn);
+       report_error("reading file (get_file)");
+       return(1);
+    }
+    fsync(fd);
+    ftruncate(fd, file_size);
+    fsync(fd);
+    close(fd);
+    /* validate checksum */
+    fd = open(pathname, O_RDONLY, 0);
+    if (fd == -1) {
+       code = errno;
+       report_error("re-opening file for checksum verification");
+       return(1);
+    }
+    found_checksum = checksum_fd(fd);
+    if (checksum != found_checksum) {
+       code = SMSU_CHECKSUM;
+       com_err(whoami, code, ": expected = %d, found = %d",
+               checksum, found_checksum);
+       report_error("checksum error");
+       return(1);
+    }
+    close(fd);
+    /* send ack or nack */
+    have_file = 1;
+    if (send_ok()) {
+       code = connection_errno(conn);
+       (void) unlink(pathname);
+       lose("sending ok after file transfer (get_file)");
+       return(1);
+    }
+    return(0);
+}
+
+static int
+get_block(fd, max_size)
+    int fd;
+    int max_size;
+{
+    STRING data;
+    int n_read, n;
+
+    code = receive_object(conn, (char *)&data, STRING_T);
+    if (code) {
+       code = connection_errno(conn);
+       lose("receiving data file (get_file)");
+    }
+    n_read = MIN(MAX_STRING_SIZE(data), max_size);
+    n = 0;
+    while (n < n_read) {
+       register int n_wrote;
+       n_wrote = write(fd, STRING_DATA(data)+n,
+                       n_read-n);
+       if (n_wrote == -1) {
+           code = errno;
+           sprintf(buf, "%s: writing file (get_file)", error_message(code));
+           sms_log_error(buf);
+           string_free(&data);
+           report_error("reporting write error (get_file)");
+           close(fd);
+           return(-1);
+       }
+       n += n_wrote;
+    }
+    string_free(&data);
+    return(n);
+}
diff --git a/update/hostname.c b/update/hostname.c
new file mode 100644 (file)
index 0000000..09a9129
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ *     $Source$
+ *     $Header$
+ */
+
+#ifndef lint
+static char *rcsid_hostname_c = "$Header$";
+#endif lint
+
+/* PrincipalHostname, borrowed from rcmd.c in Kerberos code */
+#include <stdio.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <ctype.h>
+#include <strings.h>
+char *
+PrincipalHostname(alias)
+     char *alias;
+{
+     struct hostent *h;
+     char *phost = alias;
+     if ((h=gethostbyname(alias)) != (struct hostent *)NULL) {
+         char *p = index(h->h_name, '.');
+         if (p)
+              *p = NULL;
+         p = phost = h->h_name;
+         do {
+              if (isupper(*p))
+                   *p = tolower(*p);
+         } while (*p++);
+     }
+     return(phost);
+}
diff --git a/update/inst_001.c b/update/inst_001.c
new file mode 100644 (file)
index 0000000..195ce44
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ *     $Source$
+ *     $Header$
+ */
+
+#ifndef lint
+static char *rcsid_inst_001_c = "$Header$";
+#endif lint
+
+#include <stdio.h>
+#include "gdb.h"
+#include "kludge.h"
+#include "sms_update_int.h"
+
+STRING instructions = { 0, 0 };
+extern CONNECTION conn;
+extern int have_instructions;
+extern int code;
+
+/*
+ * instruction sequence transmission:
+ * syntax:
+ *     >>> (STRING) "inst_001"
+ *     <<< (int)0
+ *     >>> (STRING) instructions
+ *     <<< (int)0
+ */
+
+inst_001(str)
+     char *str;
+{
+     if (send_ok())
+         lose("sending okay for inst_001");
+     code = receive_object(conn, (char *)&instructions, STRING_T);
+     if (code) {
+         report_error("reporting failure to receive instructions");
+         return;
+     }
+     have_instructions = 1;
+     if (send_ok())
+         lose("sending okay after instructions");
+     dprintf(("got instructions: %s\n", STRING_DATA(instructions)));
+}
diff --git a/update/log.c b/update/log.c
new file mode 100644 (file)
index 0000000..7d352bb
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ *     $Source$
+ *     $Header$
+ */
+
+#ifndef lint
+static char *rcsid_log_c = "$Header$";
+#endif lint
+
+/*
+ * handle logging for dcm and update server
+ *
+ * this should eventually use zephyr
+ */
+
+/*
+ * define syslog for using syslog,
+ * default to tty
+ */
+#define use_syslog
+
+#include <stdio.h>
+#include "com_err.h"
+#include <varargs.h>
+#include "update.h"
+#include <krb.h>
+
+#ifdef use_syslog
+#include <syslog.h>
+#else
+#define use_tty
+#endif
+
+#ifdef use_syslog
+int syslog_prio[] = {
+    LOG_DEBUG,
+    LOG_INFO,
+    LOG_WARNING,
+    LOG_ERR
+};
+#endif
+int log_priority;
+
+sms_update_com_err_hook(whoami, code, fmt, args)
+    char *whoami;
+    int code;
+    char *fmt;
+    va_list args;
+{
+    char buf[BUFSIZ], *cp;
+    FILE _strbuf;
+
+#ifndef use_syslog
+    strcpy(buf, whoami);
+    for (cp = buf; *cp; cp++)
+       ;
+    *cp++ = ':';
+    *cp++ = ' ';
+#else
+    cp = buf;
+    *cp = '\0';
+#endif
+    if (code) {
+       strcpy(cp, error_message(code));
+       while (*cp)
+           cp++;
+    }
+    _strbuf._flag = _IOWRT+_IOSTRG;
+    _strbuf._ptr = cp;
+    _strbuf._cnt = BUFSIZ-(cp-buf);
+    _doprnt(fmt, args, &_strbuf);
+    putc('\0', &_strbuf);
+#ifdef use_syslog
+    syslog(syslog_prio[log_priority], "%s", buf);
+#endif
+#ifdef use_tty
+    puts(buf);
+#endif
+}
+
+sms_update_initialize()
+{
+    static int initialized = 0;
+    if (initialized)
+       return;
+#ifdef use_syslog
+    openlog(whoami, LOG_PID, LOG_DAEMON);
+#endif
+    (void) set_com_err_hook(sms_update_com_err_hook);
+    log_priority = log_INFO;
+    initialized = 1;
+}
diff --git a/update/send_file.c b/update/send_file.c
new file mode 100644 (file)
index 0000000..6772736
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ *     $Source$
+ *     $Header$
+ */
+
+#ifndef lint
+static char *rcsid_send_file_c = "$Header$";
+#endif lint
+
+#include <stdio.h>
+#include "com_err.h"
+#include "gdb.h"
+#include "smsu_int.h"
+#include <sys/file.h>
+#include "update.h"
+#include "sms_update_int.h"
+#include "kludge.h"
+
+extern CONNECTION conn;
+extern int errno;
+char buf[BUFSIZ];
+extern struct update_desc *info;
+
+/*
+ * syntax:
+ * (already sent) pathname file_size checksum
+ * <<< (int)code                       can we send it?
+ * >>> data
+ * <<< 0
+ * >>> data
+ * <<< 0
+ * ....
+ * >>> data                            (last block)
+ * <<< 0       (on final write, close, sync, checksum)
+ *
+ * returns:
+ *  0 on success
+ *  1 on error (file not found, etc)
+ */
+
+int
+send_file(pathname, n_to_send)
+    char *pathname;
+    int n_to_send;
+{
+    int n, fd, code;
+    STRING data;
+
+    fd = open(pathname, O_RDONLY, 0);
+    if (fd == -1) {
+       sprintf(buf, "%s: can't open %s for transmission",
+               error_message(errno), pathname);
+       sms_log_error(buf);
+       return(1);
+    }
+    code = receive_object(conn, (char *)&n, INTEGER_T);
+    if (code) {
+       com_err(whoami, connection_errno(conn), ": lost connection");
+       info->override = INTERVAL_connection_lost;
+       close(fd);
+       return(1);
+    }
+    if (n) {
+       log_priority = log_ERROR;
+       com_err(whoami, n, ": from remote server: can't update %s",
+               pathname);
+       info->override = INTERVAL_update_failed;
+       close(fd);
+       return(1);
+    }
+    string_alloc(&data, UPDATE_BUFSIZ);
+    while (n_to_send > 0) {
+#ifdef DEBUG
+       printf("n_to_send = %d\n", n_to_send);
+#endif /* DEBUG */
+       n = read(fd, STRING_DATA(data), UPDATE_BUFSIZ);
+       if (n < 0) {
+           sprintf(buf, "%s: reading %s for transmission",
+                   error_message(errno), pathname);
+           sms_log_error(buf);
+           close(fd);
+           return(1);
+       }
+       MAX_STRING_SIZE(data) = n;
+       code = send_object(conn, (char *)&data, STRING_T);
+       if (code) {
+           sprintf(buf, "%s: transmitting file %s",
+                   error_message(connection_errno(conn)), pathname);
+           sms_log_error(buf);
+           close(fd);
+           return(1);
+       }
+       n_to_send -= n;
+       code = receive_object(conn, (char *)&n, INTEGER_T);
+       if (code) {
+           sprintf(buf,
+                   "%s: awaiting ACK remote server during transmission of %s",
+                   error_message(connection_errno(conn)), pathname);
+           sms_log_error(buf);
+           close(fd);
+           return(1);
+       }
+       if (n) {
+           sprintf(buf, "%s: from remote server during transmission of %s",
+                   error_message(n), pathname);
+           sms_log_error(buf);
+           close(fd);
+           return(1);
+       }
+    }
+    close(fd);
+    return(0);
+}
diff --git a/update/ticket.c b/update/ticket.c
new file mode 100644 (file)
index 0000000..c27f373
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ *     $Source$
+ *     $Header$
+ */
+
+#ifndef lint
+static char *rcsid_ticket_c = "$Header$";
+#endif lint
+
+#include <stdio.h>
+#include <krb.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <strings.h>
+#include "sms_update_int.h"
+#include "com_err.h"
+#include "kludge.h"
+
+/* too bad we can't set the pathname easily */
+/*static char tkt_pathname[] = "/tmp/tkt:sms";*/
+static char *srvtab = SRVTAB; /* default == /etc/srvtab */
+static char realm[REALM_SZ];
+static char sms[] = "sms";
+
+extern char *tkt_string(), *PrincipalHostname();
+static int initialized = 0;
+
+#define init() { if (!initialized) { get_krbrlm(realm,0); initialized=1; }}
+
+int
+get_sms_update_ticket(host, ticket)
+     char *host;
+     KTEXT ticket;
+{
+     register int code;
+     register int pass;
+     char phost[BUFSIZ];
+
+     pass = 1;
+     init();
+     strcpy(phost, PrincipalHostname(host));
+ try_it:
+     code = mk_ap_req(ticket, sms, phost, realm, (long)0);
+     if (pass == 1) {
+        /* maybe we're taking too long? */
+        if ((code = get_sms_tgt()) != 0) {
+            /* don't need phost buffer any more */
+            sprintf(phost, "%s: can't get Kerberos TGT",
+                    error_message(code));
+            sms_log_error(phost);
+            return(code);
+        }
+        pass++;
+        goto try_it;
+     }
+     return(krb_err_frob(code));
+}
+
+int
+get_sms_tgt()
+{
+    register int code;
+    init();
+    code = get_svc_in_tkt(sms, "", realm, "krbtgt", realm, 1, srvtab);
+    if (!code)
+       return(0);
+    else
+       return(krb_err_frob(code));
+}
diff --git a/update/update_server.c b/update/update_server.c
new file mode 100644 (file)
index 0000000..0615463
--- /dev/null
@@ -0,0 +1,145 @@
+/*
+ *     $Source$
+ *     $Header$
+ */
+
+#ifndef lint
+static char *rcsid_dispatch_c = "$Header$";
+#endif lint
+
+#include <stdio.h>
+#include "gdb.h"
+#include <errno.h>
+#include <strings.h>
+#include "update.h"
+#include "sms_update_int.h"
+#include "smsu_int.h"
+
+/* XXX */
+#include "kludge.h"
+/* XXX */
+
+extern int auth_001(), exec_001(), inst_001(), xfer_001();
+extern int xfer_002(), exec_002();
+
+extern int sync_proc(), quit();
+
+extern void gdb_debug();
+extern int exit(), abort(), errno;
+
+CONNECTION conn;
+int code;
+char *whoami;
+
+#define send_int(n) \
+     (_send_int=(n),send_object(conn,(char *)&_send_int,INTEGER_T))
+int _send_int;
+
+struct _dt {
+     char *str;
+     int (*proc)();
+} dispatch_table[] = {
+     { "INST_001", inst_001 },
+     { "AUTH_001", auth_001 },
+     { "XFER_001", xfer_001 },
+     { "EXEC_001", exec_001 },
+     { "XFER_002", xfer_002 },
+     { "EXEC_002", exec_002 },
+     { "quit", quit },
+     { (char *)NULL, abort }
+};
+
+/*
+ * general scratch space -- useful for building
+ * error messages et al...
+ */
+char buf[BUFSIZ];
+err(code, fmt)
+     int code;
+     char *fmt;
+{
+     sprintf(buf, fmt, error_message(code));
+     sms_log_error(buf);
+}
+
+main(argc, argv)
+     int argc;
+     char **argv;
+{
+     STRING str;
+     struct _dt *d;
+
+#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);
+         exit(1);
+     }
+     /* well, sort of... */
+
+     umask(0077);
+     sms_update_initialize();
+     init_smsU_err_tbl();
+
+     /* wait for connection */
+     gdb_init();
+     conn = create_forking_server(SERVICE_NAME, 0);
+     if (!conn) {
+         err(errno, "%s: can't get connection");
+         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(SMSU_UNKNOWN_PROC);
+         if (code) {
+             err(connection_errno(conn), "%s: sending UNKNOWN_PROC");
+         }
+     ok:
+         string_free(&str);
+     }
+}
+
+int
+send_ok()
+{
+     static int zero = 0;
+     return((code = send_object(conn, (char *)&zero, INTEGER_T)));
+}
diff --git a/update/xfer_002.c b/update/xfer_002.c
new file mode 100644 (file)
index 0000000..209af2c
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ *     $Source$
+ *     $Header$
+ */
+
+#ifndef lint
+static char *rcsid_xfer_002_c = "$Header$";
+#endif lint
+
+#include <stdio.h>
+#include "gdb.h"
+#include <ctype.h>
+#include <sys/param.h>
+#include <sys/file.h>
+#include "smsu_int.h"
+#include "kludge.h"
+#include <strings.h>
+
+extern CONNECTION conn;
+char buf[BUFSIZ];
+
+extern int code, errno;
+
+extern int have_authorization, have_file, done;
+
+/*
+ *
+ * syntax:
+ * >>> (STRING)"xfer_002" filesize checksum pathname
+ * <<< (int)0
+ * >>> (STRING)data
+ * <<< (int)code
+ * >>> (STRING)data
+ * <<< (int)code
+ * ...
+ * >>> (STRING)data    (last data block)
+ * <<< (int)code       (from read, write, checksum verify)
+ *
+ * function:
+ *     perform initial preparations and receive file as
+ * a single string, storing it into <pathname>.sms_update.
+ *
+ * still to be done: file locking; perform transfers in pieces instead
+ * of all at once; use checksums
+ */
+
+int
+xfer_002(str)
+    char *str;
+{
+    int file_size;
+    int checksum;
+    char *pathname;
+    
+    str += 8;
+    while (*str == ' ')
+       str++;
+    if (!*str) {
+    failure:
+       reject_call(SMSU_BAD_ARGS);
+       return;
+    }
+    file_size = atoi(str);
+    while (isdigit(*str))
+       str++;
+    while (*str == ' ')
+       str++;
+    checksum = atoi(str);
+    while (isdigit(*str))
+       str++;
+    while (*str == ' ')
+       str++;
+    if (*str != '/')
+       goto failure;
+    pathname = str;
+    if (!have_authorization) {
+       reject_call(SMSU_NO_AUTH);
+       return;
+    }
+    if (done)                  /* re-initialize data */
+       initialize();
+    code = send_ok();
+    if (code)
+       lose("sending ok for file xfer (2)");
+    code = get_file(pathname, file_size, checksum);
+    if (!code) {
+       char buf[BUFSIZ];
+       have_file = 1;
+       strcpy(buf, "transferred file ");
+       strcat(buf, pathname);
+       sms_log_info(buf);
+    }
+    return;
+}
This page took 0.202472 seconds and 5 git commands to generate.