diff --git a/code/unix.links b/code/unix.links index 0a31519..9bed13e 100644 --- a/code/unix.links +++ b/code/unix.links @@ -148,7 +148,7 @@ fun runState(st0, m) { sig stdin : FileDescr var stdin = 0; sig stderr : FileDescr -var stderr = 3; +var stderr = 2; sig eof : String var eof = "\x00"; @@ -161,6 +161,9 @@ typename Mode = [|Create|Append|]; sig fopen : (Mode, String) {Fopen:(Mode, String) -> FileDescr |_}-> FileDescr fun fopen(mode, filename) { do Fopen(mode, filename) } +sig fclose : (FileDescr) {Fclose:(FileDescr) -> () |_}-> () +fun fclose(fd) { do Fclose(fd) } + typename File = Queue.T(String); sig emptyFile : File @@ -197,7 +200,7 @@ fun defaultFileSystem() { sig lookupFile : (FileDescr, FileSystem) ~> File fun lookupFile(fd, fsys) { switch (lookup(fd, fsys.ft)) { - case Nothing -> error("No such file") + case Nothing -> error("err: No such file(" ^^ intToString(fd) ^^ ")") case Just(file) -> file } } @@ -210,18 +213,19 @@ fun replaceFile(fd, file, fsys) { sig createFile : (String, FileSystem) -> (FileDescr, FileSystem) fun createFile(filename, fsys) { - (fsys.next, (fsys with fs = (filename, fsys.next) :: fsys.fs, next = fsys.next + 1)) + var fd = fsys.next; + (fd, (next = fd + 1, fs = (filename, fd) :: fsys.fs, ft = (fd, emptyFile) :: fsys.ft)) } sig openFile : (Mode, String, FileSystem) ~> (FileDescr, FileSystem) fun openFile(mode, filename, fsys) { - var (fd, fsys) = switch (lookup(filename, fsys.fs)) { + var (fd, fsys') = switch (lookup(filename, fsys.fs)) { case Nothing -> createFile(filename, fsys) case Just(fd) -> (fd, fsys) }; switch (mode) { case Create -> error("erase") - case Append -> (fd, fsys) + case Append -> (fd, fsys') } } @@ -233,7 +237,7 @@ fun closeFile((=front,=rear)) { sig allowState : (() {Get-,Put- |e}~> a) -> () {Get:s,Put:(s) -> () |e}~> a fun allowState(f) { (f : (() {Get:s,Put:(s) -> () |e}~> a) <- (() {Get-,Put- |e}~> a)) } -sig fileIO : (Comp(a, {Get-,Put-,Gets:(FileDescr) -> String,Puts:(FileDescr,String) -> (),Fopen:(Mode,String) -> FileDescr |e})) {Get:() {}-> FileSystem,Put:(FileSystem) -> (),Gets{_},Puts{_},Fopen{_} |e}~> a +sig fileIO : (Comp(a, {Get-,Put-,Gets:(FileDescr) -> String,Puts:(FileDescr,String) -> (),Fclose:(FileDescr) -> (),Fopen:(Mode,String) -> FileDescr |e})) {Get:() {}-> FileSystem,Put:(FileSystem) -> (),Gets{_},Puts{_},Fclose{_},Fopen{_} |e}~> a fun fileIO(m) { handle(allowState(m)()) { case Gets(fd, resume) -> @@ -248,6 +252,10 @@ fun fileIO(m) { var fsys = get(); var (fd, fsys') = openFile(mode, filename, fsys); put(fsys'); resume(fd) + case Fclose(fd, resume) -> + var fsys = get(); + var fsys' = replaceFile(fd, closeFile(lookupFile(fd, fsys)), fsys); + put(fsys'); resume(()) } } @@ -361,12 +369,31 @@ fun init() { }) } -sig init' : (FileSystem) {Fopen{_},Fork{_},Get{_},Getenv{_},Gets{_},Put{_},Puts{_},Su{_},Yield{_}|_}~> ((), FileSystem) +sig example' : () {Fork:Bool,Fclose:(FileDescr) -> (),Fopen:(Mode,String) -> FileDescr,Getenv:(String) -> String,Su:(User) -> (),Puts:(FileDescr,String) -> (),Yield:() |_}~> () +fun example'() { + var pid = fork(); + var () = { + if (pid) redirect(fun(){puts(stdout, "dummy")}, stderr) + else if (fork()) su(Alice) + else su(Bob) + }; + var user = whoami(); + var fd = fopen(Append, user ^^ ".txt"); + puts(fd, "Hello World!"); + var uid = getenv("UID"); + echo("My UID is " ^^ uid); + (if (amiroot()) { yield(); echo(user ^^ " is running as root.") } else ()); + echo("My home dir is /home/" ^^ user); + fclose(fd) +} + + +sig init' : (FileSystem) {Fclose{_},Fopen{_},Fork{_},Get{_},Getenv{_},Gets{_},Put{_},Puts{_},Su{_},Yield{_}|_}~> ((), FileSystem) fun init'(fsys) { runState(fsys, fun() { fileIO(fun() { schedule(fun() { - usermgr(Root, envs, example) + usermgr(Root, envs, example') }) }) })