--- /dev/null
+/*
+ * $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:
+ */
--- /dev/null
+# 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
+
--- /dev/null
+#! /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$
+#
--- /dev/null
+mkdir /tmp/nfs.dir
+cd /tmp/nfs.dir
+tar xf /tmp/nfs
+chmod 775 /tmp/nfs.dir
+exit
+#
+# $Source$
+# $Header$
+#
--- /dev/null
+# $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
--- /dev/null
+/*
+ * $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';
+}
--- /dev/null
+/*
+ * $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 = ¶m_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:
+ */
--- /dev/null
+/*
+ * $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
--- /dev/null
+#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);
+}
--- /dev/null
+#
+# $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
--- /dev/null
+/*
+ * $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);
+}
--- /dev/null
+/*
+ * $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);
+}
--- /dev/null
+/*
+ * $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);
+}
--- /dev/null
+/*
+ * $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);
+ }
+ }
+}
--- /dev/null
+/*
+ * $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);
+}
--- /dev/null
+/*
+ * $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);
+}
--- /dev/null
+/*
+ * $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)));
+}
--- /dev/null
+/*
+ * $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;
+}
--- /dev/null
+/*
+ * $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);
+}
--- /dev/null
+/*
+ * $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));
+}
--- /dev/null
+/*
+ * $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)));
+}
--- /dev/null
+/*
+ * $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;
+}