[comp.os.minix] Turbo C diff's for Minix 1.2; here they are ! Part 4 of 9

evas@euraiv1.UUCP (Eelco van Asperen) (10/02/87)

Here is part 4 of 9:						Eelco van Asperen.

# This is a shar archive.  Extract with sh, not csh.
# This archive ends with exit, so do not worry about trailing junk.
# --------------------------- cut here --------------------------
echo Extracting lib/qsort.c
sed 's/^X//' > lib/qsort.c << '+ END-OF-FILE 'lib/qsort.c
Xstatic	qsort1();
Xstatic	int (*qcompar)();
Xstatic	qexchange();
Xstatic	q3exchange();
X
Xqsort(base, nel, width, compar)
X	char *base;
X	int (*compar)();
X{
X	qcompar = compar;
X	qsort1(base, base + (nel - 1) * width, width);
X}
X
Xstatic
Xqsort1(a1, a2, width)
X	char *a1, *a2;
X	register int width;
X{
X	register char *left, *right;
X	register char *lefteq, *righteq;
X	int cmp;
X
X	for (;;) {
X		if (a2 <= a1) return;
X		left = a1;
X		right = a2;
X		lefteq = righteq = a1 + width * (((a2-a1)+width)/(2*width));
X		/*
X		   Pick an element in the middle of the array.
X		   We will collect the equals around it.
X		   "lefteq" and "righteq" indicate the left and right
X		   bounds of the equals respectively.
X		   Smaller elements end up left of it, larger elements end
X		   up right of it.
X		*/
Xagain:
X		while (left < lefteq && (cmp = (*qcompar)(left, lefteq)) <= 0) {
X			if (cmp < 0) {
X				/* leave it where it is */
X				left += width;
X			}
X			else {
X				/* equal, so exchange with the element to
X				   the left of the "equal"-interval.
X				*/
X				lefteq -= width;
X				qexchange(left, lefteq, width);
X			}
X		}
X		while (right > righteq) {
X			if ((cmp = (*qcompar)(right, righteq)) < 0) {
X				/* smaller, should go to left part
X				*/
X				if (left < lefteq) {
X					/* yes, we had a larger one at the
X					   left, so we can just exchange
X					*/
X					qexchange(left, right, width);
X					left += width;
X					right -= width;
X					goto again;
X				}
X				/* no more room at the left part, so we
X				   move the "equal-interval" one place to the
X				   right, and the smaller element to the
X				   left of it.
X				   This is best expressed as a three-way
X				   exchange.
X				*/
X				righteq += width;
X				q3exchange(left, righteq, right, width);
X				lefteq += width;
X				left = lefteq;
X			}
X			else if (cmp == 0) {
X				/* equal, so exchange with the element to
X				   the right of the "equal-interval"
X				*/
X				righteq += width;
X				qexchange(right, righteq, width);
X			}
X			else	/* just leave it */ right -= width;
X		}
X		if (left < lefteq) {
X			/* larger element to the left, but no more room,
X			   so move the "equal-interval" one place to the
X			   left, and the larger element to the right
X			   of it.
X			*/
X			lefteq -= width;
X			q3exchange(right, lefteq, left, width);
X			righteq -= width;
X			right = righteq;
X			goto again;
X		}
X		/* now sort the "smaller" part */
X		qsort1(a1, lefteq - width, width);
X		/* and now the larger, saving a subroutine call
X		   because of the for(;;)
X		*/
X		a1 = righteq + width;
X	}
X	/*NOTREACHED*/
X}
X
Xstatic
Xqexchange(p, q, n)
X	register char *p, *q;
X	register int n;
X{
X	register int c;
X
X	while (n-- > 0) {
X		c = *p;
X		*p++ = *q;
X		*q++ = c;
X	}
X}
X
Xstatic
Xq3exchange(p, q, r, n)
X	register char *p, *q, *r;
X	register int n;
X{
X	register int c;
X
X	while (n-- > 0) {
X		c = *p;
X		*p++ = *r;
X		*r++ = *q;
X		*q++ = c;
X	}
X}
+ END-OF-FILE lib/qsort.c
chmod u=rw,g=r,o=r lib/qsort.c
set `sum lib/qsort.c`
sum=$1
case $sum in
12232)	:;;
*)	echo 'Bad sum in 'lib/qsort.c >&2
esac
echo Extracting lib/regexp.dif
sed 's/^X//' > lib/regexp.dif << '+ END-OF-FILE 'lib/regexp.dif
X813c813
X<   extern char *strchr();
X---
X>   extern char *strchr(char *,char);
X1001a1002
X>   extern char *strchr(char *,char);
+ END-OF-FILE lib/regexp.dif
chmod u=rw,g=r,o=r lib/regexp.dif
set `sum lib/regexp.dif`
sum=$1
case $sum in
9408)	:;;
*)	echo 'Bad sum in 'lib/regexp.dif >&2
esac
echo Extracting lib/scanf.dif
sed 's/^X//' > lib/scanf.dif << '+ END-OF-FILE 'lib/scanf.dif
X3c3
X< #include <stdio.h>
X---
X> #include "stdio.h"
X74c74
X< static index(ch, string)
X---
X> static scnindex(ch, string)
X292c292
X< 				(index (ic, format) ^ reverse)) {
X---
X> 				(scnindex (ic, format) ^ reverse)) {
+ END-OF-FILE lib/scanf.dif
chmod u=rw,g=r,o=r lib/scanf.dif
set `sum lib/scanf.dif`
sum=$1
case $sum in
15960)	:;;
*)	echo 'Bad sum in 'lib/scanf.dif >&2
esac
echo Extracting lib/sendrec.asm
sed 's/^X//' > lib/sendrec.asm << '+ END-OF-FILE 'lib/sendrec.asm
Xtitle Send/Receive  -  C86 version; now for Turbo C [EVAS]
Xpage,132
X
Xinclude prologue.h
X
X	PUBLIC _send, _receive, _send_rec, _sendrec
X
X
X; The following definitions are from  ../h/com.h
X
X	__SEND	= 1
X	__RECEIVE= 2
X	__BOTH	= 3
X	__SYSVEC	= 32
X
X
X_TEXT	SEGMENT byte public 'CODE'
X
X	ASSUME	CS:_TEXT,DS:DGROUP
X
X;========================================================================
X;                           send and receive                              
X;========================================================================
X; send(), receive(), send_rec() all save bp, but destroy ax, bx, and cx.
X
X_send:	mov cx,__SEND		; send(dest, ptr)
X	jmp L0
X
X_receive:
X	mov cx,__RECEIVE		; receive(src, ptr)
X	jmp L0
X
X_sendrec:
X_send_rec:
X	mov cx,__BOTH		; send_rec(srcdest, ptr)
X	jmp L0
X
X  L0:	push bp			; save bp
X	mov bp,sp		; can't index off sp
X	mov ax,4[bp]		; ax = dest-src
X	mov bx,6[bp]		; bx = message pointer
X	int __SYSVEC		; trap to the kernel
X	pop bp			; restore bp
X	ret			; return
X
X_TEXT	ENDS
X
X	END	; end of assembly-file
+ END-OF-FILE lib/sendrec.asm
chmod u=rw,g=r,o=r lib/sendrec.asm
set `sum lib/sendrec.asm`
sum=$1
case $sum in
8152)	:;;
*)	echo 'Bad sum in 'lib/sendrec.asm >&2
esac
echo Extracting lib/setjmp.asm
sed 's/^X//' > lib/setjmp.asm << '+ END-OF-FILE 'lib/setjmp.asm
Xtitle setjmp/longjmp  -  C86 version
Xpage,132
X
Xinclude ..\lib\prologue.h
X
X
X	PUBLIC _setjmp, _longjmp
X	EXTRN _exit:near
X
X
X; 	struct jmpbuf {
X;		int bp;
X;	 	int sp;
X;	 	int ret-addr;
X; 	}
X
XJMPERR	EQU	-99		; call _exit(JMPERR) when jmp-error
X
X_TEXT	SEGMENT byte public 'CODE'
X
X	ASSUME	CS:_TEXT,DS:DGROUP
X
X_setjmp:
X	mov	bx,sp
X	mov	ax,[bx]		; ret-addr.
X	mov	bx,2[bx]	; addr of jmp-struct
X	mov	[bx],bp
X	mov	2[bx],sp
X	mov	4[bx],ax
X	xor	ax,ax
X	ret
X
X_longjmp:
X	push	bp
X	mov	bp,sp		; set new frame pointer to sp
X	mov	bx,4[bp]	; get address of jmp-structure
X	mov	ax,6[bp]	; get ret-code
X	or	ax,ax
X	jne	L1
X	inc	ax		; return code may not be zero
X    L1:	mov	sp,[bx+2]
X	mov	bp,[bx]
X	or	bp,bp		; test if last frame-pointer (error)
X	jne	L2		; else execute the longjmp
X	pop	bp
X	mov	ax,JMPERR
X	push	ax
X	call	_exit		; should never return
X	hlt
X    L2:	mov	bx,[bx+4]
X	pop	cx		; dump the bp we pushed upon entry
X	jmp	bx
X
X_TEXT	ENDS
X
X	END
+ END-OF-FILE lib/setjmp.asm
chmod u=rw,g=r,o=r lib/setjmp.asm
set `sum lib/setjmp.asm`
sum=$1
case $sum in
6019)	:;;
*)	echo 'Bad sum in 'lib/setjmp.asm >&2
esac
echo Extracting lib/system.c
sed 's/^X//' > lib/system.c << '+ END-OF-FILE 'lib/system.c
X#include	<stdio.h>
X
X#ifndef NIL
X#define NIL 0
X#endif
X
X
Xsystem( cmd )
Xchar *cmd;
X{
X    int retstat, procid, waitstat;
X
X    if( (procid = fork()) == 0 )
X    {
X        execl( "/bin/sh", "sh", "-c", cmd, NIL );
X        exit( 127 );
X    }
X
X    while( (waitstat = wait(&retstat)) != procid && waitstat != -1 )
X        ;
X    if (waitstat == -1)
X        retstat = -1;
X
X    return( retstat );
X}
+ END-OF-FILE lib/system.c
chmod u=rw,g=r,o=r lib/system.c
set `sum lib/system.c`
sum=$1
case $sum in
26514)	:;;
*)	echo 'Bad sum in 'lib/system.c >&2
esac
if test -f mlib
then	echo Removing   mlib
	rm mlib
