[comp.unix.microport] proposed fix for DST start date in SV/AT

hedrick@athos.rutgers.edu (Charles Hedrick) (04/05/88)

The following is only for the adventuresome:

Here's my proposed fix for the DST problem in SV/AT.  This is only
intended for SV/AT.  It presumably will not work on the 386 version.
(Judging by the Uport bbs system, the 386 version does have the
problem, but it's very unlikely that ctime.o will use the exact code
sequence that this program is looking for.)  This consists of a
program that will patch executables to change the start date of DST to
the first Sunday in April.  Unfortunately, it has to be called on
every executable on the system that uses the routine ctime, and there
are a lot of them.  So I also supply a shell script that will apply it
to a whole directory (actually any wildcard spec).  Typically I do
something like
  cd /bin
  fixdstdir *
It needs to be done on /bin, /usr/bin, /usr/lib, /usr/lib/uucp, /etc,
/lib/large, /lib/small, /lib/libp/large, and /lib/libp/small.  This is
on a system that has the base Unix and the development system.  I
haven't loaded the word-processing software, so I don't know what
additional things might need to be fixed up there.

Some caveats:
  - the C program searches for specific executable code sequences.
	It appears to work for 2.3.0-L, but could fail for other
	releases if ctime.o happens to compile differently.
  - in theory the program could trigger falsely, if some other
	piece of code happened to generate the right code sequence.
	I sort of doubt it.  The test is for loading 119 and
	then 303 into two specific registers (these are the day
	numbers for the start and end of DST), but you never know.
	So back up your system software being doing this.
  - when I was using this, the system crashed once with a general
	protection failure.  I presume there was just too much
	disk I/O going on.  So I suggest doing this when nobody is
	logged in who will get upset with a crash.
  - it will fail on any files that are currently in use (another
	argument for doing it single-user)
  - for some reason I got a wierd error message in /etc.  I
	ended up doing 
	    fixdstdir [a-g]*
	    fixdstdir [h-z]*
	which worked fine.
  - this program will change the last-write dates on any files
	that are updated.  This appears to be reasonable, but note
	that if you do incremental backups, your next backup will
	have lots of files in it. (I count about 70 files that
	get changed.)
  - if you have directories with your own software, e.g.
	/usr/local/bin, you'll want to do them as well.
  - the C program is quite inefficient.  It's the way it is because
	it was easy to design that way.  Debugging printout is
	still present.  Since it's only going to be run once, none
	of this matters.


#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	fixdst.c
#	fixdstdir
# This archive created: Tue Apr  5 06:06:08 1988
export PATH; PATH=/bin:$PATH
if test -f 'fixdst.c'
then
	echo shar: will not over-write existing file "'fixdst.c'"
else
cat << \SHAR_EOF > 'fixdst.c'
#include <stdio.h>

int buffer[16];
main (argc,argv)
  int argc;
  char **argv;
 {
  register int *pt;
  register int i;
  FILE *f;
  int target;
  long pos;

  f = fopen(argv[1],"r");
  if (f == NULL) {
	printf("can't open file\n");
	exit(2);
  }

  while (! feof(f)) {
	for (pt = buffer, i = 0; i < 15; pt++, i++)
		*pt = *(pt+1);
	buffer[15] = getw(f);
	if (buffer[0] == 0x46c7 && buffer[1] == 0x77fc &&
	    buffer[2] == 0xc700 && buffer[3] == 0xfa46 &&
	    buffer[4] == 0x012f) {
		for (i = 0; i < 16; i++)
			printf("%d ", buffer[i]);
		printf("\n");
		pos = ftell(f);
		f = fopen(argv[1],"r+");
		if (f == NULL) {
			printf("can't reopen file for update\n");
			exit(2);
		}
		fseek(f, pos-30, 0);
		putw(0x60fc, f);
		fclose(f);
		exit(0);
	}
	else if (buffer[0] == 0xfc46 && buffer[1] == 0x0077 &&
		 buffer[2] == 0x46c7 && buffer[3] == 0x2ffa) {
		for (i = 0; i < 16; i++)
			printf("%d ", buffer[i]);
		printf("\n");
		printf("\n");
		pos = ftell(f);
		f = fopen(argv[1],"r+");
		if (f == NULL) {
			printf("can't reopen file for update\n");
			exit(2);
		}
		fseek(f, pos-30, 0);
		putw(0x0060, f);
		fclose(f);
		exit(0);
	}
  }
exit(1);
}
SHAR_EOF
chmod +x 'fixdst.c'
fi # end of overwriting check
if test -f 'fixdstdir'
then
	echo shar: will not over-write existing file "'fixdstdir'"
else
cat << \SHAR_EOF > 'fixdstdir'
#!/bin/csh

foreach i ($*)
  fixdst $i
  if ($status == 0) then
    echo $i
  endif
end
SHAR_EOF
chmod +x 'fixdstdir'
fi # end of overwriting check
#	End of shell archive
exit 0