3 /* Copyright (c) 1994-2011 by Marc Feeley, All Rights Reserved. */
6 * This module implements the operating system specific routines
9 * - OS specific initialization/finalization
10 * - process termination
12 * - conversion of error codes to error messages
13 * - low-level memory allocation
16 * - process times (user time, system time and real time).
17 * - heartbeat interrupt handling
18 * - user interrupt handling
19 * - access to OS environment variables
22 * - dynamic C compilation
23 * - floating point environment setup
24 * - virtual memory statistics
25 * - filesystem path expansion
26 * - formatting of source code position
27 * - operations on I/O devices
30 #define ___INCLUDED_FROM_OS
31 #define ___VERSION 406003
45 /**********************************/
47 #ifdef ___DEBUG_ALLOC_MEM_TRACE
48 #define ___alloc_mem(bytes) ___alloc_mem_debug(bytes,__LINE__,__FILE__)
53 /*---------------------------------------------------------------------------*/
55 #define NBELEMS(table)(sizeof (table) / sizeof (table[0]))
58 /*---------------------------------------------------------------------------*/
61 ___SCMOBJ ___setup_os_interrupt_handling ___PVOID
65 if ((e
= ___setup_heartbeat_interrupt_handling ()) == ___FIX(___NO_ERR
))
67 if ((e
= ___setup_user_interrupt_handling ()) != ___FIX(___NO_ERR
))
68 ___cleanup_heartbeat_interrupt_handling ();
74 void ___cleanup_os_interrupt_handling ___PVOID
76 ___cleanup_user_interrupt_handling ();
77 ___cleanup_heartbeat_interrupt_handling ();
80 void ___disable_os_interrupts ___PVOID
82 ___disable_heartbeat_interrupts ();
83 ___disable_user_interrupts ();
86 void ___enable_os_interrupts ___PVOID
88 ___enable_user_interrupts ();
89 ___enable_heartbeat_interrupts ();
93 /*---------------------------------------------------------------------------*/
95 /* Virtual memory statistics. */
105 #ifndef USE_getrusage
107 *minflt
= 0; /* can't get statistics... result is 0 */
116 if (getrusage (RUSAGE_SELF
, &ru
) == 0)
118 *minflt
= ru
.ru_minflt
;
119 *majflt
= ru
.ru_majflt
;
123 *minflt
= 0; /* can't get statistics... result is 0 */
131 /*---------------------------------------------------------------------------*/
133 /* Formatting of source code position. */
135 char *___format_filepos
151 mac_gui_highlight (path
, filepos
);
157 return 0; /* Use default format for displaying location */
161 /* - - - - - - - - - - - - - - - - - - */
163 /* Miscellaneous networking utilities. */
165 #ifdef USE_NETWORKING
172 ___HIDDEN
int network_family_decode
194 ___HIDDEN ___SCMOBJ network_family_encode
212 return ___FIX(family
);
216 ___HIDDEN
int network_socktype_decode
243 ___HIDDEN ___SCMOBJ network_socktype_encode
266 return ___FIX(socktype
);
270 ___HIDDEN
int network_protocol_decode
292 ___HIDDEN ___SCMOBJ network_protocol_encode
310 return ___FIX(protocol
);
314 ___SCMOBJ ___SCMOBJ_to_in_addr
315 ___P((___SCMOBJ addr
,
326 ia
->s_addr
= htonl (INADDR_ANY
); /* wildcard address */
328 ia
->s_addr
= htonl ((___INT(___U8VECTORREF(addr
,___FIX(0)))<<24) +
329 (___INT(___U8VECTORREF(addr
,___FIX(1)))<<16) +
330 (___INT(___U8VECTORREF(addr
,___FIX(2)))<<8) +
331 ___INT(___U8VECTORREF(addr
,___FIX(3))));
333 return ___FIX(___NO_ERR
);
337 ___SCMOBJ ___in_addr_to_SCMOBJ
338 ___P((struct in_addr
*ia
,
348 a
= ntohl (ia
->s_addr
);
351 result
= ___FAL
; /* wildcard address */
354 result
= ___alloc_scmobj (___sU8VECTOR
, 4, ___STILL
);
356 if (___FIXNUMP(result
))
357 return ___FIX(___CTOS_HEAP_OVERFLOW_ERR
+arg_num
);
360 ___U8VECTORSET(result
,___FIX(0),___FIX((a
>>24) & 0xff))
361 ___U8VECTORSET(result
,___FIX(1),___FIX((a
>>16) & 0xff))
362 ___U8VECTORSET(result
,___FIX(2),___FIX((a
>>8) & 0xff))
363 ___U8VECTORSET(result
,___FIX(3),___FIX(a
& 0xff))
372 ___SCMOBJ ___SCMOBJ_to_in6_addr
373 ___P((___SCMOBJ addr
,
387 /* wildcard address */
391 ia
->s6_addr
[i
<<1] = 0;
392 ia
->s6_addr
[(i
<<1)+1] = 0;
399 ___U16 x
= ___INT(___U16VECTORREF(addr
,___FIX(i
)));
400 ia
->s6_addr
[i
<<1] = (x
>>8) & 0xff;
401 ia
->s6_addr
[(i
<<1)+1] = x
& 0xff;
405 return ___FIX(___NO_ERR
);
409 ___SCMOBJ ___in6_addr_to_SCMOBJ
410 ___P((struct in6_addr
*ia
,
421 if (ia
->s6_addr
[i
] != 0)
425 result
= ___FAL
; /* wildcard address */
428 result
= ___alloc_scmobj (___sU16VECTOR
, 8<<1, ___STILL
);
430 if (___FIXNUMP(result
))
431 return ___FIX(___CTOS_HEAP_OVERFLOW_ERR
+arg_num
);
437 ___FIX((___CAST(___U16
,ia
->s6_addr
[i
<<1])<<8) +
438 ia
->s6_addr
[(i
<<1)+1]))
447 ___SCMOBJ ___SCMOBJ_to_sockaddr
448 ___P((___SCMOBJ addr
,
465 ___SCMOBJ ___temp
; /* needed by the ___U8VECTORP and ___U16VECTORP macros */
467 if (addr
== ___FAL
|| ___U8VECTORP(addr
))
469 struct sockaddr_in
*sa_in
= ___CAST(struct sockaddr_in
*,sa
);
470 *salen
= sizeof (*sa_in
);
471 memset (sa_in
, 0, sizeof (*sa_in
));
472 sa_in
->sin_family
= AF_INET
;
473 sa_in
->sin_port
= htons (___INT(port_num
));
474 result
= ___SCMOBJ_to_in_addr (addr
, &sa_in
->sin_addr
, arg_num
);
477 else if (___U16VECTORP(addr
))
479 struct sockaddr_in6
*sa_in6
= ___CAST(struct sockaddr_in6
*,sa
);
480 *salen
= sizeof (*sa_in6
);
481 memset (sa_in6
, 0, sizeof (*sa_in6
));
482 sa_in6
->sin6_family
= AF_INET6
;
483 sa_in6
->sin6_port
= htons (___INT(port_num
));
484 result
= ___SCMOBJ_to_in6_addr (addr
, &sa_in6
->sin6_addr
, arg_num
);
488 result
= ___FIX(___UNKNOWN_ERR
);
494 ___SCMOBJ ___sockaddr_to_SCMOBJ
495 ___P((struct sockaddr
*sa
,
507 result
= ___make_vector (4, ___FAL
, ___STILL
);
509 if (___FIXNUMP(result
))
510 return ___FIX(___CTOS_HEAP_OVERFLOW_ERR
+arg_num
);
512 if (salen
== sizeof (struct sockaddr_in
))
514 struct sockaddr_in
*sa_in
= ___CAST(struct sockaddr_in
*,sa
);
515 ___SCMOBJ addr
= ___in_addr_to_SCMOBJ (&sa_in
->sin_addr
, arg_num
);
517 if (___FIXNUMP(addr
))
519 ___release_scmobj (result
);
523 ___FIELD(result
,1) = network_family_encode (sa_in
->sin_family
);
524 ___FIELD(result
,2) = ___FIX(ntohs (sa_in
->sin_port
));
525 ___FIELD(result
,3) = addr
;
526 ___release_scmobj (addr
);
529 else if (salen
== sizeof (struct sockaddr_in6
))
531 struct sockaddr_in6
*sa_in6
= ___CAST(struct sockaddr_in6
*,sa
);
532 ___SCMOBJ addr
= ___in6_addr_to_SCMOBJ (&sa_in6
->sin6_addr
, arg_num
);
534 if (___FIXNUMP(addr
))
536 ___release_scmobj (result
);
540 ___FIELD(result
,1) = network_family_encode (sa_in6
->sin6_family
);
541 ___FIELD(result
,2) = ___FIX(ntohs (sa_in6
->sin6_port
));
542 ___FIELD(result
,3) = addr
;
543 ___release_scmobj (addr
);
549 ___release_scmobj (result
);
555 ___SCMOBJ ___addr_to_SCMOBJ
570 struct in_addr
*ia
= ___CAST(struct in_addr
*,sa
);
573 result
= ___alloc_scmobj (___sU8VECTOR
, 4, ___STILL
);
575 if (___FIXNUMP(result
))
576 return ___FIX(___CTOS_HEAP_OVERFLOW_ERR
+arg_num
);
578 a
= ntohl (ia
->s_addr
);
580 ___U8VECTORSET(result
,___FIX(0),___FIX((a
>>24)&0xff))
581 ___U8VECTORSET(result
,___FIX(1),___FIX((a
>>16)&0xff))
582 ___U8VECTORSET(result
,___FIX(2),___FIX((a
>>8)&0xff))
583 ___U8VECTORSET(result
,___FIX(3),___FIX(a
&0xff))
586 else if (salen
== 16)
588 struct in6_addr
*ia
= ___CAST(struct in6_addr
*,sa
);
591 result
= ___alloc_scmobj (___sU16VECTOR
, 8<<1, ___STILL
);
593 if (___FIXNUMP(result
))
594 return ___FIX(___CTOS_HEAP_OVERFLOW_ERR
+arg_num
);
597 ___U16VECTORSET(result
,
599 ___FIX((___CAST(___U16
,ia
->s6_addr
[i
<<1])<<8)
600 +ia
->s6_addr
[(i
<<1)+1]))
606 ___release_scmobj (result
);
614 /* - - - - - - - - - - - - - - - - - - */
616 /* Access to host information. */
618 #ifdef USE_getaddrinfo
620 ___HIDDEN
int ai_flags_decode
629 ai_flags
|= AI_PASSIVE
;
634 ai_flags
|= AI_CANONNAME
;
637 #ifdef AI_NUMERICHOST
639 ai_flags
|= AI_NUMERICHOST
;
642 #ifdef AI_NUMERICSERV
644 ai_flags
|= AI_NUMERICSERV
;
654 ai_flags
|= AI_ADDRCONFIG
;
659 ai_flags
|= AI_V4MAPPED
;
668 ___SCMOBJ ___os_address_infos
669 ___P((___SCMOBJ host
,
688 #ifndef USE_getaddrinfo
690 return ___FIX(___UNIMPL_ERR
);
694 #ifdef USE_getaddrinfo
706 struct addrinfo hints
, *res
, *res0
;
709 if ((e
= ___SCMOBJ_to_CHARSTRING (host
, &chost
, 1))
710 != ___FIX(___NO_ERR
))
713 if ((e
= ___SCMOBJ_to_CHARSTRING (serv
, &cserv
, 2))
714 != ___FIX(___NO_ERR
))
716 ___release_string (chost
);
720 memset (&hints
, 0, sizeof (hints
));
722 hints
.ai_flags
= ai_flags_decode (___INT(flags
));
723 hints
.ai_family
= network_family_decode (___INT(family
));
724 hints
.ai_socktype
= network_socktype_decode (___INT(socktype
));
725 hints
.ai_protocol
= network_protocol_decode (___INT(protocol
));
727 code
= getaddrinfo (chost
, cserv
, &hints
, &res0
);
731 e
= err_code_from_gai_code (code
);
732 ___release_string (chost
);
733 ___release_string (cserv
);
740 for (res
= res0
; res
!= NULL
; res
= res
->ai_next
)
742 x
= ___sockaddr_to_SCMOBJ (res
->ai_addr
,
748 ___release_scmobj (lst
);
755 vect
= ___make_vector (5, ___FAL
, ___STILL
);
757 if (___FIXNUMP(vect
))
759 ___release_scmobj (x
);
760 ___release_scmobj (lst
);
762 return ___FIX(___CTOS_HEAP_OVERFLOW_ERR
+___RETURN_POS
);
765 ___FIELD(vect
,1) = network_family_encode (res
->ai_family
);
766 ___FIELD(vect
,2) = network_socktype_encode (res
->ai_socktype
);
767 ___FIELD(vect
,3) = network_protocol_encode (res
->ai_protocol
);
768 ___FIELD(vect
,4) = x
;
770 ___release_scmobj (x
);
772 p
= ___make_pair (vect
, ___NUL
, ___STILL
);
774 ___release_scmobj (vect
);
778 ___release_scmobj (lst
);
780 return ___FIX(___CTOS_HEAP_OVERFLOW_ERR
+___RETURN_POS
);
792 ___release_scmobj (lst
);
796 ___release_string (chost
);
797 ___release_string (cserv
);
805 ___SCMOBJ ___os_host_info
806 ___P((___SCMOBJ host
),
810 #ifndef USE_gethostbyname
812 return ___FIX(___UNIMPL_ERR
);
816 #ifdef USE_gethostbyname
824 struct hostent
*he
= 0;
827 ___SCMOBJ ___temp
; /* needed by the ___U8VECTORP and ___U16VECTORP macros */
831 errno
= 0; /* in case the h_errno ends up being NETDB_SUCCESS
832 * incorrectly which will be treated as NETDB_INTERNAL
833 * (see err_code_from_h_errno)
838 #ifdef USE_gethostbyaddr
840 if (___U8VECTORP(host
))
844 if ((e
= ___SCMOBJ_to_in_addr (host
, &ia
, 1)) != ___FIX(___NO_ERR
))
847 he
= gethostbyaddr (___CAST(char*,&ia
), 4, AF_INET
);
850 else if (___U16VECTORP(host
))
854 if ((e
= ___SCMOBJ_to_in6_addr (host
, &ia
, 1)) != ___FIX(___NO_ERR
))
857 he
= gethostbyaddr (___CAST(char*,&ia
), 16, AF_INET6
);
866 * Convert the Scheme string to a C "char*" string. If an
867 * invalid character is seen then return an error.
870 if ((e
= ___SCMOBJ_to_NONNULLCHARSTRING (host
, &chost
, 1))
871 != ___FIX(___NO_ERR
))
879 if (inet_pton (AF_INET
, chost
, &ia
) == 1)
880 he
= gethostbyaddr (___CAST(char*,&ia
), 4, AF_INET
);
889 if (inet_pton (AF_INET6
, chost
, &ia
) == 1)
890 he
= gethostbyaddr (___CAST(char*,&ia
), 16, AF_INET6
);
900 he
= gethostbyname (chost
);
907 e
= err_code_from_h_errno ();
911 e
= err_code_from_WSAGetLastError ();
915 ___release_string (chost
);
917 if (e
!= ___FIX(___NO_ERR
))
920 vect
= ___make_vector (4, ___FAL
, ___STILL
);
922 if (___FIXNUMP(vect
))
923 return ___FIX(___CTOS_HEAP_OVERFLOW_ERR
+___RETURN_POS
);
925 /* convert h_name to string */
927 if ((e
= ___CHARSTRING_to_SCMOBJ
928 (___CAST(char*,he
->h_name
),
931 != ___FIX(___NO_ERR
))
933 ___release_scmobj (vect
);
937 ___FIELD(vect
,1) = x
;
938 ___release_scmobj (x
);
940 /* convert h_aliases to strings */
943 while (he
->h_aliases
[i
] != 0)
949 if ((e
= ___CHARSTRING_to_SCMOBJ
950 (___CAST(char*,he
->h_aliases
[i
]),
953 != ___FIX(___NO_ERR
))
955 ___release_scmobj (lst
);
956 ___release_scmobj (vect
);
960 p
= ___make_pair (x
, lst
, ___STILL
);
962 ___release_scmobj (x
);
963 ___release_scmobj (lst
);
967 ___release_scmobj (vect
);
968 return ___FIX(___CTOS_HEAP_OVERFLOW_ERR
+___RETURN_POS
);
974 ___FIELD(vect
,2) = lst
;
975 ___release_scmobj (lst
);
977 /* convert h_addr_list to u8/u16vectors */
980 while (he
->h_addr_list
[i
] != 0)
986 switch (he
->h_addrtype
)
990 x
= ___in_addr_to_SCMOBJ
991 (___CAST(struct in_addr
*,he
->h_addr_list
[i
]),
999 x
= ___in6_addr_to_SCMOBJ
1000 (___CAST(struct in6_addr
*,he
->h_addr_list
[i
]),
1008 continue; /* ignore unknown address families */
1013 ___release_scmobj (lst
);
1014 ___release_scmobj (vect
);
1018 p
= ___make_pair (x
, lst
, ___STILL
);
1020 ___release_scmobj (x
);
1021 ___release_scmobj (lst
);
1025 ___release_scmobj (vect
);
1026 return ___FIX(___CTOS_HEAP_OVERFLOW_ERR
+___RETURN_POS
);
1032 ___FIELD(vect
,3) = lst
;
1033 ___release_scmobj (lst
);
1034 ___release_scmobj (vect
);
1036 /* guarantee that at least one address is returned */
1039 return ___FIX(___H_ERRNO_ERR(NO_ADDRESS
));
1047 ___SCMOBJ ___os_host_name ___PVOID
1049 #ifndef USE_gethostname
1051 return ___FIX(___UNIMPL_ERR
);
1055 #ifdef USE_gethostname
1057 #define HOSTNAME_MAX_LEN 1024
1061 char name
[HOSTNAME_MAX_LEN
];
1063 if (gethostname (name
, HOSTNAME_MAX_LEN
) < 0)
1064 return err_code_from_errno ();
1066 if ((e
= ___NONNULLCHARSTRING_to_SCMOBJ (name
, &result
, ___RETURN_POS
))
1067 != ___FIX(___NO_ERR
))
1070 ___release_scmobj (result
);
1078 /* - - - - - - - - - - - - - - - - - - */
1080 /* Access to service information. */
1082 ___SCMOBJ ___os_service_info
1083 ___P((___SCMOBJ service
,
1084 ___SCMOBJ protocol
),
1088 ___SCMOBJ protocol
;)
1090 #ifndef USE_getservbyname
1092 return ___FIX(___UNIMPL_ERR
);
1096 #ifdef USE_getservbyname
1109 * Convert the Scheme string to a C "char*" string. If an invalid
1110 * character is seen then return an error.
1113 if (!___FIXNUMP(service
))
1114 if ((e
= ___SCMOBJ_to_NONNULLCHARSTRING (service
, &cservice
, 1))
1115 != ___FIX(___NO_ERR
))
1118 if ((e
= ___SCMOBJ_to_CHARSTRING (protocol
, &cprotocol
, 2))
1119 != ___FIX(___NO_ERR
))
1121 if (!___FIXNUMP(service
))
1122 ___release_string (cservice
);
1128 errno
= 0; /* in case the h_errno ends up being NETDB_SUCCESS
1129 * incorrectly which will be treated as NETDB_INTERNAL
1130 * (see err_code_from_h_errno)
1135 if (___FIXNUMP(service
))
1136 se
= getservbyport (htons (___INT(service
)), cprotocol
);
1138 se
= getservbyname (cservice
, cprotocol
);
1144 e
= err_code_from_h_errno ();
1150 e
= err_code_from_WSAGetLastError ();
1156 ___release_string (cprotocol
);
1158 if (!___FIXNUMP(service
))
1159 ___release_string (cservice
);
1161 if (e
!= ___FIX(___NO_ERR
))
1164 vect
= ___make_vector (5, ___FAL
, ___STILL
);
1166 if (___FIXNUMP(vect
))
1167 return ___FIX(___CTOS_HEAP_OVERFLOW_ERR
+___RETURN_POS
);/************/
1169 /* convert s_name to string */
1171 if ((e
= ___CHARSTRING_to_SCMOBJ (se
->s_name
, &x
, ___RETURN_POS
))
1172 != ___FIX(___NO_ERR
))
1174 ___release_scmobj (vect
);
1178 ___FIELD(vect
,1) = x
;
1179 ___release_scmobj (x
);
1181 /* convert s_aliases to strings */
1184 while (se
->s_aliases
[i
] != 0)
1190 if ((e
= ___CHARSTRING_to_SCMOBJ (se
->s_aliases
[i
], &x
, ___RETURN_POS
))
1191 != ___FIX(___NO_ERR
))
1193 ___release_scmobj (lst
);
1194 ___release_scmobj (vect
);
1198 p
= ___make_pair (x
, lst
, ___STILL
);
1200 ___release_scmobj (x
);
1201 ___release_scmobj (lst
);
1205 ___release_scmobj (vect
);
1206 return ___FIX(___CTOS_HEAP_OVERFLOW_ERR
+___RETURN_POS
);/*******************/
1212 ___FIELD(vect
,2) = lst
;
1213 ___release_scmobj (lst
);
1215 /* convert s_port to integer */
1217 ___FIELD(vect
,3) = ___FIX(ntohs (se
->s_port
));
1219 /* convert s_name to string */
1221 if ((e
= ___CHARSTRING_to_SCMOBJ (se
->s_proto
, &x
, ___RETURN_POS
))
1222 != ___FIX(___NO_ERR
))
1224 ___release_scmobj (vect
);
1228 ___FIELD(vect
,4) = x
;
1229 ___release_scmobj (x
);
1231 ___release_scmobj (vect
);
1239 /* - - - - - - - - - - - - - - - - - - */
1241 /* Access to protocol information. */
1243 ___SCMOBJ ___os_protocol_info
1244 ___P((___SCMOBJ protocol
),
1246 ___SCMOBJ protocol
;)
1248 #ifndef USE_getprotobyname
1250 return ___FIX(___UNIMPL_ERR
);
1254 #ifdef USE_getprotobyname
1256 ___SCMOBJ e
= ___FIX(___NO_ERR
);
1262 struct protoent
*pe
;
1266 * Convert the Scheme string to a C "char*" string. If an invalid
1267 * character is seen then return an error.
1270 if (!___FIXNUMP(protocol
))
1271 if ((e
= ___SCMOBJ_to_NONNULLCHARSTRING (protocol
, &cprotocol
, 1))
1272 != ___FIX(___NO_ERR
))
1277 errno
= 0; /* in case the h_errno ends up being NETDB_SUCCESS
1278 * incorrectly which will be treated as NETDB_INTERNAL
1279 * (see err_code_from_h_errno)
1284 if (___FIXNUMP(protocol
))
1285 pe
= getprotobynumber (___INT(protocol
));
1287 pe
= getprotobyname (cprotocol
);
1293 e
= err_code_from_h_errno ();
1299 e
= err_code_from_WSAGetLastError ();
1304 if (!___FIXNUMP(protocol
))
1305 ___release_string (cprotocol
);
1307 if (e
!= ___FIX(___NO_ERR
))
1310 vect
= ___make_vector (4, ___FAL
, ___STILL
);
1312 if (___FIXNUMP(vect
))
1313 return ___FIX(___CTOS_HEAP_OVERFLOW_ERR
+___RETURN_POS
);/************/
1315 /* convert p_name to string */
1317 if ((e
= ___CHARSTRING_to_SCMOBJ (pe
->p_name
, &x
, ___RETURN_POS
))
1318 != ___FIX(___NO_ERR
))
1320 ___release_scmobj (vect
);
1324 ___FIELD(vect
,1) = x
;
1325 ___release_scmobj (x
);
1327 /* convert p_aliases to strings */
1330 while (pe
->p_aliases
[i
] != 0)
1336 if ((e
= ___CHARSTRING_to_SCMOBJ (pe
->p_aliases
[i
], &x
, ___RETURN_POS
))
1337 != ___FIX(___NO_ERR
))
1339 ___release_scmobj (lst
);
1340 ___release_scmobj (vect
);
1344 p
= ___make_pair (x
, lst
, ___STILL
);
1346 ___release_scmobj (x
);
1347 ___release_scmobj (lst
);
1351 ___release_scmobj (vect
);
1352 return ___FIX(___CTOS_HEAP_OVERFLOW_ERR
+___RETURN_POS
);/*******************/
1358 ___FIELD(vect
,2) = lst
;
1359 ___release_scmobj (lst
);
1361 /* convert p_proto to integer */
1363 ___FIELD(vect
,3) = ___FIX(pe
->p_proto
);
1365 ___release_scmobj (vect
);
1373 /* - - - - - - - - - - - - - - - - - - */
1375 /* Access to network information. */
1377 ___SCMOBJ ___os_network_info
1378 ___P((___SCMOBJ network
),
1382 #ifndef USE_getnetbyname
1384 return ___FIX(___UNIMPL_ERR
);
1388 return ___FIX(___UNIMPL_ERR
);
1394 /* - - - - - - - - - - - - - - - - - - */
1396 /* Access to file information. */
1398 ___SCMOBJ ___os_file_info
1399 ___P((___SCMOBJ path
,
1412 #ifndef USE_GetFileAttributesEx
1414 #define ___INFO_PATH_CE_SELECT(latin1,utf8,ucs2,ucs4,wchar,native) native
1416 if ((e
= ___SCMOBJ_to_NONNULLSTRING
1420 ___CE(___INFO_PATH_CE_SELECT
),
1422 == ___FIX(___NO_ERR
))
1424 ___FILE
*check_exist
= ___fopen (cpath
, "r");
1426 if (check_exist
== 0)
1428 e
= fnf_or_err_code_from_errno ();
1429 ___release_string (cpath
);
1433 ___fclose (check_exist
);
1435 ___release_string (cpath
);
1437 result
= ___make_vector (14, ___FAL
, ___STILL
);
1439 if (___FIXNUMP(result
))
1440 return ___FIX(___CTOS_HEAP_OVERFLOW_ERR
+___RETURN_POS
);/**********/
1442 ___FIELD(result
,1) = ___FIX(0); /* unknown type */
1443 ___FIELD(result
,2) = ___FIX(0);
1444 ___FIELD(result
,3) = ___FIX(0);
1445 ___FIELD(result
,4) = ___FIX(0);
1446 ___FIELD(result
,5) = ___FIX(0);
1447 ___FIELD(result
,6) = ___FIX(0);
1448 ___FIELD(result
,7) = ___FIX(0);
1449 ___FIELD(result
,8) = ___FIX(0);
1451 if ((e
= ___F64_to_SCMOBJ (___CAST(___F64
,NEG_INFINITY
),
1454 != ___FIX(___NO_ERR
))
1456 ___release_scmobj (result
);
1460 ___FIELD(result
,9) = x
;
1461 ___FIELD(result
,10) = x
;
1462 ___FIELD(result
,11) = x
;
1463 ___FIELD(result
,12) = ___FIX(0);
1464 ___FIELD(result
,13) = x
;
1466 ___release_scmobj (x
);
1468 ___release_scmobj (result
);
1478 #define ___INFO_PATH_CE_SELECT(latin1,utf8,ucs2,ucs4,wchar,native) native
1480 if ((e
= ___SCMOBJ_to_NONNULLSTRING
1484 ___CE(___INFO_PATH_CE_SELECT
),
1486 == ___FIX(___NO_ERR
))
1490 if (((chase
== ___FAL
)
1491 ? ___lstat (___CAST(___STRING_TYPE(___INFO_PATH_CE_SELECT
),cpath
), &s
)
1492 : ___stat (___CAST(___STRING_TYPE(___INFO_PATH_CE_SELECT
),cpath
), &s
))
1495 e
= fnf_or_err_code_from_errno ();
1496 ___release_string (cpath
);
1500 ___release_string (cpath
);
1502 result
= ___make_vector (14, ___FAL
, ___STILL
);
1504 if (___FIXNUMP(result
))
1505 return ___FIX(___CTOS_HEAP_OVERFLOW_ERR
+___RETURN_POS
);/**********/
1507 if (S_ISREG(s
.st_mode
))
1508 ___FIELD(result
,1) = ___FIX(1);
1509 else if (S_ISDIR(s
.st_mode
))
1510 ___FIELD(result
,1) = ___FIX(2);
1511 else if (S_ISCHR(s
.st_mode
))
1512 ___FIELD(result
,1) = ___FIX(3);
1513 else if (S_ISBLK(s
.st_mode
))
1514 ___FIELD(result
,1) = ___FIX(4);
1515 else if (S_ISFIFO(s
.st_mode
))
1516 ___FIELD(result
,1) = ___FIX(5);
1517 else if (S_ISLNK(s
.st_mode
))
1518 ___FIELD(result
,1) = ___FIX(6);
1519 else if (S_ISSOCK(s
.st_mode
))
1520 ___FIELD(result
,1) = ___FIX(7);
1522 ___FIELD(result
,1) = ___FIX(0);
1524 if ((e
= ___ULONGLONG_to_SCMOBJ (___CAST(___ULONGLONG
,s
.st_dev
),
1527 != ___FIX(___NO_ERR
))
1529 ___release_scmobj (result
);
1533 ___FIELD(result
,2) = x
;
1534 ___release_scmobj (x
);
1536 if ((e
= ___LONGLONG_to_SCMOBJ (___CAST(___LONGLONG
,s
.st_ino
),
1539 != ___FIX(___NO_ERR
))
1541 ___release_scmobj (result
);
1545 ___FIELD(result
,3) = x
;
1546 ___release_scmobj (x
);
1548 ___FIELD(result
,4) =
1549 ___FIX(s
.st_mode
& (S_ISUID
|S_ISGID
|S_ISVTX
|S_IRWXU
|S_IRWXG
|S_IRWXO
));
1551 if ((e
= ___ULONGLONG_to_SCMOBJ (___CAST(___ULONGLONG
,s
.st_nlink
),
1554 != ___FIX(___NO_ERR
))
1556 ___release_scmobj (result
);
1560 ___FIELD(result
,5) = x
;
1561 ___release_scmobj (x
);
1563 ___FIELD(result
,6) = ___FIX(s
.st_uid
);
1565 ___FIELD(result
,7) = ___FIX(s
.st_gid
);
1567 if ((e
= ___LONGLONG_to_SCMOBJ (___CAST(___LONGLONG
,s
.st_size
),
1570 != ___FIX(___NO_ERR
))
1572 ___release_scmobj (result
);
1576 ___FIELD(result
,8) = x
;
1577 ___release_scmobj (x
);
1579 if ((e
= ___F64_to_SCMOBJ (___CAST(___F64
,s
.st_atime
), &x
, ___RETURN_POS
))
1580 != ___FIX(___NO_ERR
))
1582 ___release_scmobj (result
);
1586 ___FIELD(result
,9) = x
;
1587 ___release_scmobj (x
);
1589 if ((e
= ___F64_to_SCMOBJ (___CAST(___F64
,s
.st_mtime
), &x
, ___RETURN_POS
))
1590 != ___FIX(___NO_ERR
))
1592 ___release_scmobj (result
);
1596 ___FIELD(result
,10) = x
;
1597 ___release_scmobj (x
);
1599 if ((e
= ___F64_to_SCMOBJ (___CAST(___F64
,s
.st_ctime
), &x
, ___RETURN_POS
))
1600 != ___FIX(___NO_ERR
))
1602 ___release_scmobj (result
);
1606 ___FIELD(result
,11) = x
;
1607 ___release_scmobj (x
);
1609 #ifndef FILE_ATTRIBUTE_READ_ONLY
1610 #define FILE_ATTRIBUTE_READ_ONLY 1
1613 #ifndef FILE_ATTRIBUTE_DIRECTORY
1614 #define FILE_ATTRIBUTE_DIRECTORY 16
1617 #ifndef FILE_ATTRIBUTE_NORMAL
1618 #define FILE_ATTRIBUTE_NORMAL 128
1621 ___FIELD(result
,12) =
1622 ___FIX(S_ISDIR(s
.st_mode
)
1623 ? FILE_ATTRIBUTE_DIRECTORY
1624 : FILE_ATTRIBUTE_NORMAL
);
1626 if ((e
= ___F64_to_SCMOBJ (___CAST(___F64
,NEG_INFINITY
),
1629 != ___FIX(___NO_ERR
))
1631 ___release_scmobj (result
);
1635 ___FIELD(result
,13) = x
;
1636 ___release_scmobj (x
);
1638 ___release_scmobj (result
);
1645 #ifdef USE_GetFileAttributesEx
1648 #define ___INFO_PATH_CE_SELECT(latin1,utf8,ucs2,ucs4,wchar,native) ucs2
1650 #define ___INFO_PATH_CE_SELECT(latin1,utf8,ucs2,ucs4,wchar,native) native
1653 if ((e
= ___SCMOBJ_to_NONNULLSTRING
1657 ___CE(___INFO_PATH_CE_SELECT
),
1659 == ___FIX(___NO_ERR
))
1661 WIN32_FILE_ATTRIBUTE_DATA fad
;
1663 if (!GetFileAttributesEx
1664 (___CAST(___STRING_TYPE(___INFO_PATH_CE_SELECT
),cpath
),
1665 GetFileExInfoStandard
,
1668 e
= err_code_from_GetLastError ();
1669 ___release_string (cpath
);
1673 ___release_string (cpath
);
1675 result
= ___make_vector (14, ___FAL
, ___STILL
);
1677 if (___FIXNUMP(result
))
1678 return ___FIX(___CTOS_HEAP_OVERFLOW_ERR
+___RETURN_POS
);/**********/
1680 if (fad
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
1681 ___FIELD(result
,1) = ___FIX(2);
1683 ___FIELD(result
,1) = ___FIX(1);
1685 ___FIELD(result
,2) = ___FIX(0);
1686 ___FIELD(result
,3) = ___FIX(0);
1688 if (fad
.dwFileAttributes
& FILE_ATTRIBUTE_READONLY
)
1689 ___FIELD(result
,4) = ___FIX(0333);
1691 ___FIELD(result
,4) = ___FIX(0777);
1693 ___FIELD(result
,5) = ___FIX(1);
1694 ___FIELD(result
,6) = ___FIX(0);
1695 ___FIELD(result
,7) = ___FIX(0);
1697 if ((e
= ___U64_to_SCMOBJ
1698 (___U64_from_UM32_UM32(fad
.nFileSizeHigh
,fad
.nFileSizeLow
),
1701 != ___FIX(___NO_ERR
))
1703 ___release_scmobj (result
);
1707 ___FIELD(result
,8) = x
;
1708 ___release_scmobj (x
);
1710 if ((e
= ___F64_to_SCMOBJ
1711 (___CAST(___F64
,FILETIME_TO_TIME(fad
.ftLastAccessTime
)),
1714 != ___FIX(___NO_ERR
))
1716 ___release_scmobj (result
);
1720 ___FIELD(result
,9) = x
;
1721 ___release_scmobj (x
);
1723 if ((e
= ___F64_to_SCMOBJ
1724 (___CAST(___F64
,FILETIME_TO_TIME(fad
.ftLastWriteTime
)),
1727 != ___FIX(___NO_ERR
))
1729 ___release_scmobj (result
);
1733 ___FIELD(result
,10) = x
;
1734 ___FIELD(result
,11) = x
;
1735 ___release_scmobj (x
);
1737 ___FIELD(result
,12) = ___FIX(fad
.dwFileAttributes
);
1739 if ((e
= ___F64_to_SCMOBJ
1740 (___CAST(___F64
,FILETIME_TO_TIME(fad
.ftCreationTime
)),
1743 != ___FIX(___NO_ERR
))
1745 ___release_scmobj (result
);
1749 ___FIELD(result
,13) = x
;
1750 ___release_scmobj (x
);
1752 ___release_scmobj (result
);
1763 /* - - - - - - - - - - - - - - - - - - */
1765 /* Access to user information. */
1767 ___SCMOBJ ___os_user_info
1768 ___P((___SCMOBJ user
),
1772 ___SCMOBJ e
= ___FIX(___NO_ERR
);
1777 #ifndef USE_getpwnam
1779 return ___FIX(___UNIMPL_ERR
);
1787 #define ___USER_CE_SELECT(latin1,utf8,ucs2,ucs4,wchar,native) native
1789 if (___FIXNUMP(user
) ||
1790 (e
= ___SCMOBJ_to_NONNULLSTRING
1794 ___CE(___USER_CE_SELECT
),
1796 == ___FIX(___NO_ERR
))
1798 if (___FIXNUMP(user
))
1800 if ((p
= getpwuid (___INT(user
)))
1803 e
= err_code_from_errno ();
1809 if ((p
= getpwnam (___CAST(___STRING_TYPE(___USER_CE_SELECT
),cuser
)))
1812 e
= err_code_from_errno ();
1813 ___release_string (cuser
);
1817 ___release_string (cuser
);
1820 result
= ___make_vector (6, ___FAL
, ___STILL
);
1822 if (___FIXNUMP(result
))
1823 return ___FIX(___CTOS_HEAP_OVERFLOW_ERR
+___RETURN_POS
);/**********/
1825 if ((e
= ___NONNULLCHARSTRING_to_SCMOBJ
1829 != ___FIX(___NO_ERR
))
1831 ___release_scmobj (result
);
1835 ___FIELD(result
,1) = x
;
1836 ___release_scmobj (x
);
1838 ___FIELD(result
,2) = ___FIX(p
->pw_uid
);
1840 ___FIELD(result
,3) = ___FIX(p
->pw_gid
);
1842 if ((e
= ___NONNULLCHARSTRING_to_SCMOBJ
1846 != ___FIX(___NO_ERR
))
1848 ___release_scmobj (result
);
1852 ___FIELD(result
,4) = x
;
1853 ___release_scmobj (x
);
1855 if ((e
= ___NONNULLCHARSTRING_to_SCMOBJ
1859 != ___FIX(___NO_ERR
))
1861 ___release_scmobj (result
);
1865 ___FIELD(result
,5) = x
;
1866 ___release_scmobj (x
);
1868 ___release_scmobj (result
);
1879 ___SCMOBJ ___os_user_name ___PVOID
1883 ___UCS_2STRING cstr
;
1887 static ___UCS_2 cvar
[] =
1888 { 'U', 'S', 'E', 'R', 'N', 'A', 'M', 'E', '\0' };
1892 static ___UCS_2 cvar
[] =
1893 { 'U', 'S', 'E', 'R', '\0' };
1897 if ((e
= ___getenv_UCS_2 (cvar
, &cstr
)) != ___FIX(___NO_ERR
))
1901 if ((e
= ___UCS_2STRING_to_SCMOBJ
1905 != ___FIX(___NO_ERR
))
1908 ___release_scmobj (result
);
1918 /* - - - - - - - - - - - - - - - - - - */
1920 /* Access to group information. */
1922 ___SCMOBJ ___os_group_info
1923 ___P((___SCMOBJ group
),
1927 ___SCMOBJ e
= ___FIX(___NO_ERR
);
1932 #ifndef USE_getgrnam
1934 return ___FIX(___UNIMPL_ERR
);
1942 #define ___GROUP_CE_SELECT(latin1,utf8,ucs2,ucs4,wchar,native) native
1944 if (___FIXNUMP(group
) ||
1945 (e
= ___SCMOBJ_to_NONNULLSTRING
1949 ___CE(___GROUP_CE_SELECT
),
1951 == ___FIX(___NO_ERR
))
1953 if (___FIXNUMP(group
))
1955 if ((g
= getgrgid (___INT(group
)))
1958 e
= err_code_from_errno ();
1964 if ((g
= getgrnam (___CAST(___STRING_TYPE(___GROUP_CE_SELECT
),cgroup
)))
1967 e
= err_code_from_errno ();
1968 ___release_string (cgroup
);
1972 ___release_string (cgroup
);
1975 result
= ___make_vector (3, ___FAL
, ___STILL
);
1977 if (___FIXNUMP(result
))
1978 return ___FIX(___CTOS_HEAP_OVERFLOW_ERR
+___RETURN_POS
);/**********/
1980 if ((e
= ___NONNULLCHARSTRING_to_SCMOBJ
1984 != ___FIX(___NO_ERR
))
1986 ___release_scmobj (result
);
1990 ___FIELD(result
,1) = x
;
1991 ___release_scmobj (x
);
1993 ___FIELD(result
,2) = ___FIX(g
->gr_gid
);
1995 if ((e
= ___NONNULLCHARSTRINGLIST_to_SCMOBJ
1999 != ___FIX(___NO_ERR
))
2001 ___release_scmobj (result
);
2005 ___FIELD(result
,3) = x
;
2006 ___release_scmobj (x
);
2008 ___release_scmobj (result
);
2019 /* - - - - - - - - - - - - - - - - - - */
2021 /* Access to process information. */
2023 ___SCMOBJ ___os_getpid ___PVOID
2026 #ifndef USE_GetCurrentProcessId
2035 return ___FIX(getpid());
2039 #ifdef USE_GetCurrentProcessId
2041 return ___FIX(GetCurrentProcessId());
2047 ___SCMOBJ ___os_getppid ___PVOID
2057 return ___FIX(getppid());
2063 /*---------------------------------------------------------------------------*/
2065 /* System type information. */
2068 #ifndef ___SYS_TYPE_CPU
2069 #define ___SYS_TYPE_CPU "unknown"
2072 #ifndef ___SYS_TYPE_VENDOR
2073 #define ___SYS_TYPE_VENDOR "unknown"
2076 #ifndef ___SYS_TYPE_OS
2077 #define ___SYS_TYPE_OS "unknown"
2080 #ifndef ___CONFIGURE_COMMAND
2081 #define ___CONFIGURE_COMMAND "unknown"
2085 ___HIDDEN
char *os_sys_type
[] =
2086 { ___SYS_TYPE_CPU
, ___SYS_TYPE_VENDOR
, ___SYS_TYPE_OS
, NULL
};
2089 ___HIDDEN
char *os_sys_type_string
=
2090 ___SYS_TYPE_CPU
"-" ___SYS_TYPE_VENDOR
"-" ___SYS_TYPE_OS
;
2093 ___HIDDEN
char *configure_command_string
= ___CONFIGURE_COMMAND
;
2096 char **___os_system_type ___PVOID
2102 char *___os_system_type_string ___PVOID
2104 return os_sys_type_string
;
2108 char *___os_configure_command_string ___PVOID
2110 return configure_command_string
;
2114 /*---------------------------------------------------------------------------*/
2116 /* C compilation environment information. */
2119 #ifndef ___OBJ_EXTENSION
2120 #define ___OBJ_EXTENSION ".obj"
2123 #ifndef ___EXE_EXTENSION
2124 #define ___EXE_EXTENSION ".exe"
2127 #ifndef ___BAT_EXTENSION
2128 #define ___BAT_EXTENSION ".bat"
2132 ___HIDDEN
char *os_obj_extension_string
= ___OBJ_EXTENSION
;
2134 ___HIDDEN
char *os_exe_extension_string
= ___EXE_EXTENSION
;
2136 ___HIDDEN
char *os_bat_extension_string
= ___BAT_EXTENSION
;
2139 char *___os_obj_extension_string ___PVOID
2141 return os_obj_extension_string
;
2145 char *___os_exe_extension_string ___PVOID
2147 return os_exe_extension_string
;
2151 char *___os_bat_extension_string ___PVOID
2153 return os_bat_extension_string
;
2157 /*---------------------------------------------------------------------------*/
2160 ___HIDDEN
void heartbeat_intr ___PVOID
2162 /**** belongs elsewhere */
2163 ___raise_interrupt (___INTR_HEARTBEAT
);
2167 ___HIDDEN
void user_intr ___PVOID
2169 /**** belongs elsewhere */
2170 ___raise_interrupt (___INTR_USER
);
2174 ___HIDDEN
void terminate_intr ___PVOID
2176 /**** belongs elsewhere */
2177 ___raise_interrupt (___INTR_TERMINATE
);
2181 ___SCMOBJ ___setup_os ___PVOID
2186 * To perform correct cleanup when the program terminates an
2187 * "atexit (___cleanup)" is performed in "setup_io" in certain
2188 * environments. There must not be any possibility of program
2189 * termination through "exit (...)" between the "atexit (...)"
2190 * and the entry of "___setup_mem". This guarantees that
2191 * "___cleanup" does not access dangling pointers.
2194 if ((e
= ___setup_base_module ()) == ___FIX(___NO_ERR
))
2196 if ((e
= ___setup_time_module (heartbeat_intr
)) == ___FIX(___NO_ERR
))
2198 if ((e
= ___setup_shell_module ()) == ___FIX(___NO_ERR
))
2200 if ((e
= ___setup_files_module ()) == ___FIX(___NO_ERR
))
2202 if ((e
= ___setup_dyn_module ()) == ___FIX(___NO_ERR
))
2204 if ((e
= ___setup_tty_module (user_intr
, terminate_intr
)) == ___FIX(___NO_ERR
))
2206 if ((e
= ___setup_io_module ()) == ___FIX(___NO_ERR
))
2209 ___set_signal_handler (SIGPIPE
, SIG_IGN
); /***** belongs elsewhere */
2211 return ___FIX(___NO_ERR
);
2213 ___cleanup_tty_module ();
2215 ___cleanup_dyn_module ();
2217 ___cleanup_files_module ();
2219 ___cleanup_shell_module ();
2221 ___cleanup_time_module ();
2223 ___cleanup_base_module ();
2230 void ___cleanup_os ___PVOID
2232 ___cleanup_io_module ();
2233 ___cleanup_tty_module ();
2234 ___cleanup_dyn_module ();
2235 ___cleanup_files_module ();
2236 ___cleanup_shell_module ();
2237 ___cleanup_time_module ();
2238 ___cleanup_base_module ();
2242 /*---------------------------------------------------------------------------*/