/ u2 -- unix syslink: / name1, name2 jsr r0,arg2 / u.namep has 1st arg u.off has 2nd jsr r0,namei / find the i-number associated with the 1st / path name br error9 / cannot be found jsr r0,iget / get the i-node into core mov (sp)+,u.namep / u.namep points to 2nd name mov r1,-(sp) / put i-number of name1 on the stack (a link / to this file is to be created) mov cdev,-(sp) / put i-nodes device on the stack jsr r0,isdir / is it a directory jsr r0,namei / no, get i-number of name2 br .+4 / not found so r1-i-number of current directory / ii = i-number of current directory br error9 / file already exists., error cmp (sp)+,cdev / u.dirp now points to end of current directory bne error9 mov (sp),u.dirbuf / i-number of name1 into u.dirbuf jsr r0,mkdir / make directory entry for name2 in current /directory mov (sp)+,r1 / r1 has i-number of name1 jsr r0,iget / get i-node into core incb i.nlks / add 1 to its number of links jsr r0,setimod / set the i-node modified flag sysret9: jmp sysret / see 'sysret' routine error9: jmp error / see 'error' routine isdir: / if the i-node whose i-number is in r1 is a directory there is an / error unless super user made the call tstb u.uid / super user beq 1f / yes, don't care mov ii,-(sp) / put current i-number on stack jsr r0,iget / get i-node into core (i-number in r1) bit $40000,i.flgs / is it a directory bne error9 / yes, error mov (sp)+,r1 / no, put current i-number in r1 (ii) jsr r0,iget / get it back in 1: rts r0 sysunlink: / name - remove link name jsr r0,arg; u.namep / u.namep points to name jsr r0,namei / find the i-number associated with the path name br error9 / not found mov r1,-(sp) / put its i-number on the stack jsr r0,isdir / is it a directory clr u.dirbuf / no, clear the location that will get written / into the i-number portion of the entry sub $10.,u.off / move u.off back 1 directory entry jsr r0,wdir / free the directory entry mov (sp)+,r1 / get i-number back jsr r0,iget / get i-node jsr r0,setimod / set modified flag decb i.nlks / decrement the number of links bgt sysret9 / if this was not the last link to file return jsr r0,anyi / if it was, see if anyone has it open. Then / free contents of file and destroy it. br sysret9 mkdir: jsr r0,copyz; u.dirbuf+2; u.dirbuf+10. / clear this mov u.namep,r2 / r2 points to name of directory entry mov $u.dirbuf+2,r3 / r3 points to u.dirbuf+2 1: / put characters in the directory name in u.dirbuf+2 - u.dirbuf+10 movb (r2)+,r1 / move character in name to r1 beq 1f / if null, done cmp r1,$'/ / is it a "/"? beq error9 / yes, error cmp r3,$u.dirbuf+10. / have we reached the last slot for / a char? beq 1b / yes, go back movb r1,(r3)+ / no, put the char in the u.dirbuf br 1b / get next char 1: mov u.dirp,u.off / pointer to empty current directory slot to /u.off wdir: mov $u.dirbuf,u.base / u.base points to created file name mov $10.,u.count / u.count = 10 mov ii,r1 / r1 has i-number of current directory jsr r0,access; 1 / get i-node and set its file up for writing jsr r0,writei / write into directory rts r0 sysexec: jsr r0,arg2 / arg0 in u.namep,arg1 on top of stack jsr r0,namei / namei returns i-number of file named in / sysexec call in r1 br error9 jsr r0,iget / get i-node for file to be executed bit $20,i.flgs / is file executable beq error9 jsr r0,iopen / gets i-node for file with i-number given in / r1 (opens file) bit $40,i.flgs / test user id on execution bit beq 1f tstb u.uid / test user id beq 1f / super user movb i.uid,u.uid / put user id of owner of file as process / user id 1: mov (sp)+,r5 / r5 now contains address of list of pointers to / arguments to be passed mov $1,u.quit / u.quit determines handling of quits; / u.quit = 1 take quit mov $1,u.intr / u.intr determines handling of interrupts; / u.intr = 1 take interrupt mov $rtssym,30 / emt trap vector set to take system routine mov $fpsym,*10 / reserved instruction trap vector set to take / system routine mov $sstack,sp / stack space used during swapping mov r5,-(sp) / save arguments pointer on stack mov $ecore,r5 / r5 has end of core mov $core,r4 / r4 has start of users core mov r4,u.base / u.base has start of users core mov (sp),r2 / move arguments list pointer into r2 1: tst (r2)+ / argument char = "nul" bne 1b tst -(r2) / decrement r2 by 2; r2 has addr of end of arguent / pointer list 1: / move arguments to bottom of users core mov -(r2),r3 / (r3) last non zero argument ptr cmp r2,(sp) / is r2 = beginning of argument ptr list blo 1f / branch to 1f when all arguments are moved 2: tstb (r3)+ bne 2b / scan argument for \0 (nul) 2: movb -(r3),-(r5) / move argument char by char starting at / "ecore" cmp r3,(r2) / moved all characters in this argument bhi 2b / branch 2b if not mov r5,(r4)+ / move r5 into top of users core; r5 has / pointer to nth arg br 1b / string 1: clrb -(r5) bic $1,r5 / make r5 even, r5 points to last word of argument / strings mov $core,r2 1: / move argument pointers into core following argument strings cmp r2,r4 bhis 1f / branch to 1f when all pointers are moved mov (r2)+,-(r5) br 1b 1: sub $core,r4 / gives number of arguments *2 asr r4 / divide r4 by 2 to calculate the number of args stored mov r4,-(r5) / save number of arguments ahead of the argument / pointers clr -(r5) / popped into ps when rti in sysrele is executed mov $core,-(r5) / popped into pc when rti in sysrele / is executed mov r5,0f / load second copyz argument tst -(r5) / decrement r5 mov r5,u.r0 / sub $16.,r5 / skip 8 words mov r5,u.sp / assign user stack pointer value, effectively / zeroes all regs when sysrele is executed jsr r0,copyz; core; 0:0 / zero user's core clr u.break mov r5,sp / point sp to user's stack mov $14,u.count mov $u.off,u.fofp clr u.off / set offset in file to be read to zero jsr r0,readi / read in first six words of user's file, starting / at $core mov sp,r5 / put users stack address in r5 sub $core+40.,r5 / subtract $core +40, from r5 (leaves / number of words less 26 available for / program in user core mov r5,u.count / cmp core,$405 / br .+14 is first instruction if file is / standard a.out format bne 1f / branch, if not standard format mov core+2,r5 / put 2nd word of users program in r5; number of / bytes in program text sub $14,r5 / subtract 12 cmp r5,u.count / bgt 1f / branch if r5 greater than u.count mov r5,u.count jsr r0,readi / read in rest of user's program text add core+10,u.nread / add size of user data area to u.nread br 2f 1: jsr r0,readi / read in rest of file 2: mov u.nread,u.break / set users program break to end of / user code add $core+14,u.break / plus data area jsr r0,iclose / does nothing br sysret3 / return to core image at $core sysfstat: / set status of open file jsr r0,arg; u.off / put buffer address in u.off mov u.off,-(sp) / put buffer address on the stack mov *u.r0,r1 / put file descriptor in r1 jsr r0,getf / get the files i-number tst r1 / is it 0? beq error3 / yes, error bgt 1f / if i-number is negative (open for writing) neg r1 / make it positive, then branch br 1f / to 1f sysstat: / ; name of file; buffer - get files status jsr r0,arg2 / get the 2 arguments jsr r0,namei / get the i-number for the file br error3 / no such file, error 1: jsr r0,iget / get the i-node into core mov (sp)+,r3 / move u.off to r3 (points to buffer) mov r1,(r3)+ / put i-number in 1st word of buffer mov $inode,r2 / r2 points to i-node 1: mov (r2)+,(r3)+ / move rest of i-node to buffer cmp r2,$inode+32 / done? bne 1b / no, go back br sysret3 / return through sysret error3: jmp error / see 'error' routine sysret3: jmp sysret / see 'sysret' routine getf: / get the device number and the i-number of an open file cmp r1,$10. / user limited to 10 open files bhis error3 / u.fp is table of users open files, index in / fsp table movb u.fp(r1),r1 / r1 contains number of entry in fsp table beq 1f / if its zero return asl r1 asl r1 / multiply by 8 to get index into fsp table entry asl r1 add $fsp-4,r1 / r1 is pointing at the 3rd word in the fsp entry mov r1,u.fofp / save address of 3rd word in fsp entry in u.fofp mov -(r1),cdev / remove the device number cdev mov -(r1),r1 / and the i-number r1 1: rts r0 namei: mov u.cdir,r1 / put the i-number of current directory in r1 mov u.cdev,cdev / device number for users directory into cdev cmpb *u.namep,$'/ / is first char in file name a / bne 1f inc u.namep / go to next char mov rootdir,r1 / put i-number of rootdirectory in r1 clr cdev / clear device number 1: tstb *u.namep / is the character in file name a nul beq nig / yes, end of file name reached; branch to "nig" 1: jsr r0,access; 2 / get i-node with i-number r1 bit $40000,i.flgs / directory i-node? beq error3 / no, got an error mov i.size,u.dirp / put size of directory in u.dirp clr u.off / u.off is file offset used by user mov $u.off,u.fofp / u.fofp is a pointer to the offset portion / of fsp entry 2: mov $u.dirbuf,u.base / u.dirbuf holds a file name copied from / a directory mov $10.,u.count / u.count is byte count for reads and writes jsr r0,readi / read 10. bytes of file with i-number (r1); / i.e. read a directory entry tst u.nread ble nib / gives error return tst u.dirbuf / bne 3f / branch when active directory entry (i-node word in / entry non zero) mov u.off,u.dirp sub $10.,u.dirp br 2b 3: mov u.namep,r2 / u.namep points into a file name string mov $u.dirbuf+2,r3 / points to file name of directory entry 3: movb (r2)+,r4 / move a character from u.namep string into r4 beq 3f / if char is nul, then the last char in string has been / moved cmp r4,$'/ / is char a </> beq 3f cmp r3,$u.dirbuf+10. / have I checked all 8 bytes of file name beq 3b cmpb (r3)+,r4 / compare char in u.namep string to file name / char read from beq 3b / directory; branch if chars match br 2b / file names do not match go to next directory entry 3: cmp r3,$u.dirbuf+10. / if equal all 8 bytes were matched beq 3f tstb (r3)+ / bne 2b 3: mov r2,u.namep / u.namep points to char following a / or nul mov u.dirbuf,r1 / move i-node number in directory entry to r1 tst r4 / if r4 = 0 the end of file name reached, if r4 = </> / then go to next directory bne 1b nig: tst (r0)+ / gives non-error return nib: rts r0 syschdir: / makes the directory specified in the argument the current / directory jsr r0,arg; u.namep / u.namep points to path name jsr r0,namei / find its i-number br error3 jsr r0,access; 2 / get i-node into core bit $40000,i.flgs / is it a directory? beq error3 / no error mov r1,u.cdir / move i-number to users current directory mov cdev,u.cdev / move its device to users current device br sysret3 isown: jsr r0,arg2 / u.namep points to file name jsr r0,namei / get its i-number br error3 jsr r0,iget / get i-node into core tstb u.uid / super user? beq 1f / yes, branch cmpb i.uid,u.uid / no, is this the owner of the file beq 1f / yes jmp error3 / no, error 1: jsr r0,setimod / indicates i-node has been modified mov (sp)+,r2 / mode is put in r2 (u.off put on stack with / 2nd arg) rts r0 syschmod: / name; mode jsr r0,isown / get the i-node and check user status bit $40000,i.flgs / directory? beq 2f / no bic $60,r2 / su & ex / yes, clear set user id and / executable modes 2: movb r2,i.flgs / move remaining mode to i.flgs br 1f syschown: / name; owner jsr r0,isown / get the i-node and check user status tstb u.uid / super user beq 2f / yes, 2f bit $40,i.flgs / no, set userid on execution? bne 3f / yes error, could create Trojan Horses 2: movb r2,i.uid / no, put the new owners id in the i-node 1: jmp sysret4 3: jmp error arg: mov u.sp,r1 mov *18.(r1),*(r0)+ / put argument of system call into / argument of arg2 add $2,18.(r1) / point pc on stack to next system argument rts r0 arg2: jsr r0,arg; u.namep / u.namep contains value of first arg in / sys call jsr r0,arg; u.off / u.off contains value of second arg in / sys call mov r0,r1 / r0 points to calling routine mov (sp),r0 / put operation code back in r0 mov u.off,(sp) / put pointer to second argument on stack jmp (r1) / return to calling routine systime: / get time of year mov s.time,4(sp) mov s.time+2,2(sp) / put the present time on the stack br sysret4 sysstime: / set time tstb u.uid / is user the super user bne error4 / no, error mov 4(sp),s.time mov 2(sp),s.time+2 / set the system time br sysret4 sysbreak: / set the program break mov u.break,r1 / move users break point to r1 cmp r1,$core / is it the same or lower than core? blos 1f / yes, 1f cmp r1,sp / is it the same or higher than the stack? bhis 1f / yes, 1f bit $1,r1 / is it an odd address beq 2f / no, its even clrb (r1)+ / yes, make it even 2: / clear area between the break point and the stack cmp r1,sp / is it higher or same than the stack bhis 1f / yes, quit clr (r1)+ / clear word br 2b / go back 1: jsr r0,arg; u.break / put the "address" in u.break (set new / break point) br sysret4 / br sysret maknod: / r1 contains the mode bis $100000,r1 / allocate flag set mov r1,-(sp) / put mode on stack mov ii,r1 / move current i-number to r1 jsr r0,access; 1 / get its i-node into core mov r1,-(sp) / put i-number on stack mov $40.,r1 / r1 = 40 1: / scan for a free i-node (next 4 instructions) inc r1 / r1 = r1 + 1 jsr r0,imap / get byte address and bit position in inode map in / r2 & m bitb mq,(r2) / is the i-node active bne 1b / yes, try the next one bisb mq,(r2) / no, make it active (put a 1 in the bit map) jsr r0,iget / get i-node into core tst i.flgs / is i-node already allocated blt 1b / yes, look for another one mov r1,u.dirbuf / no, put i-number in u.dirbuf mov (sp)+,r1 / get current i-number back jsr r0,iget / get i-node in core jsr r0,mkdir / make a directory entry in current directory mov u.dirbuf,r1 / r1 = new inode number jsr r0,iget / get it into core jsr r0,copyz; inode; inode+32. / 0 it out mov (sp)+,i.flgs / fill flags movb u.uid,i.uid / user id movb $1,i.nlks / 1 link mov s.time,i.ctim / time created mov s.time+2,i.ctim+2 / time modified jsr r0,setimod / set modified flag rts r0 / return sysseek: / moves read write pointer in an fsp entry jsr r0,seektell / get proper value in u.count add u.base,u.count / add u.base to it mov u.count,*u.fofp / put result into r/w pointer br sysret4 systell: / get the r/w pointer jsr r0,seektell br error4 error4: jmp error / see 'error' routine sysret4: jmp sysret / see 'sysret' routine seektell: jsr r0,arg; u.base / puts offset in u.base jsr r0,arg; u.count / put ptr name in u.count mov *u.r0,r1 / file descriptor in r1 (index in u.fp list) jsr r0,getf / u.fofp points to 3rd word in fsp entry mov r1,-(sp) / r1 has i-number of file, put it on the stack beq error4 / if i-number is 0, not active so error bgt .+4 / if its positive jump neg r1 / if not make it positive jsr r0,iget / get its i-node into core cmp u.count,$1 / is ptr name =1 blt 2f / no its zero beq 1f / yes its 1 mov i.size,u.count / put number of bytes in file in u.count br 2f 1: / ptr name =1 mov *u.fofp,u.count / put offset in u.count 2: / ptrname =0 mov (sp)+,r1 / i-number on stack r1 rts r0 sysintr: / set interrupt handling jsr r0,arg; u.intr / put the argument in u.intr br 1f / go into quit routine sysquit: jsr r0,arg; u.quit / put argument in u.quit 1: mov u.ttyp,r1 / move pointer to control tty buffer to r1 beq sysret4 / return to user clrb 6(r1) / clear the interrupt character in the tty buffer br sysret4 / return to user syssetuid: / set process id movb *u.r0,r1 / move process id (number) to r1 cmpb r1,u.ruid / is it equal to the real user id number beq 1f / yes tstb u.uid / no, is current user the super user? bne error4 / no, error 1: movb r1,u.uid / put process id in u.uid movb r1,u.ruid / put process id in u.ruid br sysret4 / system return sysgetuid: movb u.ruid,*u.r0 / move the real user id to (u.r0) br sysret4 / systerm return, sysret fclose: mov r1,-(sp) / put r1 on the stack (it contains the index / to u.fp list) jsr r0,getf / r1 contains i-number, cdev has device =, u.fofp / points to 3rd word of fsp entry tst r1 / is inumber 0? beq 1f / yes, i-node not active so return tst (r0)+ / no, jump over error return mov r1,r2 / move i-number to r2 mov (sp),r1 / restore value of r1 from the stack which is / index to u.fp clrb u.fp(r1) / clear that entry in the u.fp list mov u.fofp,r1 / r1 points to 3rd word in fsp entry decb 2(r1) / decrement the number of processes that have opened / the file bge 1f / if all processes haven't closed the file, return mov r2,-(sp) / put r2 on the stack (i-number) clr -4(r1) / clear 1st word of fsp entry tstb 3(r1) / has this file been deleted beq 2f / no, branch mov r2,r1 / yes, put i-number back into r1 jsr r0,anyi / free all blocks related to i-number / check if file appears in fsp again 2: mov (sp)+,r1 / put i-number back into r1 jsr r0,iclose / check to see if its a special file 1: mov (sp)+,r1 / put index to u.fp back into r1 rts r0 anyi: / r1 contains an i-number mov $fsp,r2 / move start of fsp table to r2 1: cmp r1,(r2) / do i-numbers match? beq 1f / yes, 1f neg r1 / no complement r1 cmp r1,(r2) / do they match now? beq 1f / yes, transfer / i-numbers do not match add $8,r2 / no, bump to next entry in fsp table cmp r2,$fsp+[nfiles*8] / are we at last entry in the table blt 1b / no, check next entries i-number tst r1 / yes, no match bge .+4 neg r1 / make i-number positive jsr r0,imap / get address of allocation bit in the i-map in r2 bicb mq,(r2) / clear bit for i-node in the imap jsr r0,itrunc / free all blocks related to i-node clr i.flgs / clear all flags in the i-node rts r0 / return 1: / i-numbers match incb 7(r2) / increment upper byte of the 4th word rts r0 / in that fsp entry (deleted flag of fsp entry)