[comp.os.minix] How to get patch running

bishop@ecsvax.UUCP (Alan Bishop) (05/10/87)

(hope you don't get two copies of this.)

Here's how I got patch to work under MINIX:
The version I had was 2.0, 86/09/17, patchlevel 0.  I have no idea
what the current version is, but this is what was on my local UNIX
system.  I don't think there should be any great differences.

Out of the files in MANIFEST, you do not need Configure (takes
far too long to get going), Makefile.SH (not really needed.  I
didn't play with it much.), and config.H (although it might be nice.)

The config.h (generated by Configure) that I use is at the end of this
article, along with some other patch stuff.

In common.h, find the section that #includes stdio.h and that kind of
stuff.  Replace it with:

#include <stdio.h>
#include <stat.h>
#include <signal.h>
#include "/usr/src/include/ctype.h"
#include "assert.h"

#define toupper(c)	((c)-'a'+'A')

Change the ctype.h line to whereever you keep the include directory
that comes on the distribution disks.  Better yet, put it somewhere useful.
Find a copy of assert.h somewhere.  All it does it define a macro "assert"
that prints a diagnostic message if something goes wrong.  If you want,
just add a function

assert() {}

somewhere instead of doing this, or use a define to ignore them altogether.

Next, a change or two have to be made to patch.c.
Find the routine do_ed_script().  Replace it by something like:

void
do_ed_script()

{
	printf("MINIX does not support ed scripts.\n");
	exit(1);
}

or whatever you want.  This was previously forked up a copy of /bin/ed,
which wouldn't have done too much good under MINIX.  It also used a
few library routines that MINIX doesn't have.

Also, a change can be made to util.c.

On lines 37 and 38, change "dev_t" to "short int" and "ino_t" to
"unsigned short".

Delete lines 142-152 (#if defined... to #else) and line 221 (#endif lint).

In ask (a few lines down, actually between 142 and 221) change

    write(2, buf, strlen(buf));
    if (tty2) {				/* might be redirected to a file */
	r = read(2, buf, sizeof buf);
    }
    else if (isatty(1)) {		/* this may be new file output */
	Fflush(stdout);
	write(1, buf, strlen(buf));
	r = read(1, buf, sizeof buf);
    }
    else if ((ttyfd = open("/dev/tty", 2)) >= 0 && isatty(ttyfd)) {

to
    write(2, buf, strlen(buf));
    if ((ttyfd = open("/dev/tty", 2)) >= 0 && isatty(ttyfd)) {

Reading from stderr and stdout produces errors.  Doesn't appear that
they're open for input.

Finally, we have to change all of the %ld to %D.
They're all in patch.c and pch.c.
You can use ^R in mined.

Now, it's time to compile the stuff.  Just use cc -c.  If you're
running low on /tmp space or memory, you might have to use -F or -T.
(with the period).  Doesn't really matter, just get the .s file.

cc -c version.c
cc -c util.c
cc -c inp.c (expect warnings)
cc -c pch.c (expect warnings)
cc -c patch.c (expect warnings)

Now, it's time to implement a system() replacement, which it doesn't
look like MINIX has.  Enclosed at the end of this article is system.c
It's quite possible that patch will never use it.  I didn't look.
system.c should work anyway.

cc -c system.c

Now, MINIX has a bug in the library routine putc.  I posted a fix
a few days ago.  Here it is again.  Fix it before going any further.

---fix---
Problem: putc does not return the character passed to it.

Fix: in putc.c (from lib/libsrc.a) change the line which reads
	return(0);
to
	return(ch & CMASK);
---end---

I've had trouble using ar to replace a module.  Has anyone else?
Anyway, we'll ignore the issue for right now.  Use "ar p" to extract
putc.c from libsrc.a, make the change, and 

cc -c putc.c

Now we're ready to compile.

This will eat HUGE amounts of /tmp space.  Removing /lib/* won't
do it.  You may have to execute asld -T. ... instead or remove
/lib/*, /bin/sh, etc.  

cc -o patch inp.s version.s util.s pch.s patch.s system.s putc.s

This should do it.  I've used my copy to apply patches from the net and
some test patches.  I bet they were all new-style context diffs, though.
If there are any problems with using other diff styles, let me know.

Due to limited memory, it will occassionally
run out of memory (I've only had this happen while reversing patches.)
It continues intelligently even after that.  Won't it be nice when we have
the updated asld and can split up code and data?

If there are any problems with this procedure, please let me know.
I've done this twice, so this should work.

here are the files.
-------
config.h
-------

/* config.h
 * This file was produced by running the Configure script.
 * Feel free to modify any of this as the need arises.
 */


/*#undef	EUNICE		/* no file linking? */
/*#undef	VMS		/* other assorted ickies? */

/*#undef	index strchr	/* cultural */
/*#undef	rindex strrchr	/*  differences? */

/*#define	void int	/* is void to be avoided? */
#define CANVARARG

/* How many register declarations are paid attention to? */
/* AGB: I really don't know about this.  It shouldn't matter
   a great deal. */

#define Reg1 		register
#define Reg2 		register
#define Reg3 		register
#define Reg4 		/**/
#define Reg5 		/**/
#define Reg6 		/**/
#define Reg7 		/**/
#define Reg8 		/**/
#define Reg9 		/**/
#define Reg10 		/**/
#define Reg11 		/**/
#define Reg12 		/**/
#define Reg13 		/**/
#define Reg14 		/**/
#define Reg15 		/**/
#define Reg16 		/**/

------
system.c
------

/* Doesn't deal with spawning interactive subprocesses */
/* THIS IS ONLY TO KEEP PATCH HAPPY. */
/* (if you don't look at this, you'll be happier) */
/* It may not even work properly.  Testing consisted of
   system("date").  Note: it also always returns sucess.
*/

system(input)
char *input;

{

	int	files[2]; /* Input and output for pipes */
	int	pid; /* pid of forked process */
	char	eoln = '\n'; /* Just a carriage return */
	int	status; /* Status of subprocess */

	if (pipe(files) < 0) {
		return(127); /* Only allowable error return */
	}
	else {
		if ((pid = fork()) == 0) {

/* Child process */
			close(files[1]);
			close(0);
			dup(files[0]);
			close(files[0]);

			execl("/bin/sh", "sh", 0);
			exit(1);
		}
		else {
			
/* Main process */
			close(files[0]);
			write(files[1], input, strlen(input));
			write(files[1], &eoln, 1);
			close(files[1]);

			wait();
		}
		return(0);
	}
}
------

alan

--
				Alan Bishop
			     ...!decvax!mcnc!ecsvax!bishop
				bishop@ecsvax.{UUCP,BITNET}

lwall@sdcrdcf.UUCP (05/12/87)

The current patch level of patch is 8.  Some of the patches are fairly
important.  Here's an index:

1: Backwards scan for place to insert hunk can give up prematurely
2: patch can report a new-style context diff when it is really an old one
3: new-style diff with deletion can trigger spurious assertion failure
4: Certain long hunks are not dynamically allocated correctly
5: Patch misplaces patches when fuzz factor > 0
6: New-style context diffs can cause double call to free().
7: Some mangled patches result in misleading diagnostics.
8: Short replacement part causes spurious "Out of sync" message.

If you are missing patches they can be obtained from me:

Larry Wall
{allegra,burdvax,cbosgd,hplabs,ihnp4,sdcsvax}!sdcrdcf!lwall

If you send a mail message of the following form it will greatly speed
processing:

 Subject: Command
 @SH mailpatch PATH patch 2.0 LIST

where PATH is a return path FROM ME TO YOU in bang notation, and LIST
is the number of one or more patches you need, separated by spaces,
commas, and/or hyphens.  Saying 35- says everything from 35 to the end.

Larry Wall
{allegra,burdvax,cbosgd,hplabs,ihnp4,sdcsvax}!sdcrdcf!lwall