diff --git a/src/alt/chrm.s b/src/alt/chrm.s new file mode 100644 index 0000000..acbf8e0 --- /dev/null +++ b/src/alt/chrm.s @@ -0,0 +1,41 @@ +" Alternative chrm: chrm file [file file ...] +" +" Unlink the named files + + lac 017777 " Go to the argc + tad d1 " Skip past the argc + dac 2f " Save pointing at cmd name, we will skip later + lac 017777 i " How many arguments do we have? + sad d4 + sys exit " None, so exit + tad dm4 " Subtract 1 + dac 017777 i " and save in the argc + +1: + lac 017777 i " Any arguments left? + sna + sys exit " No, exit the program + tad dm4 " Subtract 4 from the argc and update it + dac 017777 i + lac 2f " Move up to the next filename + tad d4 + dac 2f " and save it in the unlink arg + sys unlink; 2:0 " Unlink the file + sma + jmp 1b " Loop back if the unlink was OK, or issue err + lac 2b " Copy the filename pointer below + dac 2f + lac d1 " Write the filename on stdout + sys write; 2:0; 4 + lac d1 + sys write; 1f; 2 " Write " ?\n" on stdout + jmp 1b " and loop back + +1: + 040077;012000 " String literal " ?\n" +dd: +
;040040;040040;040040 " Filename dd +d1: 1 +d4: 4 +d5: 5 +dm4: -4 diff --git a/src/alt/init.s b/src/alt/init.s new file mode 100644 index 0000000..0c897fc --- /dev/null +++ b/src/alt/init.s @@ -0,0 +1,292 @@ +" init + + -1 + sys intrp + jms init1 " Fork the first child connected to ttyin/ttyout + jms init2 " Fork the second child connected to keyboard/display +1: + sys rmes " Wait for a child to exit + sad pid1 + jmp 1f " It was child 1, so jump to 1f and restart it + sad pid2 + jms init2 " It was child 2, so restart it + jmp 1 " and loop back. XXX: weird use of 1: not 1b. I don't like it! +1: + jms init1 + jmp 1 " Weird use of 1: not 1b. I don't like it! + +init1: 0 + sys fork " Fork a child process + jmp 1f + sys open; ttyin; 0 " which opens the ttyin + sys open; ttyout; 1 " and ttyout files, and + jmp login " waits for a user to log in +1: + dac pid1 " Parent stores childs pid in pid1 + jmp init1 i " and returns + +init2: 0 + sys fork " Fork a child process + jmp 1f + sys open; keybd; 0 " which opens the keyboard + sys open; displ; 1 " and display files, and + jmp login " waits for a user to log in +1: + dac pid2 " Parent stores childs pid in pid2 + jmp init2 i " and returns + +login: + -1 + sys intrp + sys open; password; 0 " Open the passwd file + lac d1 + sys write; m1; m1s " Write "\nlogin:" on the terminal + jms rline " and read the user's username + lac ebufp + dac tal +1: + jms gline + law ibuf-1 + dac 8 + law obuf-1 + dac 9 +2: + lac 8 i + sad o12 + lac o72 + sad 9 i + skp + jmp 1b + sad o72 + skp + jmp 2b + lac 9 i + sad o72 + jmp 1f + -1 + tad 9 + dac 9 + lac d1 + sys write; m3; m3s " Write "password: " on the terminal + jms rline " and read the user's password + law ibuf-1 + dac 8 +2: + lac 8 i + sad o12 + lac o72 + sad 9 i + skp + jmp error + sad o72 + skp + jmp 2b +1: + dzm nchar + law dir-1 + dac 8 +1: + lac 9 i + sad o72 + jmp 1f + dac char + lac nchar + sza + jmp 2f + lac char + alss 9 + xor o40 + dac 8 i + dac nchar + jmp 1b +2: + lac 8 + dac nchar + lac nchar i + and o777000 + xor char + dac nchar i + dzm nchar + jmp 1b +1: + dzm nchar +1: + lac 9 i + sad o12 + jmp 2f + tad om60 + lmq + lac nchar + cll; als 3 + omq + dac nchar + jmp 1b +2: + lac nchar + sys setuid " Set the user's user-id + sys chdir; dotdot " Change into the root directory (out of system) + sys chdir; dir " and then the user's home directory + + lac d2 " Close file descriptor 2 + sys close + sys open; sh; 0 " Open the shell executable file (we get fd 2) + sma + jmp 1f + sys link; system; sh; sh + spa + jmp error + sys open; sh; 0 + spa + jmp error + sys unlink; sh +1: + law 017700 " Copy the code at the boot label below + dac 9 " up to location 017700 + law boot-1 + dac 8 +1: + lac 8 i + dac 9 i + sza " Stop copying when we hit the 0 marker + jmp 1b + jmp 017701 " and then jump to the code + +boot: + lac d2 " Load fd2 (the opened shell file) + lmq " Save the fd into MQ + sys read; 4096; 07700 " Read 4,032 words into locations 4096 onwards + " leaving the top 64 words for this boot code. + lacq " Get the fd back and close the file + sys close + jmp 4096 " and jump to the beginning of that executable + 0 " 0 marks the end of the code, used by the copy routine above + +rline: 0 + law ibuf-1 " Store ibuf pointer in location 8 + dac 8 +1: + cla " Set fd 0 (stdin) + sys read; char; 1 " Read in one character from the device + lac char + lrss 9 " Get it and shift down 9 bits + sad o100 + jmp rline+1 " Skip if it is an '@' character + sad o43 + jmp 2f " Jump below if it was a '#' character + dac 8 i " Store the character in the buffer + sad o12 + jmp rline i " Return from routine if it was a newline + jmp 1b " otherwise loop back to get another one +2: + law ibuf-1 " # handling. Do nothing if at start of the buffer (?) + sad 8 + jmp 1b " and loop back + -1 + tad 8 " Otherwise, move the pointer in location 8 back one + dac 8 + jmp 1b " and loop back + +gline: 0 + law obuf-1 + dac 8 " Save obuf pointer into location 8 +1: + jms gchar " Get a character + dac 8 i " Save it into the obuf buffer + sad o12 + jmp gline i " Return when we hit a newline + jmp 1b " or loop back to read another one + +gchar: 0 + lac tal " Load the pointer to the next word in the buffer + sad ebufp + jmp 1f " We've reached the end of the buffer, so read more + ral " Move the msb into the link register + lac tal i " Load the word from the buffer + snl " Skip if this is the second character in the word + lrss 9 " It's the first char, shift down the top character + and o777 " Keep the lowest 7 bits + lmq + lac tal + add o400000 " Flip the msb and save into tal + dac tal + lacq + sna + jmp gchar+1 " Skip a NUL character and read another one + jmp gchar i " Return the character from the subroutine +1: + lac bufp + dac tal +1: + dzm tal i + isz tal " ??? this section + lac tal + sad ebufp + skp + jmp 1b + lac bufp + dac tal + lac d2 " Buffer is empty, read another 64 characters + sys read; buf; 64 + sna + jmp error " No characters were read in + jmp gchar+1 " Loop back to get one character + +error: + lac d1 + sys write; m2; m2s " Write "?\n" on stdout + lac d1 + sys smes " and exit the child process + sys exit + +m1: + 012; ;;;;;;<: 040 +m3s = .-m3 +dotdot: + <..>;040040;040040;040040 +dir: + 040040;040040;040040;040040 + +ttyin: + ;;;;; 040040 +keybd: + ;;; +displ: + ;;;; 040040;040040;040040 +system: + ;;; 040040 +password: + ;;; + +d1: 1 +o43: 043 +o100: 0100 +o400000: 0400000 +d2: 2 +o12: 012 +om60: -060 +d3: 3 +ebufp: buf+64 +bufp: buf +o777: 0777 +o777000: 0777000 +o40: 040 +o72: 072 + +ibuf: .=.+100 +obuf: .=.+100 +tal: .=.+1 +buf: .=.+64 +char: .=.+1 +nchar: .=.+1 +pid1: .=.+1 +pid2: .=.+1 diff --git a/src/alt/s2.s b/src/alt/s2.s new file mode 100644 index 0000000..9c1f70d --- /dev/null +++ b/src/alt/s2.s @@ -0,0 +1,356 @@ +"** 01-s1.pdf page 7 +" s2 + + " file status (stat) system call + " AC/ pointer to status (inode) buffer + i-num (13 words) + " sys status; dir_name_ptr; file_name_ptr + " NO_DD version: sys status; file_name_ptr +.status: + jms arg " fetch file name pointer + dac .+3 + lac u.cdir " get current working directory + jms namei; .. " look up file + jms error " not found: return error + jms iget " read file inode + lac u.ac " get user buffer pointer + and o17777 " truncate to 13 bits + jms betwen; o10000; o17762 " is user memory (but not last 14 wds)? + jms error " no: error + dac .+3 " save as copy destination + jms copy; inode; ..; 12 " copy inode to user buffer + lac d.i " copy i-num from last dnode read ?? + dac 9 i " save thru index 9 (pre-increment) ?? + jmp okexit + + " capture display? +.capt: + lac u.ac " get user AC + dac u.dspbuf " save as user display buffer + jms movdsp " switch to user display buffer + jmp sysexit + + " release display? +.rele: + dzm u.dspbuf " clear user display buffer pointer + law dspbuf " get default display buffer + jms movdsp " change to it + jmp sysexit + +.chmod: + jms isown " check if user owns file arg + lac u.ac " get new permissions + and o17 " mask to read/write bits + lmq " save in MQ + lac i.flags " get file flags + and o777760 " clear permissions + omq " or in new permissions from MQ + dac i.flags " save in inode + jms iput " write inode back + jmp okexit + +.chown: + jms isown " check if user owns file arg + lac u.ac " get new owner + dac i.uid " save in inode + jms iput " write inode back + jmp okexit + +.getuid: " getuid system call + lac u.uid + dac u.ac " return u.uid in user AC + jmp sysexit + +.seek: + jms seektell + tad u.base +"** 01-s1.pdf page 8 + spa + jms error + lmq + lac f.flags + and d1 + sna + jms 1f + lacq + jms betwen; d0; i.size + jms dacisize + jmp 2f +1: + lacq + jms betwen; d0; i.size + lac i.size +2: + dac f.badd + dac u.ac + jms fput + jmp sysexit + +.tell: + jms seektell + cma + tad d1 + tad u.base + dac u.ac + jmp sysexit + +.link: + jms arg " Save the argument pointers in + dac 0f "0f, 1f and 2f + jms arg + dac 1f + jms arg + dac 2f + lac u.cdir " Search the current directory + jms namei; 0:0 " for the first argument + jms error " Didn't find it + jms namei; 1:0 " In the i-num found by 1st namei, + jms error " search for 2nd argument, err not found + dac u.base " save in user data + jms copy; 2:0; name; 4 + lac u.cdir " Search the process' current directory + jms namei; name " for the third argument + skp + jms error " Error if it already exists + lac d1 + dac mode " Save mode bits for access + jms access " check access (or return error to user) + jms dslot " allocate directory slot + lac u.base " get source file i-number + jms iget " read inode in + lac ii " get the i-num + dac d.i " Save the i-num in the directory entry + jms copy; name; d.name; 4 " Copy the new link name into the directory entry + lac i.uniq " Copy the i-node unique number into + dac d.uniq " the directory entry + -1 + tad i.nlks " Decrement link count, i.e. one more link + dac i.nlks +"** 01-s1.pdf page 9 + jms iput " Save the i-node and directory entry for + jms dput " the new link + jmp okexit " and return OK + +.unlink: + jms argname " fetch filename, inode + dac u.base " save i-number + lac d1 " write mode bit + dac mode " save for access call + jms access " check access or return error (reads inode) + dzm d.i " clear directory i-num + jms dput " write directory entry back + lac u.base " get i-number back + jms iget " read inode back + isz i.nlks " increment link count (kept as negative count) + jmp 1f " not zero + jms itrunc " zero links: free blocks + dzm i.flags " clear status (free inode) +1: + jms iput " write inode back to disk + jmp sysexit + +.setuid: " setuid system call + lac u.uid " load current user id + sma " negative (super user) + jms error " no: error!! + lac u.ac " load user AC + dac u.uid " save as new uid + jmp sysexit + + " rename system call: + " sys rename; old_name_ptr; new_name_ptr + " Questions: + " when is directory entry read?? + " is access check on directory or src file?? + " check for existing file with new name?? + " when is directory entry written back?? +.rename: + jms arg " fetch first arg (old name pointer) + dac 0f " save for namei + jms arg " fetch second arg (new name pointer) + dac 1f " save for copy + lac u.cdir " get CWD + jms namei; 0:0 " search for (old) name + jms error " not found: return error + lac d1 " get write mode bit + dac mode " save for access call + jms access " access OK? (or return error to user) + jms copy; 1:0; d.name; 4 " copy new name into directory entry + jms dput " and write it to disk + jmp okexit + + " time system call returns line (mains) frequency ticks + " high order bits returned in AC, low order in MQ + " s.tim is located in "system" block (written to disk) + " so this is a running count of uptime since first boot! + " at 60Hz, 36 bits would last 36+ years! +.time: + lac s.tim " load high order bits + dac u.ac " return in AC + lac s.tim+1 " load low order bits + dac u.mq " return in MQ + jmp sysexit + +.chdir: + jms argname " fetch argument as filename + jms iget " (re)read inode(???) + lac i.flags " get flags + and o20 " get directory bit + sna " is a directory? + jms error " no: return error to user + lac ii " yes: get i-number + dac u.cdir " save as current working directory +"** 01-s1.pdf page 10 + jmp okexit + + " open system call + " sys open; filename_ptr; flags (0 for read, 1 for write) + " returns w/ "fd" in AC (or -1 if not found) +.open: + jms arg " get filename + dac 0f " save for namei + jms arg " get flags + sza " zero (read) + lac d1 " no: get write mode bit + sna " non-zero (write)? + lac d2 " no: get read mode bot + dac mode " save for access call + lac u.cdir " get current working directory + jms namei; 0:0 " search for file + jms error " error: return -1 + jms iget " load inode + jms access " check access (may return w/ error to user) + lac i.flags " get file flags + and o20 " get directory bit + sna " is directory? + jmp open1 " no, join common code + lac mode " get access mode + and d1 " get write bit + sna " write access? + jmp open1 " no, continue + lac u.uid " yes: get uid? + sma " negative? (-1 is superuser) + jms error " no: return error + jmp open1 " yes: join common code + +.creat: + lac d1 " mode bit 1 (write) + dac mode " save for access call + jms arg " get name pointer + dac .+2 " save for copy + jms copy; ..; name; 4 " copy filename to "name" + lac u.cdir + jms namei; name " look up in current working directory + jmp 1f " not found + jms iget " file exists: read inode + jms access " check access (or return error to user) + lac i.flags " get flags + and o20 " get directory bit + sna " is a directory? + jmp .+4 " no: skip to truncate + lac u.uid " get user + sma " is super user? + jms error " no: error + jms itrunc " yes: truncate + cla + jms dacisize " clear i.size + jmp open1 +1: + jms access " here if not found + lac u.ac " get access bits from user AC (zero for lock!) + and o17 " mask to permissions + jms icreat +open1: " common exit for open/creat + jms fassign " assign fd slot + jms error " none free, return -1 + jmp sysexit + +"** 01-s1.pdf page 11 +.close: + jms finac " get fnode (open file) for fd in user AC + dzm f.flags " clear flags + jms fput " write fnode back to u.ofiles + jmp sysexit + +.read: + jms arg " get argument + and o17777 " mask to address + dac u.base " save as I/O base + jms arg " get second argument + dac u.count " save as count + lac u.base " get base + jms betwen; o10000; o17777 " end inside user memory? + jms error " no: error + tad u.count " get end of buffer + jms betwen; u.base; o17777 " inside buffer/user memory? + jms error " no: error + dac u.limit " yes: save as I/O limit +1: + jms finac " get fnode for fd in user AC + lac f.flags " get open file flags + and d1 " get write bit + sza " open for write? + jms error " yes: error + lac i.flags " get inode flags + and o40 " get special file bit + sna " special? + jmp 1f " no + iof " yes: disable interrupts + lac ii " get i number + tad swr " add to base instruction + dac .+1 + jmp .. i " dispatch to read routine +1: + lac u.base " get user base + dac 1f+1 " save as iread base + lac u.count " get user count + dac 1f+2 " save as iread count + lac f.badd " get file offset +1: + jms iread; ..; .. + jmp exitrw + + " write system call: + " AC/ fd + " sys write; buffer; count + " AC/ count or -1 on error +.write: + jms arg " pick up buffer + and o17777 " mask to addr + dac u.base " save as I/O base + jms arg " pick up count + dac u.count " save as count + tad u.base " add base (get limit) + jms betwen; u.base; o17777 " check between base and end of memory + jms error " no: error + dac u.limit " yes: save as limit + jms finac " get fnode with fd from user AC + lac f.flags " get open file table flags + and d1 " open for write? + sna " if yes, skip + jms error " no: error + lac i.flags " get inode flags + and o40 " get device bit +"** 01-s1.pdf page 12 + sna " special? + jmp 1f " no + iof " yes, special: turn interrupts off + lac ii " get i number + tad sww " get write routine entry addr + dac .+1 + jmp .. i " dispatch to write routine +1: " here with regular file + lac u.base " get base + dac 1f+1 " save as iwrite arg 1 + lac u.count " get count + dac 1f+2 " save as iwrite 2 + lac f.badd " get fd offset +1: + jms iwrite; ..; .. " write to file + +exitrw: " common exit for read/write system calls + dac u.ac " save return in user AC + tad f.badd + dac f.badd " update file offset + jms iput " release inode + jms fput " release fnode + jmp sysexit " return to user