fi
if test -d mlib
then	:
else	echo Creating   mlib
	mkdir mlib
fi
echo Extracting mlib/libfile
sed 's/^X//' > mlib/libfile << '+ END-OF-FILE 'mlib/libfile
X..\mlib\minix
Xy
X+cleanup +fgets +fprintf +system +puts +qsort +ctime &
X+fputs +fread +freopen +fclose +fopen +fseek &
X+fflush +ftell +fwrite +gets +getc +printdat &
X+setbuf +sprintf +doprintf +putc +scanf +ungetc &
X+strcmp +access +chdir +chmod +chown +chroot &
X+creat +dup +dup2 +exec +exit +fork +isatty &
X+fstat +getegid +getenv +geteuid +getgid +getpass &
X+close +getuid +ioctl +kill +link +lseek +malloc &
X+brk +brk2 +mknod +mktemp +getpid +mount +open &
X+perror +pipe +popen +prints +read +setgid +setuid &
X+sleep +alarm +pause +signal +catchsig +stat &
X+stime +strcat +strcpy +strlen +strncat +strncmp &
X+strncpy +sync +time +times +umask +umount +unlink &
X+utime +wait +stderr +write +syslib +call +atoi &
X+message +sendrec +printk +abort +itoa +stb &
X+abs +atol +ctype +index +bcopy +getutil &
X+rand +rindex +crypt +getgrent +getpwent +regexp &
X+regsub +setjmp +ldiv +lrsh +lxmul +scopy +spush
X..\mlib\minix.lst
+ END-OF-FILE mlib/libfile
chmod u=rw,g=r,o=r mlib/libfile
set `sum mlib/libfile`
sum=$1
case $sum in
14183)	:;;
*)	echo 'Bad sum in 'mlib/libfile >&2
esac
echo Extracting mlib/minix.lst
sed 's/^X//' > mlib/minix.lst << '+ END-OF-FILE 'mlib/minix.lst
XLDIV@.............ldiv              LLSH@.............lrsh
XLMOD@.............ldiv              LRSH@.............lrsh
XLUDIV@............ldiv              LUMOD@............ldiv
XLURSH@............lrsh              LXMUL@............lxmul
XSCOPY@............scopy             SPUSH@............spush
X_abort............abort             _abs..............abs
X_access...........access            _alarm............alarm
X_atoi.............atoi              _atol.............atol
X_bcopy............bcopy             _begsig...........catchsig
X_brk..............brk               _brk2.............brk2
X_Buf..............prints            _Bufp.............prints
X_callm1...........call              _callm3...........call
X_calloc...........malloc            _callx............call
X_chdir............chdir             _chmod............chmod
X_chown............chown             _chroot...........chroot
X_close............close             _creat............creat
X_crypt............crypt             _ctime............ctime
X_dup..............dup               _dup2.............dup2
X_encrypt..........crypt             _endgrent.........getgrent
X_endpwent.........getpwent          _errno............call
X_error_message....perror            _execl............exec
X_execle...........exec              _execn............exec
X_execv............exec              _execve...........exec
X_exit.............exit              _fclose...........fclose
X_fflush...........fflush            _fgets............fgets
X_fopen............fopen             _fork.............fork
X_fprintf..........fprintf           _fputs............fputs
X_fread............fread             _free.............malloc
X_freopen..........freopen           _fscanf...........scanf
X_fseek............fseek             _fstat............fstat
X_ftell............ftell             _fwrite...........fwrite
X_getc.............getc              _getegid..........getegid
X_getenv...........getenv            _geteuid..........geteuid
X_getgid...........getgid            _getgrent.........getgrent
X_getgrgid.........getgrent          _getgrnam.........getgrent
X_getpass..........getpass           _getpid...........getpid
X_getpwent.........getpwent          _getpwnam.........getpwent
X_getpwuid.........getpwent          _gets.............gets
X_getuid...........getuid            _get_base.........getutil
X_get_size.........getutil           _get_tot_mem......getutil
X_gmtime...........ctime             _index............index
X_ioctl............ioctl             _isatty...........isatty
X_itoa.............itoa              _kill.............kill
X_len..............call              _link.............link
X_localtime........ctime             _longjmp..........setjmp
X_lseek............lseek             _M................message
X_malloc...........malloc            _mknod............mknod
X_mktemp...........mktemp            _mount............mount
X_nullptr..........exec              _open.............open
X_pause............pause             _pclose...........popen
X_perror...........perror            _pipe.............pipe
X_popen............popen             _printf...........fprintf
X_printk...........printk            _prints...........prints
X_putc.............putc              _puts.............puts
X_qsort............qsort             _rand.............rand
X_read.............read              _realloc..........malloc
X_receive..........sendrec           _regcomp..........regexp
X_regexec..........regexp            _regsub...........regsub
X_rindex...........rindex            _sbrk.............brk
X_scanf............scanf             _send.............sendrec
X_sendrec..........sendrec           _send_rec.........sendrec
X_setbuf...........setbuf            _setgid...........setgid
X_setgrent.........getgrent          _setjmp...........setjmp
X_setkey...........crypt             _setpwent.........getpwent
X_setuid...........setuid            _signal...........signal
X_sleep............sleep             _sprintf..........sprintf
X_sscanf...........scanf             _stat.............stat
X_std_err..........stderr            _stime............stime
X_strcat...........strcat            _strcmp...........strcmp
X_strcpy...........strcpy            _strlen...........strlen
X_strncat..........strncat           _strncmp..........strncmp
X_strncpy..........strncpy           _sync.............sync
X_system...........system            _sys_abort........syslib
X_sys_copy.........syslib            _sys_exec.........syslib
X_sys_fork.........syslib            _sys_getsp........syslib
X_sys_newmap.......syslib            _sys_sig..........syslib
X_sys_times........syslib            _sys_xit..........syslib
X_tell_fs..........syslib            _time.............time
X_times............times             _tzset............ctime
X_umask............umask             _umount...........umount
X_ungetc...........ungetc            _unlink...........unlink
X_utime............utime             _vectab...........signal
X_wait.............wait              _write............write
X__cleanup.........cleanup           __ctype_..........ctype
X__doprintf........doprintf          __doscanf.........scanf
X__io_table........printdat          __stderr..........printdat
X__stdin...........printdat          __stdout..........printdat
X___daylight.......ctime             ___stb............stb
X___stdin..........printdat          ___stdout.........printdat
X___timezone.......ctime             ___tzname.........ctime
X
X
Xcleanup           Offset: 00000010H  Code and data size: 25H
X  __cleanup       
X
Xfgets             Offset: 00000110H  Code and data size: 40H
X  _fgets          
X
Xfprintf           Offset: 00000210H  Code and data size: 50H
X  _fprintf          _printf         
X
Xsystem            Offset: 00000360H  Code and data size: 6aH
X  _system         
X
Xputs              Offset: 000004c0H  Code and data size: 2dH
X  _puts           
X
Xqsort             Offset: 000005c0H  Code and data size: 1abH
X  _qsort          
X
Xctime             Offset: 00000860H  Code and data size: 3b6H
X  _ctime            _gmtime           _localtime        _tzset
X  ___daylight       ___timezone       ___tzname       
X
Xfputs             Offset: 00000e40H  Code and data size: 23H
X  _fputs          
X
Xfread             Offset: 00000f20H  Code and data size: 47H
X  _fread          
X
Xfreopen           Offset: 00001020H  Code and data size: 20H
X  _freopen        
X
Xfclose            Offset: 00001110H  Code and data size: 62H
X  _fclose         
X
Xfopen             Offset: 00001260H  Code and data size: f4H
X  _fopen          
X
Xfseek             Offset: 00001450H  Code and data size: 122H
X  _fseek          
X
Xfflush            Offset: 00001640H  Code and data size: 51H
X  _fflush         
X
Xftell             Offset: 00001750H  Code and data size: 7eH
X  _ftell          
X
Xfwrite            Offset: 00001880H  Code and data size: 45H
X  _fwrite         
X
Xgets              Offset: 00001980H  Code and data size: 3fH
X  _gets           
X
Xgetc              Offset: 00001a80H  Code and data size: 8fH
X  _getc           
X
Xprintdat          Offset: 00001bd0H  Code and data size: 846H
X  __io_table        __stderr          __stdin           __stdout
X  ___stdin          ___stdout       
X
Xsetbuf            Offset: 00001d40H  Code and data size: 40H
X  _setbuf         
X
Xsprintf           Offset: 00001e40H  Code and data size: 3fH
X  _sprintf        
X
Xdoprintf          Offset: 00001f50H  Code and data size: 461H
X  __doprintf      
X
Xputc              Offset: 00002530H  Code and data size: b3H
X  _putc           
X
Xscanf             Offset: 000026a0H  Code and data size: 51cH
X  _fscanf           _scanf            _sscanf           __doscanf
X
Xungetc            Offset: 00002e10H  Code and data size: 47H
X  _ungetc         
X
Xstrcmp            Offset: 00002f00H  Code and data size: 30H
X  _strcmp         
X
Xaccess            Offset: 00002fd0H  Code and data size: 18H
X  _access         
X
Xchdir             Offset: 000030a0H  Code and data size: 18H
X  _chdir          
X
Xchmod             Offset: 00003170H  Code and data size: 18H
X  _chmod          
X
Xchown             Offset: 00003240H  Code and data size: 2aH
X  _chown          
X
Xchroot            Offset: 00003330H  Code and data size: 18H
X  _chroot         
X
Xcreat             Offset: 00003400H  Code and data size: 18H
X  _creat          
X
Xdup               Offset: 000034d0H  Code and data size: 24H
X  _dup            
X
Xdup2              Offset: 000035b0H  Code and data size: 28H
X  _dup2           
X
Xexec              Offset: 00003690H  Code and data size: 207H
X  _execl            _execle           _execn            _execv
X  _execve           _nullptr        
X
Xexit              Offset: 000039c0H  Code and data size: 23H
X  _exit           
X
Xfork              Offset: 00003aa0H  Code and data size: 20H
X  _fork           
X
Xisatty            Offset: 00003b80H  Code and data size: 29H
X  _isatty         
X
Xfstat             Offset: 00003c60H  Code and data size: 2aH
X  _fstat          
X
Xgetegid           Offset: 00003d40H  Code and data size: 2fH
X  _getegid        
X
Xgetenv            Offset: 00003e30H  Code and data size: 47H
X  _getenv         
X
Xgeteuid           Offset: 00003f30H  Code and data size: 2fH
X  _geteuid        
X
Xgetgid            Offset: 00004020H  Code and data size: 26H
X  _getgid         
X
Xgetpass           Offset: 00004100H  Code and data size: 9eH
X  _getpass        
X
Xclose             Offset: 000042b0H  Code and data size: 24H
X  _close          
X
Xgetuid            Offset: 00004390H  Code and data size: 26H
X  _getuid         
X
Xioctl             Offset: 00004470H  Code and data size: 262H
X  _ioctl          
X
Xkill              Offset: 000048b0H  Code and data size: 23H
X  _kill           
X
Xlink              Offset: 00004990H  Code and data size: 30H
X  _link           
X
Xlseek             Offset: 00004a90H  Code and data size: 3fH
X  _lseek          
X
Xmalloc            Offset: 00004bb0H  Code and data size: 1f3H
X  _calloc           _free             _malloc           _realloc
X
Xbrk               Offset: 00004f00H  Code and data size: 5dH
X  _brk              _sbrk           
X
Xbrk2              Offset: 00005040H  Code and data size: 2dH
X  _brk2           
X
Xmknod             Offset: 00005130H  Code and data size: 2aH
X  _mknod          
X
Xmktemp            Offset: 00005220H  Code and data size: 40H
X  _mktemp         
X
Xgetpid            Offset: 00005320H  Code and data size: 20H
X  _getpid         
X
Xmount             Offset: 00005400H  Code and data size: 30H
X  _mount          
X
Xopen              Offset: 00005500H  Code and data size: 18H
X  _open           
X
Xperror            Offset: 000055d0H  Code and data size: 33eH
X  _error_message    _perror         
X
Xpipe              Offset: 00005b00H  Code and data size: 43H
X  _pipe           
X
Xpopen             Offset: 00005c10H  Code and data size: 1ecH
X  _pclose           _popen          
X
Xprints            Offset: 00005f70H  Code and data size: 198H
X  _Buf              _Bufp             _prints         
X
Xread              Offset: 000061a0H  Code and data size: 2aH
X  _read           
X
Xsetgid            Offset: 00006280H  Code and data size: 23H
X  _setgid         
X
Xsetuid            Offset: 00006360H  Code and data size: 23H
X  _setuid         
X
Xsleep             Offset: 00006440H  Code and data size: 20H
X  _sleep          
X
Xalarm             Offset: 00006550H  Code and data size: 23H
X  _alarm          
X
Xpause             Offset: 00006630H  Code and data size: 20H
X  _pause          
X
Xsignal            Offset: 00006710H  Code and data size: 7aH
X  _signal           _vectab         
X
Xcatchsig          Offset: 00006860H  Code and data size: 31H
X  _begsig         
X
Xstat              Offset: 000069a0H  Code and data size: 30H
X  _stat           
X
Xstime             Offset: 00006a90H  Code and data size: 21H
X  _stime          
X
Xstrcat            Offset: 00006b80H  Code and data size: 31H
X  _strcat         
X
Xstrcpy            Offset: 00006c50H  Code and data size: 29H
X  _strcpy         
X
Xstrlen            Offset: 00006d20H  Code and data size: 1aH
X  _strlen         
X
Xstrncat           Offset: 00006de0H  Code and data size: 34H
X  _strncat        
X
Xstrncmp           Offset: 00006ec0H  Code and data size: 35H
X  _strncmp        
X
Xstrncpy           Offset: 00006fa0H  Code and data size: 2cH
X  _strncpy        
X
Xsync              Offset: 00007070H  Code and data size: 21H
X  _sync           
X
Xtime              Offset: 00007150H  Code and data size: 70H
X  _time           
X
Xtimes             Offset: 000072a0H  Code and data size: 62H
X  _times          
X
Xumask             Offset: 000073f0H  Code and data size: 24H
X  _umask          
X
Xumount            Offset: 000074d0H  Code and data size: 18H
X  _umount         
X
Xunlink            Offset: 000075a0H  Code and data size: 18H
X  _unlink         
X
Xutime             Offset: 00007670H  Code and data size: 42H
X  _utime          
X
Xwait              Offset: 000077a0H  Code and data size: 31H
X  _wait           
X
Xstderr            Offset: 00007890H  Code and data size: 25H
X  _std_err        
X
Xwrite             Offset: 00007970H  Code and data size: 24H
X  _write          
X
Xsyslib            Offset: 00007a50H  Code and data size: 1bcH
X  _sys_abort        _sys_copy         _sys_exec         _sys_fork
X  _sys_getsp        _sys_newmap       _sys_sig          _sys_times
X  _sys_xit          _tell_fs        
X
Xcall              Offset: 00007e10H  Code and data size: d6H
X  _callm1           _callm3           _callx            _errno
X  _len            
X
Xatoi              Offset: 00008030H  Code and data size: 7cH
X  _atoi           
X
Xmessage           Offset: 00008170H  Code and data size: 18H
X  _M              
X
Xsendrec           Offset: 00008210H  Code and data size: 1fH
X  _receive          _send             _sendrec          _send_rec
X
Xprintk            Offset: 00008340H  Code and data size: 380H
X  _printk         
X
Xabort             Offset: 000087d0H  Code and data size: aH
X  _abort          
X
Xitoa              Offset: 00008890H  Code and data size: a0H
X  _itoa           
X
Xstb               Offset: 00008a20H  Code and data size: 20H
X  ___stb          
X
Xabs               Offset: 00008ae0H  Code and data size: 16H
X  _abs            
X
Xatol              Offset: 00008b90H  Code and data size: 8eH
X  _atol           
X
Xctype             Offset: 00008ce0H  Code and data size: 81H
X  __ctype_        
X
Xindex             Offset: 00008e00H  Code and data size: 1fH
X  _index          
X
Xbcopy             Offset: 00008ec0H  Code and data size: 21H
X  _bcopy          
X
Xgetutil           Offset: 00008f80H  Code and data size: 2dH
X  _get_base         _get_size         _get_tot_mem    
X
Xrand              Offset: 000090c0H  Code and data size: 31H
X  _rand           
X
Xrindex            Offset: 000091d0H  Code and data size: 21H
X  _rindex         
X
Xcrypt             Offset: 00009290H  Code and data size: 89cH
X  _crypt            _encrypt          _setkey         
X
Xgetgrent          Offset: 00009d00H  Code and data size: 695H
X  _endgrent         _getgrent         _getgrgid         _getgrnam
X  _setgrent       
X
Xgetpwent          Offset: 0000a120H  Code and data size: 6c5H
X  _endpwent         _getpwent         _getpwnam         _getpwuid
X  _setpwent       
X
Xregexp            Offset: 0000a590H  Code and data size: ef4H
X  _regcomp          _regexec        
X
Xregsub            Offset: 0000bae0H  Code and data size: 16dH
X  _regsub         
X
Xsetjmp            Offset: 0000bd40H  Code and data size: 38H
X  _longjmp          _setjmp         
X
Xldiv              Offset: 0000be70H  Code and data size: 86H
X  LDIV@             LMOD@             LUDIV@            LUMOD@
X
Xlrsh              Offset: 0000bf70H  Code and data size: 3aH
X  LLSH@             LRSH@             LURSH@          
X
Xlxmul             Offset: 0000c010H  Code and data size: 19H
X  LXMUL@          
X
Xscopy             Offset: 0000c070H  Code and data size: 2cH
X  SCOPY@          
X
Xspush             Offset: 0000c0e0H  Code and data size: 21H
X  SPUSH@          
+ END-OF-FILE mlib/minix.lst
chmod u=rw,g=r,o=r mlib/minix.lst
set `sum mlib/minix.lst`
sum=$1
case $sum in
62174)	:;;
*)	echo 'Bad sum in 'mlib/minix.lst >&2
esac
if test -f mm
then	echo Removing   mm
	rm mm
