Xref: utzoo comp.mail.mush:834 comp.sources.bugs:2449 Path: utzoo!attcan!telly!eci386!woods From: woods@eci386.uucp (Greg A. Woods) Newsgroups: comp.mail.mush,comp.sources.bugs Subject: Re: Official Patch #2 for Mush 7.1 Summary: fixes for SysVr2.1 and older.... Keywords: patch mush sysVr2 Message-ID: <1990Jul18.021543.11830@eci386.uucp> Date: 18 Jul 90 02:15:43 GMT References: <10491@ogicse.ogc.edu> Reply-To: woods@eci386.UUCP (Greg A. Woods) Organization: Elegant Communications, Inc. Lines: 458 In article <10491@ogicse.ogc.edu> schaefer@ogicse.cse.ogi.edu (Barton E. Schaefer) writes: > This is Official Patch #2 for Mush 7.1. >[....] > Handling of "corrupted" spool mailboxes has been improved. The > size of the spool file is now correctly recorded on new mail checks, > which should reduce the frequency of corruption reports on systems > that rely on DOT_LOCKing. Unfortunately the code for DOT_LOCKing is still very closely tied to either BSD, or SysVr3.0+ (i.e SVID vol. 3). It will not work on earlier versions of SysV, i.e. those described by SVID vol. 1. According to the SVID vol. 1, setuid(BA_OS), there is no "saved-set-group-ID" capability in SysV. This means that either mush is made setuid root, or another locking mechanism is found. Our 3b1's (which run a bastardized version of SysVr2.1) also have smail2.5 and lmail2.6 installed, and since lmail2.6 uses a similar (and compatible) scheme to DOT_LOCKing, I've decided to write a pair of helper programmes which can be exec()'ed to lock and unlock the mailbox, instead of changing the locking scheme. I'll post these here, instead of just mailing them off to Bart for inclusion in the next patch. I do so in order to allow other SysVr2 sites to get running safely as soon as possible, as well as to solicit comment on other possible solutions (I think these are far from being the most desirable, or secure, solution). I'm also considering adding a couple of locking enhancements to lmail, specifically also have it lockf() the file if lockf() is available, and perhaps have it set the modes on mailboxes such that mandatory locking (if available) is enforced by lockf() on all read()'s and write()'s. Anyway, here it is. Note that a patch for "Makefile" is also included. Makefile was derived directly from makefile.sys.v, as the patch indicates. #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh 'Patch.sVr2' <<'END_OF_FILE' XIndex: Makefile X*** makefile.sys.v Sat May 12 22:16:31 1990 X--- Makefile Tue Jul 17 20:31:43 1990 X*************** X*** 27,33 X X # IRIX 3.2 systems (SGI Iris workstations) should add -DDIRECTORY to CFLAGS X X! CFLAGS= -O -DSYSV -DUSG -DCURSES -DREGCMP -DSIGRET=void X LDFLAGS= X LIBS= -lcurses -lPW X OTHERLIBS= X X--- 27,33 ----- X X # IRIX 3.2 systems (SGI Iris workstations) should add -DDIRECTORY to CFLAGS X X! CFLAGS= -O -DSYSV -DSYSVR2 -DUSG -DCURSES -DREGCMP -DSIGRET=int -DDIRECTORY -DSMAIL X LDFLAGS= X LIBS= -lcurses -lPW -ldirent -lmalloc X OTHERLIBS= X*************** X*** 29,35 X X CFLAGS= -O -DSYSV -DUSG -DCURSES -DREGCMP -DSIGRET=void X LDFLAGS= X! LIBS= -lcurses -lPW X OTHERLIBS= X # Use some variant of this one if you #define MMDF in config.h X #OTHERLIBS=/usr/src/mmdf/lib/libmmdf.a X X--- 29,35 ----- X X CFLAGS= -O -DSYSV -DSYSVR2 -DUSG -DCURSES -DREGCMP -DSIGRET=int -DDIRECTORY -DSMAIL X LDFLAGS= X! LIBS= -lcurses -lPW -ldirent -lmalloc X OTHERLIBS= X # Use some variant of this one if you #define MMDF in config.h X #OTHERLIBS=/usr/src/mmdf/lib/libmmdf.a X*************** X*** 35,40 X #OTHERLIBS=/usr/src/mmdf/lib/libmmdf.a X PROG= mush X X $(PROG): $(OBJS1) $(OBJS2) X @echo loading... X @$(CC) $(LDFLAGS) $(OBJS1) $(OBJS2) -o $(PROG) $(LIBS) $(OTHERLIBS) X X--- 35,44 ----- X #OTHERLIBS=/usr/src/mmdf/lib/libmmdf.a X PROG= mush X X+ #if SYSVR2 X+ all: $(PROG) dolock undolock X+ #endif SYSVR2 X+ X $(PROG): $(OBJS1) $(OBJS2) X $(CC) $(LDFLAGS) $(OBJS1) $(OBJS2) -o $(PROG) $(LIBS) $(OTHERLIBS) X X*************** X*** 36,43 X PROG= mush X X $(PROG): $(OBJS1) $(OBJS2) X! @echo loading... X! @$(CC) $(LDFLAGS) $(OBJS1) $(OBJS2) -o $(PROG) $(LIBS) $(OTHERLIBS) X X $(OBJS1): $(HDRS1) $(HDRS2) X $(OBJS2): $(HDRS1) $(HDRS2) $(HDRS3) X X--- 40,46 ----- X #endif SYSVR2 X X $(PROG): $(OBJS1) $(OBJS2) X! $(CC) $(LDFLAGS) $(OBJS1) $(OBJS2) -o $(PROG) $(LIBS) $(OTHERLIBS) X X #if SYSVR2 X dolock: dolock.o X*************** X*** 39,44 X @echo loading... X @$(CC) $(LDFLAGS) $(OBJS1) $(OBJS2) -o $(PROG) $(LIBS) $(OTHERLIBS) X X $(OBJS1): $(HDRS1) $(HDRS2) X $(OBJS2): $(HDRS1) $(HDRS2) $(HDRS3) X loop.o: version.h X X--- 42,55 ----- X $(PROG): $(OBJS1) $(OBJS2) X $(CC) $(LDFLAGS) $(OBJS1) $(OBJS2) -o $(PROG) $(LIBS) $(OTHERLIBS) X X+ #if SYSVR2 X+ dolock: dolock.o X+ $(CC) $(LDFLAGS) dolock.o -o dolock X+ X+ undolock: undolock.o X+ $(CC) $(LDFLAGS) undolock.o -o undolock X+ #endif SYSVR2 X+ X $(OBJS1): $(HDRS1) $(HDRS2) X $(OBJS2): $(HDRS1) $(HDRS2) $(HDRS3) X loop.o: version.h X*************** X*** 43,51 X $(OBJS2): $(HDRS1) $(HDRS2) $(HDRS3) X loop.o: version.h X X! BINDIR= /usr/local/bin X! LIBDIR= /usr/local/lib X! MRCDIR= /usr/lib X MANDIR= /usr/local/man/man1 X MANEXT= 1 X X X--- 54,62 ----- X $(OBJS2): $(HDRS1) $(HDRS2) $(HDRS3) X loop.o: version.h X X! BINDIR= /usr/lbin X! LIBDIR= /usr/lib/mush X! MRCDIR= /usr/lib/mush X MANDIR= /usr/local/man/man1 X MANEXT= 1 X X*************** X*** 51,60 X X install: mush X cp mush $(BINDIR) X! strip $(BINDIR)/mush X! chmod 0755 $(BINDIR)/mush X! cp mush.1 $(MANDIR)/mush.$(MANEXT) X! chmod 0644 $(MANDIR)/mush.$(MANEXT) X cp cmd_help $(LIBDIR) X chmod 0644 $(LIBDIR)/cmd_help X cp Mushrc $(MRCDIR)/Mushrc X X--- 62,76 ----- X X install: mush X cp mush $(BINDIR) X! # strip $(BINDIR)/mush X! #if SYSV X! chgrp mail $(BINDIR)/mush X! chmod 2755 $(BINDIR)/mush X! #else X! # chmod 755 $(BINDIR)/mush X! #endif X! # cp mush.1 $(MANDIR)/mush.$(MANEXT) X! # chmod 0644 $(MANDIR)/mush.$(MANEXT) X cp cmd_help $(LIBDIR) X chmod 0644 $(LIBDIR)/cmd_help X # cp Mushrc $(MRCDIR)/Mushrc X*************** X*** 57,61 X chmod 0644 $(MANDIR)/mush.$(MANEXT) X cp cmd_help $(LIBDIR) X chmod 0644 $(LIBDIR)/cmd_help X! cp Mushrc $(MRCDIR)/Mushrc X! chmod 0644 $(MRCDIR)/Mushrc X X--- 73,87 ----- X # chmod 0644 $(MANDIR)/mush.$(MANEXT) X cp cmd_help $(LIBDIR) X chmod 0644 $(LIBDIR)/cmd_help X! # cp Mushrc $(MRCDIR)/Mushrc X! # chmod 0644 $(MRCDIR)/Mushrc X! cp Mail.rc $(MRCDIR) X! chmod 0644 $(MRCDIR)/Mail.rc X! #if SYSVR2 X! cp dolock $(LIBDIR) X! chgrp mail $(LIBDIR)/dolock X! chmod 2755 $(LIBDIR)/dolock X! cp undolock $(LIBDIR) X! chgrp mail $(LIBDIR)/undolock X! chmod 2755 $(LIBDIR)/undolock X! #endif SYSVR2 XIndex: lock.c X*** Standard Input Wed Dec 31 19:00:00 1969 X--- lock.c Tue Jul 17 21:47:06 1990 X*************** X*** 26,31 **** X--- 26,36 ---- X char buf[MAXPATHLEN]; X int lockfd, cnt = 0; X SIGRET (*oldint)(), (*oldquit)(); X+ #ifdef SYSVR2 X+ int status; X+ int lockpid; X+ int waitid; X+ #endif X X #ifdef SYSV X /* Only the spoolfile needs to be dot_locked -- other files are X*************** X*** 35,40 **** X--- 40,70 ---- X if (strcmp(spoolfile, filename) != 0) X return 0; X #endif X+ #ifdef SYSVR2 /* no saved-group id on setgid pgms. */ X+ switch (lockpid = fork()) { X+ case 0: X+ execl(DO_DOT_LOCK, "mush-dolock", spoolfile, filename, (char *) NULL); X+ error("unable to exec(%s, %s)", DO_DOT_LOCK, filename); X+ status = -1; X+ break; X+ case -1: X+ error("unable to fork(dolock) for %s", filename); X+ status = -1; X+ break; X+ default: X+ while ((waitid = wait(&status)) == -1) X+ error("oops, wait() got EINTR"); X+ if (waitid != lockpid) X+ error("oops, wait() got %d, not %d", waitid, lockpid); X+ if (status != 0) { X+ errno = ((status & 0xf) == 0) ? (status >> 8) & 0xf : 0; X+ error("unable to lock %s (status = %d)", filename, status); X+ status = -1; X+ } X+ break; X+ } X+ return(status); X+ #else X #ifdef BSD X setregid(rgid, sgid); X #else /* BSD */ X*************** X*** 73,78 **** X--- 103,109 ---- X setgid(getgid()); X #endif /* BSD */ X return lockfd == -1? -1 : 0; X+ #endif /* SYSVR2 */ X } X #endif /* DOT_LOCK */ X X*************** X*** 200,209 **** X--- 231,270 ---- X { X #ifdef DOT_LOCK X char buf[MAXPATHLEN]; X+ #ifdef SYSVR2 X+ int status; X+ int lockpid; X+ int waitid; X+ #endif X #endif /* DOT_LOCK */ X X fflush(fp); X #ifdef DOT_LOCK X+ #ifdef SYSVR2 /* no saved-group id on setgid pgms. */ X+ X+ switch (lockpid = fork()) { X+ case 0: X+ execl(UNDO_DOT_LOCK, "mush-undolock", spoolfile, filename, (char *) NULL); X+ error("unable to exec(%s, %s)", UNDO_DOT_LOCK, filename); X+ status = -1; X+ break; X+ case -1: X+ error("unable to fork(undolock) for %s", filename); X+ status = -1; X+ break; X+ default: X+ while ((waitid = wait(&status)) == -1) X+ error("oops, wait() got EINTR"); X+ if (waitid != lockpid) X+ error("oops, wait() got %d, not %d", waitid, lockpid); X+ if (status != 0) { X+ errno = ((status & 0xf) == 0) ? (status >> 8) & 0xf : 0; X+ error("unable to unlock %s (status = %d)", filename, status); X+ status = -1; X+ } X+ break; X+ } X+ #else /* !SYSVR2 */ X #ifdef BSD X setregid(rgid, sgid); X #else X*************** X*** 222,227 **** X--- 283,289 ---- X #else X setgid(getgid()); X #endif /* BSD */ X+ #endif /* SYSVR2 */ X #endif /* DOT_LOCK */ X X (void) flock(fileno(fp), LOCK_UN); END_OF_FILE if test 6913 -ne `wc -c <'Patch.sVr2'`; then echo shar: \"'Patch.sVr2'\" unpacked with wrong size! fi # end of 'Patch.sVr2' fi if test -f 'dolock.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'dolock.c'\" else echo shar: Extracting \"'dolock.c'\" \(996 characters\) sed "s/^X//" >'dolock.c' <<'END_OF_FILE' X#include X#include X#include X#include "config.h" X Xint Xmain(argc, argv) X int argc; X char *argv[]; X{ X char *filename; X char *spoolfile; X char buf[BUFSIZ]; X int lockfd; X int cnt = 0; X X if (strcmp(argv[0], "mush-dolock") != 0 || argc != 3) { X fprintf(stderr, "dolock: usage error.\n"); X exit(0); X } X spoolfile = argv[1]; X filename = argv[2]; X /* X * Only the spoolfile needs to be dot_locked X */ X if (strcmp(spoolfile, filename) != 0) X exit(0); X (void) sprintf(buf, "%s.lock", filename); X while ((lockfd = open(buf, O_CREAT|O_WRONLY|O_EXCL, 0444)) == -1) { X if (errno != EEXIST) { X fprintf(stderr, "%s: unable to lock %s", argv[0], filename); X perror(""); X break; X } X if (cnt++ == 0) X printf("%s already locked, waiting", filename); X else { X putchar('.'); X fflush(stdout); X } X sleep(1); X /* SIGINT will terminate the process, with non-zero status */ X } X if (lockfd == -1) X exit(errno); X if (cnt) X puts("done."); X (void) close(lockfd); X exit(0); X} END_OF_FILE if test 996 -ne `wc -c <'dolock.c'`; then echo shar: \"'dolock.c'\" unpacked with wrong size! fi # end of 'dolock.c' fi if test -f 'undolock.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'undolock.c'\" else echo shar: Extracting \"'undolock.c'\" \(579 characters\) sed "s/^X//" >'undolock.c' <<'END_OF_FILE' X#include X#include X#include X#include "config.h" X Xint Xmain(argc, argv) X int argc; X char *argv[]; X{ X char *filename; X char *spoolfile; X char buf[BUFSIZ]; X int cnt = 0; X X if (strcmp(argv[0], "mush-undolock") != 0 || argc != 3) { X fprintf(stderr, "undolock: usage error\n"); X exit(0); X } X spoolfile = argv[1]; X filename = argv[2]; X if (strcmp(spoolfile, filename) == 0) { X (void) sprintf(buf, "%s.lock", filename); X if (unlink(buf) == -1) { X fprintf(stderr, "undolock: can't unlink(%s) - ", buf); X perror(""); X exit(errno); X } X } X exit(0); X} END_OF_FILE if test 579 -ne `wc -c <'undolock.c'`; then echo shar: \"'undolock.c'\" unpacked with wrong size! fi # end of 'undolock.c' fi echo shar: End of shell archive. exit 0 -- Greg A. Woods woods@{eci386,gate,robohack,ontmoh,tmsoft}.UUCP +1-416-443-1734 [h] +1-416-595-5425 [w] VE3-TCP Toronto, Ontario CANADA