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