summaryrefslogtreecommitdiff
path: root/lib/std/syswrap-ss+plan9.myr
blob: 58a751a97cf969fae2290ef81612b3d90dfa3d78 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
use sys

use "types"
use "errno"
use "cstrconv"
use "strfind"

pkg std =
	const nanosleep	: (nsecs : uint64 -> errno)
	$noret const exit	: (status : int -> void)
	pkglocal const bgetcwd	: (buf : byte[:] -> errno)
	pkglocal const lasterr	: (-> errno)
;;

const nanosleep = {nsecs
	if sys.sleep((nsecs/1_000_000 : uint32)) < 0
		-> lasterr()
	;;
	-> 0
}

const bgetcwd = {buf
	var fd

	fd = sys.open(".", sys.Oread)
	if fd < 0
		-> (fd : errno)
	;;

	if sys.fd2path(fd, buf) == 0
		/*
		Because we don't return the size, the best we can do is
		assume that if the buffer is completely full, we have
		truncated it. Since we truncate at utf8 characters, we
		can have at most 3 bytes truncated (4 bytes will fit
		any utf8 char), and one byte for the nul terminator.
		*/
		if cstrlen(buf) + 5 == buf.len
			-> Erange
		else
			-> (cstrlen(buf) : errno)
		;;
	;;
	-> Emisc
}

const digitchars = "0123456789"
const exit	= {status
	var buf : byte[32]	/* big enough for exit status numbers */
	var n, i
	
	if status == 0
		sys.exits("")
	else
		status &= 255
		i = 100
		n = 0
		while i > 0
			if status >= i
				buf[n++] = digitchars[(status/i)%10]
			;;
			i /= 10
		;;
		sys.exits(buf[:n])
	;;
}


const lasterr = {
	var errbuf	: byte[sys.Maxerr]
	var err

	sys.errstr(errbuf[:])
	err = cstrconv(errbuf[:])
	if strhas(err, "no error")
		-> Enone
	elif strhas(err, "already exists") || strhas(err, "is a directory")
		-> Eexist
	elif strhas(err, "read or write too large")
		-> Erange
	elif strhas(err, "read or write too small")
		-> Erange
	elif strhas(err, "i/o error")
		-> Eio
	elif strhas(err, "fd out of range or not open")
		-> Ebadf
	else
		-> Emisc
	;;
}