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