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