fi
if test -d mm
then	:
else	echo Creating   mm
	mkdir mm
fi
echo Extracting mm/exec.c
sed 's/^X//' > mm/exec.c << '+ END-OF-FILE 'mm/exec.c
X/* This file handles the EXEC system call.  It performs the work as follows:
X *    - see if the permissions allow the file to be executed
X *    - read the header and extract the sizes
X *    - fetch the initial args and environment from the user space
X *    - allocate the memory for the new process
X *    - copy the initial stack from MM to the process
X *    - read in the text and data segments and copy to the process
X *    - take care of setuid and setgid bits
X *    - fix up 'mproc' table
X *    - tell kernel about EXEC
X *
X *   The only entry point is do_exec.
X */
X
X#include "../h/const.h"
X#include "../h/type.h"
X#include "../h/callnr.h"
X#include "../h/error.h"
X#include "../h/stat.h"
X#include "const.h"
X#include "glo.h"
X#include "mproc.h"
X#include "param.h"
X
X#define MAGIC    0x04000301L	/* magic number with 2 bits masked off */
X#define SEP      0x00200000L	/* value for separate I & D */
X#define TEXTB              2	/* location of text size in header */
X#define DATAB              3	/* location of data size in header */
X#define BSSB               4	/* location of bss size in header */
X#define TOTB               6	/* location of total size in header */
X
X/*===========================================================================*
X *				do_exec					     *
X *===========================================================================*/
XPUBLIC int do_exec()
X{
X/* Perform the exece(name, argv, envp) call.  The user library builds a
X * complete stack image, including pointers, args, environ, etc.  The stack
X * is copied to a buffer inside MM, and then to the new core image.
X */
X
X  register struct mproc *rmp;
X  int m, r, fd, ft;
X  char mbuf[MAX_ISTACK_BYTES];	/* buffer for stack and zeroes */
X  union u {
X	char name_buf[MAX_PATH];	/* the name of the file to exec */
X	char zb[ZEROBUF_SIZE];	/* used to zero bss */
X  } u;
X  char *new_sp;
X  vir_bytes src, dst, text_bytes, data_bytes, bss_bytes, stk_bytes, vsp;
X  phys_bytes tot_bytes;		/* total space for program, including gap */
X  vir_clicks sc;
X  struct stat s_buf;
X
X  /* Do some validity checks. */
X  rmp = mp;
X  stk_bytes = (vir_bytes) stack_bytes;
X  if (stk_bytes > MAX_ISTACK_BYTES) return(ENOMEM);	/* stack too big */
X  if (exec_len <= 0 || exec_len > MAX_PATH) return(EINVAL);
X
X  /* Get the exec file name and see if the file is executable. */
X  src = (vir_bytes) exec_name;
X  dst = (vir_bytes) u.name_buf;
X  r = mem_copy(who, D, (long) src, MM_PROC_NR, D, (long) dst, (long) exec_len);
X  if (r != OK) return(r);	/* file name not in user data segment */
X  tell_fs(CHDIR, who, 0, 0);	/* temporarily switch to user's directory */
X  fd = allowed(u.name_buf, &s_buf, X_BIT);	/* is file executable? */
X  tell_fs(CHDIR, 0, 1, 0);	/* switch back to MM's own directory */
X  if (fd < 0) return(fd);	/* file was not executable */
X
X  /* Read the file header and extract the segment sizes. */
X  sc = (stk_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT;
X  m = read_header(fd, &ft, &text_bytes, &data_bytes, &bss_bytes, &tot_bytes,sc);
X  if (m < 0) {
X	close(fd);		/* something wrong with header */
X	return(ENOEXEC);
X  }
X
X  /* Fetch the stack from the user before destroying the old core image. */
X  src = (vir_bytes) stack_ptr;
X  dst = (vir_bytes) mbuf;
X  r = mem_copy(who, D, (long) src, MM_PROC_NR, D, (long) dst, (long) stk_bytes);
X  if (r != OK) {
X	close(fd);		/* can't fetch stack (e.g. bad virtual addr) */
X	return(EACCES);
X  }
X
X  /* Allocate new memory and release old memory.  Fix map and tell kernel. */
X  r = new_mem(text_bytes, data_bytes, bss_bytes, stk_bytes, tot_bytes,
X							u.zb, ZEROBUF_SIZE);
X  if (r != OK) {
X	close(fd);		/* insufficient core or program too big */
X	return(r);
X  }
X
X  /* Patch up stack and copy it from MM to new core image. */
X  vsp = (vir_bytes) rmp->mp_seg[S].mem_vir << CLICK_SHIFT;
X  patch_ptr(mbuf, vsp);
X  src = (vir_bytes) mbuf;
X  r = mem_copy(MM_PROC_NR, D, (long) src, who, D, (long) vsp, (long) stk_bytes);
X  if (r != OK) panic("do_exec stack copy err", NO_NUM);
X
X  /* Read in text and data segments. */
X  load_seg(fd, T, text_bytes);
X  load_seg(fd, D, data_bytes);
X  close(fd);			/* don't need exec file any more */
X
X  /* Take care of setuid/setgid bits. */
X  if (s_buf.st_mode & I_SET_UID_BIT) {
X	rmp->mp_effuid = s_buf.st_uid;
X	tell_fs(SETUID, who, (int) rmp->mp_realuid, (int) rmp->mp_effuid);
X  }
X  if (s_buf.st_mode & I_SET_GID_BIT) {
X	rmp->mp_effgid = s_buf.st_gid;
X	tell_fs(SETGID, who, (int) rmp->mp_realgid, (int) rmp->mp_effgid);
X  }
X
X  /* Fix up some 'mproc' fields and tell kernel that exec is done. */
X  rmp->mp_catch = 0;		/* reset all caught signals */
X  rmp->mp_flags &= ~SEPARATE;	/* turn off SEPARATE bit */
X  rmp->mp_flags |= ft;		/* turn it on for separate I & D files */
X  new_sp = (char *) vsp;
X  sys_exec(who, new_sp);
X  return(OK);
X}
X
X
X/*===========================================================================*
X *				read_header				     *
X *===========================================================================*/
XPRIVATE int read_header(fd, ft, text_bytes, data_bytes, bss_bytes, tot_bytes,sc)
Xint fd;				/* file descriptor for reading exec file */
Xint *ft;			/* place to return ft number */
Xvir_bytes *text_bytes;		/* place to return text size */
Xvir_bytes *data_bytes;		/* place to return initialized data size */
Xvir_bytes *bss_bytes;		/* place to return bss size */
Xphys_bytes *tot_bytes;		/* place to return total size */
Xvir_clicks sc;			/* stack size in clicks */
X{
X/* Read the header and extract the text, data, bss and total sizes from it. */
X
X  int m, ct;
X  vir_clicks tc, dc, s_vir, dvir;
X  phys_clicks totc;
X  long buf[HDR_SIZE/sizeof(long)];
X
X  /* Read the header and check the magic number.  The standard MINIX header 
X   * consists of 8 longs, as follows:
X   *	0: 0x04100301L (combined I & D space) or 0x04200301L (separate I & D)
X   *	1: 0x00000020L 
X   *	2: size of text segments in bytes
X   *	3: size of initialized data segment in bytes
X   *	4: size of bss in bytes
X   *	5: 0x00000000L
X   *	6: total memory allocated to program (text, data and stack, combined)
X   *	7: 0x00000000L
X   * The longs are represented low-order byte first and high-order byte last.
X   * The first byte of the header is always 0x01, followed by 0x03.
X   * The header is followed directly by the text and data segments, whose sizes
X   * are given in the header.
X   */
X
X  if (read(fd, buf, HDR_SIZE) != HDR_SIZE) return(ENOEXEC);
X  if ( (buf[0] & 0xFF0FFFFFL) != MAGIC) return(ENOEXEC);
X  *ft = (buf[0] & SEP ? SEPARATE : 0);	/* separate I & D or not */
X
X  /* Get text and data sizes. */
X  *text_bytes = (vir_bytes) buf[TEXTB];	/* text size in bytes */
X  *data_bytes = (vir_bytes) buf[DATAB];	/* data size in bytes */
X  if (*ft != SEPARATE) {
X	/* If I & D space is not separated, it is all considered data. Text=0 */
X	*data_bytes += *text_bytes;
X	*text_bytes = 0;
X  }
X
X  /* Get bss and total sizes. */
X  *bss_bytes = (vir_bytes) buf[BSSB];	/* bss size in bytes */
X  *tot_bytes = buf[TOTB];	/* total bytes to allocate for program */
X  if (*tot_bytes == 0) return(ENOEXEC);
X
X  /* Check to see if segment sizes are feasible. */
X  tc = (*text_bytes + CLICK_SHIFT - 1) >> CLICK_SHIFT;
X  dc = (*data_bytes + *bss_bytes + CLICK_SHIFT - 1) >> CLICK_SHIFT;
X  totc = (*tot_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT;
X  if (dc >= totc) return(ENOEXEC);	/* stack must be at least 1 click */
X  dvir = (*ft == SEPARATE ? 0 : tc);
X  s_vir = dvir + (totc - sc);
X  m = size_ok(*ft, tc, dc, sc, dvir, s_vir);
X  ct = buf[1] & BYTE;		/* header length */
X  if (ct > HDR_SIZE) read(fd, buf, ct - HDR_SIZE);	/* skip unused hdr */
X  return(m);
X}
X
X
X/*===========================================================================*
X *				new_mem					     *
X *===========================================================================*/
XPRIVATE int new_mem(text_bytes, data_bytes, bss_bytes,stk_bytes,tot_bytes,bf,zs)
Xvir_bytes text_bytes;		/* text segment size in bytes */
Xvir_bytes data_bytes;		/* size of initialized data in bytes */
Xvir_bytes bss_bytes;		/* size of bss in bytes */
Xvir_bytes stk_bytes;		/* size of initial stack segment in bytes */
Xphys_bytes tot_bytes;		/* total memory to allocate, including gap */
Xchar bf[ZEROBUF_SIZE];		/* buffer to use for zeroing data segment */
Xint zs;				/* true size of 'bf' */
X{
X/* Allocate new memory and release the old memory.  Change the map and report
X * the new map to the kernel.  Zero the new core image's bss, gap and stack.
X */
X
X  register struct mproc *rmp;
X  char *rzp;
X  vir_bytes vzb;
X  vir_clicks text_clicks, data_clicks, gap_clicks, stack_clicks, tot_clicks;
X  phys_clicks new_base, old_clicks;
X  phys_bytes bytes, base, count, bss_offset;
X  extern phys_clicks alloc_mem();
X  extern phys_clicks max_hole();
X
X  /* Acquire the new memory.  Each of the 4 parts: text, (data+bss), gap,
X   * and stack occupies an integral number of clicks, starting at click
X   * boundary.  The data and bss parts are run together with no space.
X   */
X
X  text_clicks = (text_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT;
X  data_clicks = (data_bytes + bss_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT;
X  stack_clicks = (stk_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT;
X  tot_clicks = (tot_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT;
X  gap_clicks = tot_clicks - data_clicks - stack_clicks;
X  if ( (int) gap_clicks < 0) return(ENOMEM);
X
X  /* Check to see if there is a hole big enough.  If so, we can risk first
X   * releasing the old core image before allocating the new one, since we
X   * know it will succeed.  If there is not enough, return failure.
X   */
X  if (text_clicks + tot_clicks > max_hole()) return(EAGAIN);
X
X  /* There is enough memory for the new core image.  Release the old one. */
X  rmp = mp;
X  old_clicks = (phys_clicks) rmp->mp_seg[S].mem_vir + rmp->mp_seg[S].mem_len;
X  if (rmp->mp_flags & SEPARATE) old_clicks += rmp->mp_seg[T].mem_len;
X  free_mem(rmp->mp_seg[T].mem_phys, old_clicks);	/* free the memory */
X
X  /* We have now passed the point of no return.  The old core image has been
X   * forever lost.  The call must go through now.  Set up and report new map.
X   */
X  new_base = alloc_mem(text_clicks + tot_clicks);	/* new core image */
X  if (new_base == NO_MEM) panic("MM hole list is inconsistent", NO_NUM);
X  rmp->mp_seg[T].mem_vir = 0;
X  rmp->mp_seg[T].mem_len = text_clicks;
X  rmp->mp_seg[T].mem_phys = new_base;
X  rmp->mp_seg[D].mem_vir = 0;
X  rmp->mp_seg[D].mem_len = data_clicks;
X  rmp->mp_seg[D].mem_phys = new_base + text_clicks;
X  rmp->mp_seg[S].mem_vir = rmp->mp_seg[D].mem_vir + data_clicks + gap_clicks;
X  rmp->mp_seg[S].mem_len = stack_clicks;
X  rmp->mp_seg[S].mem_phys = rmp->mp_seg[D].mem_phys + data_clicks + gap_clicks;
X  sys_newmap(who, rmp->mp_seg);	/* report new map to the kernel */
X
X  /* Zero the bss, gap, and stack segment. Start just above text.  */
X  for (rzp = &bf[0]; rzp < &bf[zs]; rzp++) *rzp = 0;	/* clear buffer */
X  bytes = (phys_bytes) (data_clicks + gap_clicks + stack_clicks) << CLICK_SHIFT;
X  vzb = (vir_bytes) bf;
X  base = (long) rmp->mp_seg[T].mem_phys + rmp->mp_seg[T].mem_len;
X  base = base << CLICK_SHIFT;
X  bss_offset = (data_bytes >> CLICK_SHIFT) << CLICK_SHIFT;
X  base += bss_offset;
X  bytes -= bss_offset;
X
X  while (bytes > 0) {
X	count = (long) MIN(bytes, (phys_bytes) zs);
X	if (mem_copy(MM_PROC_NR, D, (long) vzb, ABS, 0, base, count) != OK)
X		panic("new_mem can't zero", NO_NUM);
X	base += count;
X	bytes -= count;
X  }
X  return(OK);
X}
X
X
X/*===========================================================================*
X *				patch_ptr				     *
X *===========================================================================*/
XPRIVATE patch_ptr(stack, base)
Xchar stack[MAX_ISTACK_BYTES];	/* pointer to stack image within MM */
Xvir_bytes base;			/* virtual address of stack base inside user */
X{
X/* When doing an exec(name, argv, envp) call, the user builds up a stack
X * image with arg and env pointers relative to the start of the stack.  Now
X * these pointers must be relocated, since the stack is not positioned at
X * address 0 in the user's address space.
X */
X
X  char **ap, flag;
X  vir_bytes v;
X
X  flag = 0;			/* counts number of 0-pointers seen */
X  ap = (char **) stack;		/* points initially to 'nargs' */
X  ap++;				/* now points to argv[0] */
X  while (flag < 2) {
X	if (ap >= (char **) &stack[MAX_ISTACK_BYTES]) return;	/* too bad */
X	if (*ap != NIL_PTR) {
X		v = (vir_bytes) *ap;	/* v is relative pointer */
X		v += base;		/* relocate it */
X		*ap = (char *) v;	/* put it back */
X	} else {
X		flag++;
X	}
X	ap++;
X  }
X}
X
X
X/*===========================================================================*
X *				load_seg				     *
X *===========================================================================*/
XPRIVATE load_seg(fd, seg, seg_bytes)
Xint fd;				/* file descriptor to read from */
Xint seg;			/* T or D */
Xvir_bytes seg_bytes;		/* how big is the segment */
X{
X/* Read in text or data from the exec file and copy to the new core image.
X * This procedure is a little bit tricky.  The logical way to load a segment
X * would be to read it block by block and copy each block to the user space
X * one at a time.  This is too slow, so we do something dirty here, namely
X * send the user space and virtual address to the file system in the upper
X * 10 bits of the file descriptor, and pass it the user virtual address
X * instead of a MM address.  The file system copies the whole segment
X * directly to user space, bypassing MM completely.
X */
X
X  int new_fd, bytes;
X  char *ubuf_ptr;
X
X  if (seg_bytes == 0) return;	/* text size for combined I & D is 0 */
X  new_fd = (who << 8) | (seg << 6) | fd;
X  ubuf_ptr = (char *) (mp->mp_seg[seg].mem_vir << CLICK_SHIFT);
X  bytes = (int) seg_bytes;
X  read(new_fd, ubuf_ptr, bytes);
X}
+ END-OF-FILE mm/exec.c
chmod u=rw,g=r,o=r mm/exec.c
set `sum mm/exec.c`
sum=$1
case $sum in
29214)	:;;
*)	echo 'Bad sum in 'mm/exec.c >&2
esac
echo Extracting mm/forkexit.dif
sed 's/^X//' > mm/forkexit.dif << '+ END-OF-FILE 'mm/forkexit.dif
X27a28
X> PRIVATE process_group = 1;		/* next process grp to be assigned */
X81a83,85
X>   /* Set process group. */
X>   if (who == INIT_PROC_NR) rmc->mp_procgrp = process_group++;
X> 
X85c89
X<   rmc->mp_seg[S].mem_phys = rmc->mp_seg[D].mem_phys + 
X---
X>   rmc->mp_seg[S].mem_phys = rmc->mp_seg[D].mem_phys +
+ END-OF-FILE mm/forkexit.dif
chmod u=rw,g=r,o=r mm/forkexit.dif
set `sum mm/forkexit.dif`
sum=$1
case $sum in
23989)	:;;
*)	echo 'Bad sum in 'mm/forkexit.dif >&2
esac
echo Extracting mm/linklist
sed 's/^X//' > mm/linklist << '+ END-OF-FILE 'mm/linklist
X..\mlib\head+
Xmain+forkexit+break+exec+signal+
Xgetset+alloc+utility+table+putc
Xmm
Xmm
X..\mlib\minix
+ END-OF-FILE mm/linklist
chmod u=rw,g=r,o=r mm/linklist
set `sum mm/linklist`
sum=$1
case $sum in
9069)	:;;
*)	echo 'Bad sum in 'mm/linklist >&2
esac
echo Extracting mm/main.dif
sed 's/^X//' > mm/main.dif << '+ END-OF-FILE 'mm/main.dif
X147a148
X>   extern phys_clicks alloc_mem();
+ END-OF-FILE mm/main.dif
chmod u=rw,g=r,o=r mm/main.dif
set `sum mm/main.dif`
sum=$1
case $sum in
3571)	:;;
*)	echo 'Bad sum in 'mm/main.dif >&2
esac
echo Extracting mm/makefile
sed 's/^X//' > mm/makefile << '+ END-OF-FILE 'mm/makefile
XCC=tcc
XCCOPTS=-A -mt -I..\include -Di8088 -DTURBO -G -O -c
XLN=tlink
XLNOPTS=/x/d/c           # no map file; warn for duplicates; case is significant
X
XOBJS=	exec.obj alloc.obj break.obj forkexit.obj \
X	getset.obj main.obj putc.obj signal.obj table.obj utility.obj
X
X.c.obj:
X	$(CC) $(CCOPTS) $<
X
Xmm.out:	$(OBJS) ..\mlib\head.obj
X	$(LN) $(LNOPTS) @linklist
X	dos2out -d mm
X
Xall:	mm.out
X
Xfast:	*.c
X	$(CC) $(CCOPTS) *.c
X
+ END-OF-FILE mm/makefile
chmod u=rw,g=r,o=r mm/makefile
set `sum mm/makefile`
sum=$1
case $sum in
31461)	:;;
*)	echo 'Bad sum in 'mm/makefile >&2
esac
echo Extracting mm/signal.dif
sed 's/^X//' > mm/signal.dif << '+ END-OF-FILE 'mm/signal.dif
X102a103
X>   mp->mp_procgrp = rmp->mp_procgrp;	/* get process group right */
X116c117,118
X< 	id = (i+1 == SIGINT || i+1 == SIGQUIT ? 0 : proc_id);
X---
X> 	id= (i+1 == SIGINT || i+1 == SIGQUIT ? 0 : proc_id);
X> 	if (i + 1 == SIGKILL) id = -1;	/* simulate kill -1 9 */
X257c259
X<   m_sig.PROC_NR = proc_nr;
X---
X>   m_sig.CLOCK_PROC_NR = proc_nr;
X344c346,349
X<   if (rmp->mp_realuid != rmp->mp_effuid) return;
X---
X>   if (rmp->mp_realuid != rmp->mp_effuid) {
X> 	tell_fs(CHDIR, 0, 1, 0);	/* go back to MM's directory */
X> 	return;
X>   }
+ END-OF-FILE mm/signal.dif
chmod u=rw,g=r,o=r mm/signal.dif
set `sum mm/signal.dif`
sum=$1
case $sum in
37713)	:;;
*)	echo 'Bad sum in 'mm/signal.dif >&2
esac
exit 0