Val _lib7_P_ProcEnv_getpgrp (Task* task, Val arg) { //======================= // // Mythryl type: Void -> Int // // Return process group. // // This fn gets bound as get_process_group in: // // src/lib/std/src/posix-1003.1b/posix-id.pkg ENTER_MYTHRYL_CALLABLE_C_FN("_lib7_P_ProcEnv_getpgrp"); RELEASE_MYTHRYL_HEAP( task->pthread, "_lib7_P_ProcEnv_getpgrp", NULL ); // int pgrp = getpgrp(); // RECOVER_MYTHRYL_HEAP( task->pthread, "_lib7_P_ProcEnv_getpgrp" ); return TAGGED_INT_FROM_C_INT( pgrp ); }
Val _lib7_Sock_shutdown (Task* task, Val arg) { //=================== // // Mythryl type: (Socket, Int) -> Void // // This fn gets bound to shutdown' in: // // src/lib/std/src/socket/socket-guts.pkg ENTER_MYTHRYL_CALLABLE_C_FN("_lib7_Sock_shutdown"); // RAISE_SYSERR__MAY_HEAPCLEAN def in src/c/lib/raise-error.h int socket = GET_TUPLE_SLOT_AS_INT( arg, 0 ); int how = GET_TUPLE_SLOT_AS_INT( arg, 1 ); // Last use of 'arg'. // shutdown is documented by man 2 shutdown RELEASE_MYTHRYL_HEAP( task->pthread, "_lib7_Sock_shutdown", NULL ); // if (shutdown( socket, how ) < 0) return RAISE_SYSERR__MAY_HEAPCLEAN(task, status, NULL); // Where is 'status' coming from? Is this rational? // // ('status' is ignored except on MacOS, where this is probably broken) XXX BUGGO FIXME RECOVER_MYTHRYL_HEAP( task->pthread, "_lib7_Sock_shutdown" ); return HEAP_VOID; }
Val _lib7_Sock_listen (Task* task, Val arg) { //================= // // Mythryl type: (Socket, Int) -> Void // // This fn gets bound as listen' in: // // src/lib/std/src/socket/socket-guts.pkg ENTER_MYTHRYL_CALLABLE_C_FN("_lib7_Sock_listen"); int socket = GET_TUPLE_SLOT_AS_INT( arg, 0 ); int backlog = GET_TUPLE_SLOT_AS_INT( arg, 1 ); // Last use of 'arg'. RELEASE_MYTHRYL_HEAP( task->pthread, "_lib7_Sock_listen", NULL ); // int status = listen( socket, backlog ); // RECOVER_MYTHRYL_HEAP( task->pthread, "_lib7_Sock_listen" ); RETURN_VOID_EXCEPT_RAISE_SYSERR_ON_NEGATIVE_STATUS__MAY_HEAPCLEAN( task, status, NULL ); }
Val _lib7_Date_greanwich_mean_time (Task* task, Val arg) { //============================== // // Mythryl type: one_word_int::Int -> (Int, Int, Int, Int, Int, Int, Int, Int, Int) // // Takes a UTC time value (in seconds), and converts it to a 9-tuple with // the fields: tm_sec, tm_min, tm_hour, tm_mday, tm_mon, tm_year, tm_wday, // tm_yday, and tm_isdst. // // This fn gets bound to gm_time' in: // // src/lib/std/src/date.pkg ENTER_MYTHRYL_CALLABLE_C_FN("_lib7_Date_greanwich_mean_time"); time_t t = (time_t) INT1_LIB7toC(arg); RELEASE_MYTHRYL_HEAP( task->pthread, "_lib7_Date_greanwich_mean_time", NULL ); // struct tm* tm = gmtime( &t ); // RECOVER_MYTHRYL_HEAP( task->pthread, "_lib7_Date_greanwich_mean_time" ); if (tm == NULL) return RAISE_SYSERR__MAY_HEAPCLEAN(task,0,NULL); set_slot_in_nascent_heapchunk(task, 0, MAKE_TAGWORD(PAIRS_AND_RECORDS_BTAG, 9)); set_slot_in_nascent_heapchunk(task, 1, TAGGED_INT_FROM_C_INT(tm->tm_sec)); set_slot_in_nascent_heapchunk(task, 2, TAGGED_INT_FROM_C_INT(tm->tm_min)); set_slot_in_nascent_heapchunk(task, 3, TAGGED_INT_FROM_C_INT(tm->tm_hour)); set_slot_in_nascent_heapchunk(task, 4, TAGGED_INT_FROM_C_INT(tm->tm_mday)); set_slot_in_nascent_heapchunk(task, 5, TAGGED_INT_FROM_C_INT(tm->tm_mon)); set_slot_in_nascent_heapchunk(task, 6, TAGGED_INT_FROM_C_INT(tm->tm_year)); set_slot_in_nascent_heapchunk(task, 7, TAGGED_INT_FROM_C_INT(tm->tm_wday)); set_slot_in_nascent_heapchunk(task, 8, TAGGED_INT_FROM_C_INT(tm->tm_yday)); set_slot_in_nascent_heapchunk(task, 9, TAGGED_INT_FROM_C_INT(tm->tm_isdst)); return commit_nascent_heapchunk(task, 9); }
Val _lib7_netdb_get_host_by_name (Task* task, Val arg) { //============================ // // Mythryl type: String -> Null_Or( (String, List(String), Raw_Address_Family, List( Internet_Address )) ) // // This fn gets bound as get_host_by_name' in: // // src/lib/std/src/socket/dns-host-lookup.pkg ENTER_MYTHRYL_CALLABLE_C_FN("_lib7_netdb_get_host_by_name"); char* heap_name = HEAP_STRING_AS_C_STRING( arg ); // Last use of 'arg'. struct hostent* result; // We cannot reference anything on the Mythryl // heap between RELEASE_MYTHRYL_HEAP and RECOVER_MYTHRYL_HEAP // because garbage collection might be moving // it around, so copy heap_path into C storage: // Mythryl_Heap_Value_Buffer name_buf; // { char* c_name = buffer_mythryl_heap_value( &name_buf, (void*) heap_name, strlen( heap_name ) +1 ); // '+1' for terminal NUL on string. RELEASE_MYTHRYL_HEAP( task->pthread, "_lib7_netdb_get_host_by_name", NULL ); // result = gethostbyname( c_name ); // RECOVER_MYTHRYL_HEAP( task->pthread, "_lib7_netdb_get_host_by_name" ); unbuffer_mythryl_heap_value( &name_buf ); } return _util_NetDB_mkhostent (task, result); // _util_NetDB_mkhostent def in src/c/lib/socket/util-mkhostent.c }
Val _lib7_Sock_accept (Task* task, Val arg) { //================= // // Mythryl type: Socket -> (Socket, Address) // // This fn gets bound as accept' in: // // src/lib/std/src/socket/socket-guts.pkg ENTER_MYTHRYL_CALLABLE_C_FN("_lib7_Sock_accept"); int socket = TAGGED_INT_TO_C_INT( arg ); // Last use of 'arg'. char address_buf[ MAX_SOCK_ADDR_BYTESIZE ]; socklen_t address_len = MAX_SOCK_ADDR_BYTESIZE; int new_socket; RELEASE_MYTHRYL_HEAP( task->pthread, "_lib7_Sock_accept", NULL ); // /* do { */ /* Backed out 2010-02-26 CrT: See discussion at bottom of src/c/lib/socket/connect.c */ new_socket = accept (socket, (struct sockaddr*) address_buf, &address_len); /* } while (new_socket < 0 && errno == EINTR); */ /* Restart if interrupted by a SIGALRM or SIGCHLD or whatever. */ // RECOVER_MYTHRYL_HEAP( task->pthread, "_lib7_Sock_accept" ); if (new_socket == -1) { // return RAISE_SYSERR__MAY_HEAPCLEAN( task, new_socket, NULL); // } else { // Val data = make_biwordslots_vector_sized_in_bytes__may_heapclean( task, address_buf, address_len, NULL ); Val address = make_vector_header( task, UNT8_RO_VECTOR_TAGWORD, data, address_len); return make_two_slot_record(task, TAGGED_INT_FROM_C_INT( new_socket ), address); } }
Val _lib7_P_ProcEnv_getuid (Task* task, Val arg) { //====================== // // Mythryl type: Void -> Unt // // Return user id. // // This fn gets bound as get_user_id in: // // src/lib/std/src/psx/posix-id.pkg ENTER_MYTHRYL_CALLABLE_C_FN(__func__); RELEASE_MYTHRYL_HEAP( task->hostthread, __func__, NULL ); // int uid = getuid (); // RECOVER_MYTHRYL_HEAP( task->hostthread, __func__ ); Val result = make_one_word_unt(task, (Vunt) uid ); EXIT_MYTHRYL_CALLABLE_C_FN(__func__); return result; }
Val _lib7_P_TTY_tcgetpgrp (Task* task, Val arg) { //===================== // // Mythryl type: Int -> Int // // Get foreground process group id of tty. // // This fn gets bound as tcgetpgrp in: // // src/lib/std/src/posix-1003.1b/posix-tty.pkg ENTER_MYTHRYL_CALLABLE_C_FN("_lib7_P_TTY_tcgetpgrp"); int fd = TAGGED_INT_TO_C_INT( arg ); RELEASE_MYTHRYL_HEAP( task->pthread, "_lib7_P_TTY_tcgetpgrp", NULL ); // int result = tcgetpgrp( fd ); // RECOVER_MYTHRYL_HEAP( task->pthread, "_lib7_P_TTY_tcgetpgrp" ); return TAGGED_INT_FROM_C_INT( result ); }
Val _lib7_P_TTY_tcdrain (Task* task, Val arg) { //=================== // // Mythryl type: Int -> Void // // Wait for all output to be transmitted. // // This fn gets bound as tcdrain in: // // src/lib/std/src/posix-1003.1b/posix-tty.pkg ENTER_MYTHRYL_CALLABLE_C_FN("_lib7_P_TTY_tcdrain"); int fd = TAGGED_INT_TO_C_INT( arg ); RELEASE_MYTHRYL_HEAP( task->pthread, "_lib7_P_TTY_tcdrain", NULL ); // int status = tcdrain( fd ); // RECOVER_MYTHRYL_HEAP( task->pthread, "_lib7_P_TTY_tcdrain" ); RETURN_VOID_EXCEPT_RAISE_SYSERR_ON_NEGATIVE_STATUS__MAY_HEAPCLEAN(task, status, NULL); }
Val _lib7_OS_tmpname (Task* task, Val arg) { //================ // // Generate a unique name for a temporary file. // // Mythryl type: Void -> String // // This fn gets bound as tmp_name in: // // src/lib/std/src/posix/winix-file.pkg ENTER_MYTHRYL_CALLABLE_C_FN(__func__); static int call_number = 0; static int pid = 0; char buf[ 132 ]; int c1 = ++call_number; // Try to make our filename unique. if (!pid) { RELEASE_MYTHRYL_HEAP( task->hostthread, __func__, NULL ); // pid = getpid(); // Try to harder to make our filename unique. // RECOVER_MYTHRYL_HEAP( task->hostthread, __func__ ); } int c2 = ++call_number; // Try to harder yet to make our filename unique. :-) sprintf (buf, "tmpfile.%d.%d.%d.tmp", c1, pid, c2); // Val result = make_ascii_string_from_c_string__may_heapclean (task, buf, NULL); EXIT_MYTHRYL_CALLABLE_C_FN(__func__); return result; }
Val _lib7_P_FileSys_chdir (Task* task, Val arg) { //===================== // // Mythryl type: String -> Void // // Change working directory. // // This fn gets bound as change_directory in: // // src/lib/std/src/posix-1003.1b/posix-file.pkg // src/lib/std/src/posix-1003.1b/posix-file-system-64.pkg ENTER_MYTHRYL_CALLABLE_C_FN("_lib7_P_FileSys_chdir"); int status; char* heap_dir = HEAP_STRING_AS_C_STRING( arg ); // We cannot reference anything on the Mythryl // heap between RELEASE_MYTHRYL_HEAP and RECOVER_MYTHRYL_HEAP // because garbage collection might be moving // it around, so copy heap_path into C storage: // Mythryl_Heap_Value_Buffer dir_buf; // { char* c_dir = buffer_mythryl_heap_value( &dir_buf, (void*) heap_dir, strlen( heap_dir )+1 ); // '+1' for terminal NUL on string. // RELEASE_MYTHRYL_HEAP( task->pthread, "_lib7_P_FileSys_chdir", NULL ); // status = chdir( c_dir ); // RECOVER_MYTHRYL_HEAP( task->pthread, "_lib7_P_FileSys_chdir" ); // unbuffer_mythryl_heap_value( &dir_buf ); } RETURN_VOID_EXCEPT_RAISE_SYSERR_ON_NEGATIVE_STATUS__MAY_HEAPCLEAN(task, status, NULL); }
Val _lib7_P_ProcEnv_ttyname (Task* task, Val arg) { //======================= // // Mythryl type: Int -> String // // Return terminal name associated with file descriptor, if any. // // This fn gets bound as ttyname' in: // // src/lib/std/src/psx/posix-id.pkg ENTER_MYTHRYL_CALLABLE_C_FN(__func__); RELEASE_MYTHRYL_HEAP( task->hostthread, __func__, NULL ); // char* name = ttyname(TAGGED_INT_TO_C_INT(arg)); // RECOVER_MYTHRYL_HEAP( task->hostthread, __func__ ); if (name == NULL) return RAISE_ERROR__MAY_HEAPCLEAN(task, "not a terminal device", NULL); // Val result = make_ascii_string_from_c_string__may_heapclean( task, name, NULL ); EXIT_MYTHRYL_CALLABLE_C_FN(__func__); return result; }
Val _lib7_netdb_get_host_by_address (Task* task, Val arg) { //=============================== // // Mythryl type: Internet_Address -> Null_Or( (String, List(String), Raw_Address_Family, List(Internet_Address)) ) // // This fn gets bound as get_host_by_addr' in: // // src/lib/std/src/socket/dns-host-lookup.pkg ENTER_MYTHRYL_CALLABLE_C_FN("_lib7_netdb_get_host_by_address"); ASSERT (sizeof(struct in_addr) == GET_VECTOR_LENGTH( arg )); struct in_addr* heap_arg = (struct in_addr*) HEAP_STRING_AS_C_STRING( arg ); // Last use of 'arg'. struct in_addr c_arg = *heap_arg; RELEASE_MYTHRYL_HEAP( task->pthread, "_lib7_netdb_get_host_by_address", NULL ); // struct hostent* result = gethostbyaddr (&c_arg, sizeof(struct in_addr), AF_INET); // RECOVER_MYTHRYL_HEAP( task->pthread, "_lib7_netdb_get_host_by_address" ); return _util_NetDB_mkhostent ( task, result ); // _util_NetDB_mkhostent def in src/c/lib/socket/util-mkhostent.c }
Val _lib7_P_ProcEnv_setgid (Task* task, Val arg) { //====================== // // Mythryl type: Unt -> Void // // Set group id. // // This fn gets bound as set_group_id in: // // src/lib/std/src/psx/posix-id.pkg ENTER_MYTHRYL_CALLABLE_C_FN(__func__); RELEASE_MYTHRYL_HEAP( task->hostthread, __func__, &arg ); // int status = setgid( WORD_LIB7toC( arg )); // RECOVER_MYTHRYL_HEAP( task->hostthread, __func__ ); Val result = RETURN_VOID_EXCEPT_RAISE_SYSERR_ON_NEGATIVE_STATUS__MAY_HEAPCLEAN(task, status, NULL); EXIT_MYTHRYL_CALLABLE_C_FN(__func__); return result; }
Val _lib7_P_ProcEnv_getpgrp (Task* task, Val arg) { //======================= // // Mythryl type: Void -> Int // // Return process group. // // This fn gets bound as get_process_group in: // // src/lib/std/src/psx/posix-id.pkg ENTER_MYTHRYL_CALLABLE_C_FN(__func__); RELEASE_MYTHRYL_HEAP( task->hostthread, __func__, NULL ); // int pgrp = getpgrp(); // RECOVER_MYTHRYL_HEAP( task->hostthread, __func__ ); Val result = TAGGED_INT_FROM_C_INT( pgrp ); EXIT_MYTHRYL_CALLABLE_C_FN(__func__); return result; }
Val _lib7_P_ProcEnv_time (Task* task, Val arg) { //==================== // // Mythryl type: Void -> one_word_int::Int // // Return time in seconds from 00:00:00 UTC, January 1, 1970 // // This fn gets bound as time in: // // src/lib/std/src/psx/posix-id.pkg ENTER_MYTHRYL_CALLABLE_C_FN(__func__); RELEASE_MYTHRYL_HEAP( task->hostthread, __func__, NULL ); // time_t t = time( NULL ); // RECOVER_MYTHRYL_HEAP( task->hostthread, __func__ ); Val result = make_one_word_int(task, t ); EXIT_MYTHRYL_CALLABLE_C_FN(__func__); return result; }
Val _lib7_P_TTY_tcsetpgrp (Task* task, Val arg) { //===================== // // _lib7_P_TTY_tcsetpgrp : (Int, Int) -> Void // // Set foreground process group id of tty. // // This fn gets bound as tcsetpgrp in: // // src/lib/std/src/posix-1003.1b/posix-tty.pkg ENTER_MYTHRYL_CALLABLE_C_FN("_lib7_P_TTY_tcsetpgrp"); int fd = GET_TUPLE_SLOT_AS_INT(arg, 0); int pgrp = GET_TUPLE_SLOT_AS_INT(arg, 1); RELEASE_MYTHRYL_HEAP( task->pthread, "_lib7_P_TTY_tcsetpgrp", NULL ); // int status = tcsetpgrp( fd, pgrp ); // RECOVER_MYTHRYL_HEAP( task->pthread, "_lib7_P_TTY_tcsetpgrp" ); RETURN_VOID_EXCEPT_RAISE_SYSERR_ON_NEGATIVE_STATUS__MAY_HEAPCLEAN(task, status, NULL); }
Val _lib7_P_TTY_tcsendbreak (Task* task, Val arg) { //======================= // // Mythryl type: (Int, Int) -> Void // // Send break condition on tty line. // // This fn gets bound as tcsendbreak in: // // src/lib/std/src/posix-1003.1b/posix-tty.pkg ENTER_MYTHRYL_CALLABLE_C_FN("_lib7_P_TTY_tcsendbreak"); int fd = GET_TUPLE_SLOT_AS_INT( arg, 0 ); int duration = GET_TUPLE_SLOT_AS_INT( arg, 1 ); RELEASE_MYTHRYL_HEAP( task->pthread, "_lib7_P_TTY_tcsendbreak", NULL ); // int status = tcsendbreak( fd, duration ); // RECOVER_MYTHRYL_HEAP( task->pthread, "_lib7_P_TTY_tcsendbreak" ); RETURN_VOID_EXCEPT_RAISE_SYSERR_ON_NEGATIVE_STATUS__MAY_HEAPCLEAN(task, status, NULL); }
Val _lib7_Sock_getNREAD (Task* task, Val arg) { //=================== // // Mythryl type: Socket -> Int // // This fn gets bound as get_nread' in: // // src/lib/std/src/socket/socket-guts.pkg ENTER_MYTHRYL_CALLABLE_C_FN("_lib7_Sock_getNREAD"); int device = TAGGED_INT_TO_C_INT( arg ); // Last use of 'arg'. RELEASE_MYTHRYL_HEAP( task->pthread, "_lib7_Sock_getNREAD", NULL ); // int n; int status = ioctl( device, FIONREAD, (char*) &n ); // RECOVER_MYTHRYL_HEAP( task->pthread, "_lib7_Sock_getNREAD" ); if (status < 0) return RAISE_SYSERR__MAY_HEAPCLEAN(task, status, NULL); return TAGGED_INT_FROM_C_INT( n ); }
Val _lib7_P_IO_copy (Task* task, Val arg) { //=============== // // Mythryl type: (String, String) -> Int // // Copy a file and return its length. // // This fn gets bound as copy in: // // src/lib/std/src/psx/posix-io.pkg // src/lib/std/src/psx/posix-io-64.pkg # Actually, I haven't gotten around to this yet. ENTER_MYTHRYL_CALLABLE_C_FN(__func__); Val existing = GET_TUPLE_SLOT_AS_VAL(arg, 0); Val new_name = GET_TUPLE_SLOT_AS_VAL(arg, 1); char* heap_existing = HEAP_STRING_AS_C_STRING( existing ); char* heap_new_name = HEAP_STRING_AS_C_STRING( new_name ); // We cannot reference anything on the Mythryl // heap between RELEASE_MYTHRYL_HEAP and RECOVER_MYTHRYL_HEAP // because garbage collection might be moving // it around, so copy heap_path into C storage: // Mythryl_Heap_Value_Buffer existing_buf; Mythryl_Heap_Value_Buffer new_name_buf; int ok = TRUE; ssize_t total_bytes_written = 0; { char* c_existing = buffer_mythryl_heap_value( &existing_buf, (void*) heap_existing, strlen( heap_existing ) +1 ); // '+1' for terminal NUL on string. char* c_new_name = buffer_mythryl_heap_value( &new_name_buf, (void*) heap_new_name, strlen( heap_new_name ) +1 ); // '+1' for terminal NUL on string. RELEASE_MYTHRYL_HEAP( task->hostthread, __func__, NULL ); // struct stat statbuf; int fd_out; int fd_in = open(c_existing, O_RDONLY); // Open the input file. if (fd_in >= 0) { if (0 <= fstat(fd_in, &statbuf)) { // Get the mode of the input file so that we can ... fd_out = creat( c_new_name, statbuf.st_mode ); // ... open the output file with same mode as input file. if (0 <= fd_out) { char buffer[ 4096 ]; ssize_t bytes_read; int ok = TRUE; while (ok) { // Read up to one buffer[]-load from fd_in. do { bytes_read = read( fd_in, buffer, 4096 ); } while (bytes_read < 0 && errno == EINTR); // Retry if interrupted by SIGALRM or such. if (bytes_read < 0) { ok = FALSE; break; } if (bytes_read == 0) { break; } ssize_t buffer_bytes_written = 0; while (ok && (buffer_bytes_written < bytes_read)) { // Write buffer[] contents to fd_out. Usually one write() will do it, but this is not guaranteed. ssize_t bytes_to_write = bytes_read - buffer_bytes_written; ssize_t bytes_written; do { bytes_written = write( fd_out, buffer+buffer_bytes_written, bytes_to_write ); } while (bytes_written < 0 && errno == EINTR); // Retry if interrupted by SIGALRM or such. ok = ok && (bytes_written > 0); buffer_bytes_written += bytes_written; total_bytes_written += bytes_written; } } close(fd_out); } else { ok = FALSE; } close(fd_in); } else { ok = FALSE; } } else { ok = FALSE; } // RECOVER_MYTHRYL_HEAP( task->hostthread, __func__ ); unbuffer_mythryl_heap_value( &existing_buf ); unbuffer_mythryl_heap_value( &new_name_buf ); } Val result; if (!ok) result = RAISE_SYSERR__MAY_HEAPCLEAN(task, -1, NULL); // XXX SUCKO FIXME I'm being totally sloppy about accurate diagnostics here. Feel free to submit a patch improving this. else result = TAGGED_INT_FROM_C_INT( total_bytes_written ); EXIT_MYTHRYL_CALLABLE_C_FN(__func__); return result; }
Val _lib7_Sock_recvbuffrom (Task* task, Val arg) { //====================== // // Mythryl type: (Socket, rw_vector_of_one_byte_unts::Rw_Vector, Int, Int, Bool, Bool) -> (Int, Addr) // // The arguments are: // socket, // data buffer, // start position, // number of bytes, // OOB flag // peek flag. // // The result is: // number of bytes read // source address. // // This fn gets bound as recv_from_a in: // // src/lib/std/src/socket/socket-guts.pkg ENTER_MYTHRYL_CALLABLE_C_FN(__func__); char address_buf[ MAX_SOCK_ADDR_BYTESIZE ]; socklen_t address_len = MAX_SOCK_ADDR_BYTESIZE; int socket = GET_TUPLE_SLOT_AS_INT( arg, 0); // Val buf = GET_TUPLE_SLOT_AS_VAL( arg, 1); // Mythryl buffer to read bytes into. // We'll fetch this after the call, since it may move around during the call. int offset = GET_TUPLE_SLOT_AS_INT( arg, 2); // Offset within buf to read bytes into. int nbytes = GET_TUPLE_SLOT_AS_INT( arg, 3); // Number of bytes to read. int flag = 0; int n; if (GET_TUPLE_SLOT_AS_VAL(arg, 4) == HEAP_TRUE) flag |= MSG_OOB; if (GET_TUPLE_SLOT_AS_VAL(arg, 5) == HEAP_TRUE) flag |= MSG_PEEK; // We cannot reference anything on the Mythryl heap // between RELEASE_MYTHRYL_HEAP and RECOVER_MYTHRYL_HEAP // because garbage collection might be moving // it around, so allocate a C-side read buffer: // Mythryl_Heap_Value_Buffer readbuf_buf; // { char* c_readbuf = buffer_mythryl_heap_nonvalue( &readbuf_buf, nbytes ); RELEASE_MYTHRYL_HEAP( task->hostthread, __func__, &arg ); // 'arg' is still live here! // do { // n = recvfrom( socket, c_readbuf, nbytes, flag, (struct sockaddr *)address_buf, &address_len ); } while (n < 0 && errno == EINTR); // Restart if interrupted by a SIGALRM or SIGCHLD or whatever. // RECOVER_MYTHRYL_HEAP( task->hostthread, __func__ ); if (n < 0) { unbuffer_mythryl_heap_value( &readbuf_buf ); return RAISE_SYSERR__MAY_HEAPCLEAN(task, status, NULL); } Val buf = GET_TUPLE_SLOT_AS_VAL( arg, 1); // Mythryl buffer to read bytes into. char* bufstart = HEAP_STRING_AS_C_STRING(buf) + offset; memcpy( bufstart, c_readbuf, n); unbuffer_mythryl_heap_value( &readbuf_buf ); } Val data = make_biwordslots_vector_sized_in_bytes__may_heapclean( task, address_buf, address_len, NULL ); Val address = make_vector_header( task, UNT8_RO_VECTOR_TAGWORD, data, address_len); Val result = make_two_slot_record(task, TAGGED_INT_FROM_C_INT(n), address); EXIT_MYTHRYL_CALLABLE_C_FN(__func__); return result; }
Val _lib7_P_FileSys_utime (Task* task, Val arg) { //===================== // // Mythryl type: (String, one_word_int::Int, one_word_int::Int) -> Void // name actime modtime // // Sets file access and modification times. // If actime = -1, then set both to current time. // // This fn gets bound as utime' in: // // src/lib/std/src/psx/posix-file.pkg // src/lib/std/src/psx/posix-file-system-64.pkg ENTER_MYTHRYL_CALLABLE_C_FN(__func__); int status; Val path = GET_TUPLE_SLOT_AS_VAL( arg, 0); time_t actime = TUPLE_GET_INT1( arg, 1); time_t modtime = TUPLE_GET_INT1( arg, 2); char* heap_path = HEAP_STRING_AS_C_STRING( path ); // We cannot reference anything on the Mythryl // heap between RELEASE_MYTHRYL_HEAP and RECOVER_MYTHRYL_HEAP // because garbage collection might be moving // it around, so copy heap_path into C storage: // Mythryl_Heap_Value_Buffer path_buf; // { char* c_path = buffer_mythryl_heap_value( &path_buf, (void*) heap_path, strlen( heap_path ) +1 ); // '+1' for terminal NUL on string. if (actime == -1) { RELEASE_MYTHRYL_HEAP( task->hostthread, __func__, NULL ); // status = utime( c_path, NULL ); // RECOVER_MYTHRYL_HEAP( task->hostthread, __func__ ); } else { struct utimbuf tb; tb.actime = actime; tb.modtime = modtime; RELEASE_MYTHRYL_HEAP( task->hostthread, __func__, NULL ); // status = utime( c_path, &tb ); // RECOVER_MYTHRYL_HEAP( task->hostthread, __func__ ); } unbuffer_mythryl_heap_value( &path_buf ); } Val result = RETURN_VOID_EXCEPT_RAISE_SYSERR_ON_NEGATIVE_STATUS__MAY_HEAPCLEAN(task, status, NULL); EXIT_MYTHRYL_CALLABLE_C_FN(__func__); return result; }
Val get_or_set_socket_linger_option (Task* task, Val arg) { //=============================== // // Mythryl type: (Socket_Fd, Null_Or(Null_Or(Int))) -> Null_Or(Int) // // Set/get the SO_LINGER option as follows: // NULL => get current setting // THE(NULL) => disable linger // THE(THE t) => enable linger with timeout t. // // This function gets bound as ctl_linger in: // // src/lib/std/src/socket/socket-guts.pkg // ENTER_MYTHRYL_CALLABLE_C_FN(__func__); int socket = GET_TUPLE_SLOT_AS_INT( arg, 0 ); Val ctl = GET_TUPLE_SLOT_AS_VAL( arg, 1 ); // Last use of 'arg'. struct linger optVal; int status; if (ctl == OPTION_NULL) { // socklen_t optSz = sizeof( struct linger ); RELEASE_MYTHRYL_HEAP( task->hostthread, __func__, NULL ); // status = getsockopt( socket, SOL_SOCKET, SO_LINGER, (sockoptval_t)&optVal, &optSz ); // RECOVER_MYTHRYL_HEAP( task->hostthread, __func__ ); ASSERT( status < 0 || optSz == sizeof( struct linger )); // } else { // ctl = OPTION_GET(ctl); if (ctl == OPTION_NULL) { optVal.l_onoff = 0; // Argument is THE(NULL); disable linger. } else { optVal.l_onoff = 1; // argument is THE t; enable linger. optVal.l_linger = TAGGED_INT_TO_C_INT(OPTION_GET(ctl)); } RELEASE_MYTHRYL_HEAP( task->hostthread, __func__, NULL ); // status = setsockopt (socket, SOL_SOCKET, SO_LINGER, (sockoptval_t)&optVal, sizeof(struct linger)); // RECOVER_MYTHRYL_HEAP( task->hostthread, __func__ ); } if (status < 0) return RAISE_SYSERR__MAY_HEAPCLEAN(task, status, NULL); if (optVal.l_onoff == 0) return OPTION_NULL; Val result = OPTION_THE( task, TAGGED_INT_FROM_C_INT( optVal.l_linger ) ); EXIT_MYTHRYL_CALLABLE_C_FN(__func__); return result; }
Val _lib7_P_FileSys_readlink (Task* task, Val arg) { //======================== // // Mythryl type: String -> String // // Read the value of a symbolic link. // // The following implementation assumes that the system readlink // fills the given buffer as much as possible, without nul-termination, // and returns the number of bytes copied. If the buffer is not large // enough, the return value will be at least the buffer size. In that // case, we find out how big the link really is, allocate a buffer to // hold it, and redo the readlink. // // Note that the above semantics are not those of POSIX, which requires // null-termination on success, and only fills the buffer up to at most // the penultimate byte even on failure. // // Should this be written to avoid the extra copy, using heap memory? // // This fn gets bound as readlink in: // // src/lib/std/src/posix-1003.1b/posix-file.pkg // src/lib/std/src/posix-1003.1b/posix-file-system-64.pkg ENTER_MYTHRYL_CALLABLE_C_FN("_lib7_P_FileSys_readlink"); struct stat sbuf; int len; int result; char* heap_path = HEAP_STRING_AS_C_STRING( arg ); char buf[MAXPATHLEN]; // We cannot reference anything on the Mythryl // heap between RELEASE_MYTHRYL_HEAP and RECOVER_MYTHRYL_HEAP // because garbage collection might be moving // it around, so copy heap_path into C storage: // Mythryl_Heap_Value_Buffer path_buf; // { char* c_path = buffer_mythryl_heap_value( &path_buf, (void*) heap_path, strlen( heap_path ) +1 ); // '+1' for terminal NUL on string. RELEASE_MYTHRYL_HEAP( task->pthread, "_lib7_P_FileSys_readlink", NULL ); // len = readlink(c_path, buf, MAXPATHLEN); // RECOVER_MYTHRYL_HEAP( task->pthread, "_lib7_P_FileSys_readlink" ); unbuffer_mythryl_heap_value( &path_buf ); } if (len < 0) return RAISE_SYSERR__MAY_HEAPCLEAN(task, len, NULL); if (len < MAXPATHLEN) { // buf[len] = '\0'; return make_ascii_string_from_c_string__may_heapclean (task, buf, NULL); } // Buffer not big enough. // Determine how big the link text is and allocate a buffer. { char* c_path = buffer_mythryl_heap_value( &path_buf, (void*) heap_path, strlen( heap_path ) +1 ); // '+1' for terminal NUL on string. RELEASE_MYTHRYL_HEAP( task->pthread, "_lib7_P_FileSys_readlink", NULL ); // result = lstat (c_path, &sbuf); // RECOVER_MYTHRYL_HEAP( task->pthread, "_lib7_P_FileSys_readlink" ); unbuffer_mythryl_heap_value( &path_buf ); } if (result < 0) return RAISE_SYSERR__MAY_HEAPCLEAN(task, result, NULL); int nlen = sbuf.st_size + 1; char* nbuf = MALLOC(nlen); if (nbuf == 0) return RAISE_ERROR__MAY_HEAPCLEAN(task, "out of malloc memory", NULL); // Try the readlink again. Give up on error or if len is still bigger // than the buffer size. // { char* c_path = buffer_mythryl_heap_value( &path_buf, (void*) heap_path, strlen( heap_path ) +1 ); // '+1' for terminal NUL on string. RELEASE_MYTHRYL_HEAP( task->pthread, "_lib7_P_FileSys_readlink", NULL ); // len = readlink(c_path, buf, len); // RECOVER_MYTHRYL_HEAP( task->pthread, "_lib7_P_FileSys_readlink" ); unbuffer_mythryl_heap_value( &path_buf ); } if (len < 0) return RAISE_SYSERR__MAY_HEAPCLEAN(task, len, NULL); if (len >= nlen) return RAISE_ERROR__MAY_HEAPCLEAN(task, "readlink failure", NULL); nbuf[len] = '\0'; Val chunk = make_ascii_string_from_c_string__may_heapclean (task, nbuf, NULL); FREE (nbuf); // return chunk; }
Val _lib7_Sock_recv (Task* task, Val arg) { //=============== // // Mythryl type: (Socket, Int, Bool, Bool) -> vector_of_one_byte_unts::Vector // // The arguments are: socket, number of bytes, OOB flag and peek flag. // The result is the vector of bytes received. // // This fn gets bound as recv_v' in: // // src/lib/std/src/socket/socket-guts.pkg ENTER_MYTHRYL_CALLABLE_C_FN(__func__); Val vec; ssize_t n; int socket = GET_TUPLE_SLOT_AS_INT( arg, 0 ); int nbytes = GET_TUPLE_SLOT_AS_INT( arg, 1 ); Val oob = GET_TUPLE_SLOT_AS_VAL( arg, 2 ); Val peek = GET_TUPLE_SLOT_AS_VAL( arg, 3 ); int flag = 0; if (oob == HEAP_TRUE) flag |= MSG_OOB; if (peek == HEAP_TRUE) flag |= MSG_PEEK; // We cannot reference anything on the Mythryl // heap between RELEASE_MYTHRYL_HEAP and RECOVER_MYTHRYL_HEAP // because garbage collection might be moving // it around, so allocate a C-world buffer // to read the bytes into: // Mythryl_Heap_Value_Buffer read_buf; // { unsigned char* c_read = buffer_mythryl_heap_nonvalue( &read_buf, nbytes ); // log_if("recv.c/before: socket d=%d nbytes d=%d oob=%s peek=%s\n",socket,nbytes,(oob == HEAP_TRUE)?"TRUE":"FALSE",(peek == HEAP_TRUE)?"TRUE":"FALSE"); errno = 0; RELEASE_MYTHRYL_HEAP( task->hostthread, __func__, NULL ); // do { // Backed out 2010-02-26 CrT: See discussion at bottom of src/c/lib/socket/connect.c // // Restored 2012-08-07 CrT n = recv (socket, c_read, nbytes, flag); // } while (n < 0 && errno == EINTR); // Restart if interrupted by a SIGALRM or SIGCHLD or whatever. // RECOVER_MYTHRYL_HEAP( task->hostthread, __func__ ); if (n <= 0) { unbuffer_mythryl_heap_value( &read_buf ); if (n < 0) return RAISE_SYSERR__MAY_HEAPCLEAN(task, status, NULL); if (n == 0) return ZERO_LENGTH_STRING__GLOBAL; } // Allocate result vector to hold the bytes read. // NB: This might cause a heapcleaning, moving things around: // vec = allocate_nonempty_wordslots_vector__may_heapclean( task, BYTES_TO_WORDS(n), NULL ); // Copy bytes read into result vector: // memcpy( PTR_CAST(char*, vec), c_read, n); // log_if( "recv.c/after: n d=%d errno d=%d (%s)\n", n, errno, errno ? strerror(errno) : ""); // hexdump_if( "recv.c/after: Received data: ", PTR_CAST(unsigned char*, vec), n ); unbuffer_mythryl_heap_value( &read_buf ); } Val result = make_vector_header( task, STRING_TAGWORD, vec, n ); EXIT_MYTHRYL_CALLABLE_C_FN(__func__); return result; }
Val _lib7_Sock_sendbuf (Task* task, Val arg) { //================== // // Mythryl type: // ( Int, # socket fd // Wy8Vector, # byte vector // Int, # start offset // Int, # vector length (end offset) // Bool, # don't-route flag // Bool # default-oob flag // ) // -> // Int // // Send data from the buffer; bytes is either a rw_vector_of_one_byte_unts.Rw_Vector, or // a vector_of_one_byte_unts.vector. The arguments are: socket, data buffer, start // position, number of bytes, OOB flag, and don't_route flag. // // This fn gets bound as send_v, send_a in: // // src/lib/std/src/socket/socket-guts.pkg ENTER_MYTHRYL_CALLABLE_C_FN(__func__); int socket = GET_TUPLE_SLOT_AS_INT( arg, 0); Val buf = GET_TUPLE_SLOT_AS_VAL( arg, 1); int offset = GET_TUPLE_SLOT_AS_INT( arg, 2); int nbytes = GET_TUPLE_SLOT_AS_INT( arg, 3); Val oob = GET_TUPLE_SLOT_AS_VAL( arg, 4); Val dontroute = GET_TUPLE_SLOT_AS_VAL( arg, 5); // Last use of 'arg'. char* heap_data = HEAP_STRING_AS_C_STRING(buf) + offset; // Compute flags parameter: // int flgs = 0; if (oob == HEAP_TRUE) flgs |= MSG_OOB; if (dontroute == HEAP_TRUE) flgs |= MSG_DONTROUTE; // log_if( "sendbuf.c/top: socket d=%d nbytes d=%d OOB=%s DONTROUTE=%s\n", // socket, nbytes, (oob == HEAP_TRUE) ? "TRUE" : "FALSE", (dontroute == HEAP_TRUE) ? "TRUE" : "FALSE" // ); // hexdump_if( "sendbuf.c/top: Data to send: ", (unsigned char*)heap_data, nbytes ); errno = 0; int n; // We cannot reference anything on the Mythryl heap // between RELEASE_MYTHRYL_HEAP and RECOVER_MYTHRYL_HEAP // because garbage collection might be moving // it around, so copy 'heap_data' into C storage: // Mythryl_Heap_Value_Buffer data_buf; // { char* c_data = buffer_mythryl_heap_value( &data_buf, (void*) heap_data, nbytes ); RELEASE_MYTHRYL_HEAP( task->hostthread, __func__, NULL ); // do { // n = send (socket, c_data, nbytes, flgs); // } while (n < 0 && errno == EINTR); // Restart if interrupted by a SIGALRM or SIGCHLD or whatever. // RECOVER_MYTHRYL_HEAP( task->hostthread, __func__ ); // log_if( "sendbuf.c/bot: n d=%d errno d=%d\n", n, errno ); unbuffer_mythryl_heap_value( &data_buf ); } Val result = RETURN_STATUS_EXCEPT_RAISE_SYSERR_ON_NEGATIVE_STATUS__MAY_HEAPCLEAN(task, n, NULL); EXIT_MYTHRYL_CALLABLE_C_FN(__func__); return result; }