1 /* 2 * system.h - Gauche system interface 3 * 4 * Copyright (c) 2000-2020 Shiro Kawai <shiro@acm.org> 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * 3. Neither the name of the authors nor the names of its contributors 18 * may be used to endorse or promote products derived from this 19 * software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 27 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 28 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 29 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 30 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 31 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #ifndef GAUCHE_SYSTEM_H 35 #define GAUCHE_SYSTEM_H 36 37 /* This file provides some OS abstraction layer for Gauche. */ 38 39 /*============================================================== 40 * System call wrapper 41 */ 42 43 /* Our rule of thumb is that we always restart system calls 44 * when it is interrupted prematurely. The following macro 45 * hides restarting. 46 */ 47 48 #define SCM_SYSCALL3(result, expr, check) \ 49 do { \ 50 (result) = (expr); \ 51 if ((check) && (errno == EINTR || errno == EPIPE)) { \ 52 ScmVM *vm__ = Scm_VM(); \ 53 int epipe__ = (errno == EPIPE); \ 54 errno = 0; \ 55 SCM_SIGCHECK(vm__); \ 56 if (epipe__) { \ 57 errno = EPIPE; \ 58 break; \ 59 } \ 60 } else { \ 61 break; \ 62 } \ 63 } while (1) 64 65 #define SCM_SYSCALL(result, expr) \ 66 SCM_SYSCALL3(result, expr, (result < 0)) 67 68 /*============================================================== 69 * Utility functions 70 */ 71 72 /* Some commonly-used utilities */ 73 74 SCM_EXTERN int Scm_GetPortFd(ScmObj port_or_fd, int needfd); 75 76 SCM_EXTERN off_t Scm_IntegerToOffset(ScmObj i); 77 SCM_EXTERN ScmObj Scm_OffsetToInteger(off_t o); 78 79 /*============================================================== 80 * Filesystem 81 */ 82 83 SCM_EXTERN ScmObj Scm_ReadDirectory(ScmString *pathname); 84 SCM_EXTERN ScmObj Scm_GetCwd(void); 85 86 #define SCM_PATH_ABSOLUTE (1L<<0) 87 #define SCM_PATH_EXPAND (1L<<1) 88 #define SCM_PATH_CANONICALIZE (1L<<2) 89 #define SCM_PATH_FOLLOWLINK (1L<<3) /* not supported yet */ 90 SCM_EXTERN ScmObj Scm_NormalizePathname(ScmString *pathname, int flags); 91 SCM_EXTERN ScmObj Scm_TmpDir(void); 92 SCM_EXTERN ScmObj Scm_DirName(ScmString *filename); 93 SCM_EXTERN ScmObj Scm_BaseName(ScmString *filename); 94 95 /* struct stat */ 96 #ifdef GAUCHE_WINDOWS 97 typedef struct __stat64 ScmStat; 98 #else /*!GAUCHE_WINDOWS*/ 99 typedef struct stat ScmStat; 100 #endif /*!GAUCHE_WINDOWS*/ 101 102 typedef struct ScmSysStatRec { 103 SCM_HEADER; 104 ScmStat statrec; 105 } ScmSysStat; 106 107 SCM_CLASS_DECL(Scm_SysStatClass); 108 #define SCM_CLASS_SYS_STAT (&Scm_SysStatClass) 109 #define SCM_SYS_STAT(obj) ((ScmSysStat*)(obj)) 110 #define SCM_SYS_STAT_P(obj) (SCM_XTYPEP(obj, SCM_CLASS_SYS_STAT)) 111 #define SCM_SYS_STAT_STAT(obj) (&SCM_SYS_STAT(obj)->statrec) 112 113 SCM_EXTERN ScmObj Scm_MakeSysStat(void); /* returns empty SysStat */ 114 115 /*============================================================== 116 * Time 117 */ 118 119 /* time_t 120 * NB: POSIX defines time_t to be a type to represent number of seconds 121 * since Epoch. It may be a structure. In Gauche we just convert it 122 * to a number. 123 */ 124 SCM_EXTERN ScmObj Scm_MakeSysTime(time_t time); 125 SCM_EXTERN time_t Scm_GetSysTime(ScmObj val); 126 127 SCM_EXTERN void Scm_GetTimeOfDay(u_long *sec, u_long *usec); 128 SCM_EXTERN long Scm_CurrentMicroseconds(); 129 SCM_EXTERN int Scm_ClockGetTimeMonotonic(u_long *sec, u_long *nsec); 130 SCM_EXTERN int Scm_ClockGetResMonotonic(u_long *sec, u_long *nsec); 131 132 /* Gauche also has a <time> object, as specified in SRFI-18, SRFI-19 133 * and SRFI-21. It can be constructed from the basic system interface 134 * such as sys-time or sys-gettimeofday. 135 */ 136 typedef struct ScmTimeRec { 137 SCM_HEADER; 138 ScmObj type; /* 'time-utc by default. see SRFI-19 */ 139 int64_t sec; /* seconds */ 140 long nsec; /* nanoseconds */ 141 } ScmTime; 142 143 SCM_CLASS_DECL(Scm_TimeClass); 144 #define SCM_CLASS_TIME (&Scm_TimeClass) 145 #define SCM_TIME(obj) ((ScmTime*)obj) 146 #define SCM_TIMEP(obj) SCM_XTYPEP(obj, SCM_CLASS_TIME) 147 148 SCM_EXTERN ScmObj Scm_CurrentTime(void); 149 SCM_EXTERN ScmObj Scm_MakeTime(ScmObj type, long sec, long nsec); 150 SCM_EXTERN ScmObj Scm_MakeTime64(ScmObj type, int64_t sec, long nsec); 151 SCM_EXTERN ScmObj Scm_IntSecondsToTime(long sec); 152 SCM_EXTERN ScmObj Scm_Int64SecondsToTime(int64_t sec); 153 SCM_EXTERN ScmObj Scm_RealSecondsToTime(double sec); 154 SCM_EXTERN ScmObj Scm_TimeToSeconds(ScmTime *t); 155 156 /* struct timespec compatibility handling. MinGW32 runtime v3.21, at least, has 157 incompatible struct timespec. */ 158 #if defined(HAVE_STRUCT_TIMESPEC) && (!defined(GAUCHE_WINDOWS) || defined(__MINGW64_VERSION_MAJOR)) 159 typedef struct timespec ScmTimeSpec; 160 #else /*!(defined(HAVE_STRUCT_TIMESPEC) && (!defined(GAUCHE_WINDOWS) || defined(__MINGW64_VERSION_MAJOR)))*/ 161 typedef struct ScmTimeSpecRec { 162 time_t tv_sec; 163 long tv_nsec; 164 } ScmTimeSpec; 165 #endif /*!(defined(HAVE_STRUCT_TIMESPEC) && (!defined(GAUCHE_WINDOWS) || defined(__MINGW64_VERSION_MAJOR)))*/ 166 167 SCM_EXTERN ScmTimeSpec *Scm_GetTimeSpec(ScmObj t, ScmTimeSpec *spec); 168 169 /* sched_yield */ 170 SCM_EXTERN void Scm_YieldCPU(void); 171 172 /* struct tm */ 173 typedef struct ScmSysTmRec { 174 SCM_HEADER; 175 struct tm tm; 176 } ScmSysTm; 177 178 SCM_CLASS_DECL(Scm_SysTmClass); 179 #define SCM_CLASS_SYS_TM (&Scm_SysTmClass) 180 #define SCM_SYS_TM(obj) ((ScmSysTm*)(obj)) 181 #define SCM_SYS_TM_P(obj) (SCM_XTYPEP(obj, SCM_CLASS_SYS_TM)) 182 #define SCM_SYS_TM_TM(obj) SCM_SYS_TM(obj)->tm 183 184 SCM_EXTERN ScmObj Scm_MakeSysTm(struct tm *); 185 186 SCM_EXTERN int Scm_NanoSleep(const ScmTimeSpec *req, 187 ScmTimeSpec *rem); 188 189 #if !HAVE_UTIMENSAT 190 int utimensat(int, const char*, const ScmTimeSpec*, int); 191 # if !defined(AT_FDCWD) 192 # define AT_FDCWD -1 193 # endif 194 # if !defined(UTIME_NOW) 195 # define UTIME_NOW -1 196 # endif 197 # if !defined(UTIME_OMIT) 198 # define UTIME_OMIT -1 199 # endif 200 #endif /*!HAVE_UTIMENSAT*/ 201 202 /*============================================================== 203 * Groups and users 204 */ 205 206 /* struct group */ 207 typedef struct ScmSysGroupRec { 208 SCM_HEADER; 209 ScmObj name; 210 ScmObj gid; 211 ScmObj passwd; 212 ScmObj mem; 213 } ScmSysGroup; 214 215 SCM_CLASS_DECL(Scm_SysGroupClass); 216 #define SCM_CLASS_SYS_GROUP (&Scm_SysGroupClass) 217 #define SCM_SYS_GROUP(obj) ((ScmSysGroup*)(obj)) 218 #define SCM_SYS_GROUP_P(obj) (SCM_XTYPEP(obj, SCM_CLASS_SYS_GROUP)) 219 220 SCM_EXTERN ScmObj Scm_GetGroupById(gid_t gid); 221 SCM_EXTERN ScmObj Scm_GetGroupByName(ScmString *name); 222 223 /* struct passwd */ 224 typedef struct ScmSysPasswdRec { 225 SCM_HEADER; 226 ScmObj name; 227 ScmObj passwd; 228 ScmObj uid; 229 ScmObj gid; 230 ScmObj gecos; 231 ScmObj dir; 232 ScmObj shell; 233 ScmObj pwclass; 234 } ScmSysPasswd; 235 236 SCM_CLASS_DECL(Scm_SysPasswdClass); 237 #define SCM_CLASS_SYS_PASSWD (&Scm_SysPasswdClass) 238 #define SCM_SYS_PASSWD(obj) ((ScmSysPasswd*)(obj)) 239 #define SCM_SYS_PASSWD_P(obj) (SCM_XTYPEP(obj, SCM_CLASS_SYS_PASSWD)) 240 241 SCM_EXTERN ScmObj Scm_GetPasswdById(uid_t uid); 242 SCM_EXTERN ScmObj Scm_GetPasswdByName(ScmString *name); 243 244 /*============================================================== 245 * Program execution 246 */ 247 248 SCM_EXTERN int Scm_IsSugid(void); 249 250 /* flags for Scm_SysExec */ 251 enum { 252 SCM_EXEC_WITH_FORK = (1L<<0), /* fork() before exec(), i.e. spawn(). */ 253 SCM_EXEC_DETACHED = (1L<<1) /* try to detach from process group. 254 good for daemoninzing. */ 255 }; 256 257 SCM_EXTERN ScmObj Scm_SysExec(ScmString *file, ScmObj args, 258 ScmObj iomap, ScmSysSigset *mask, 259 ScmString *dir, int flags); 260 SCM_EXTERN int *Scm_SysPrepareFdMap(ScmObj iomap); 261 SCM_EXTERN void Scm_SysSwapFds(int *fds); 262 263 SCM_EXTERN void Scm_SysKill(ScmObj process, int signal); 264 SCM_EXTERN ScmObj Scm_SysWait(ScmObj process, int options); 265 266 /*============================================================== 267 * Select 268 */ 269 270 /* select */ 271 #ifdef HAVE_SELECT 272 typedef struct ScmSysFdsetRec { 273 SCM_HEADER; 274 int maxfd; 275 fd_set fdset; 276 } ScmSysFdset; 277 278 SCM_CLASS_DECL(Scm_SysFdsetClass); 279 #define SCM_CLASS_SYS_FDSET (&Scm_SysFdsetClass) 280 #define SCM_SYS_FDSET(obj) ((ScmSysFdset*)(obj)) 281 #define SCM_SYS_FDSET_P(obj) (SCM_XTYPEP(obj, SCM_CLASS_SYS_FDSET)) 282 283 SCM_EXTERN ScmObj Scm_SysSelect(ScmObj rfds, ScmObj wfds, ScmObj efds, 284 ScmObj timeout); 285 SCM_EXTERN ScmObj Scm_SysSelectX(ScmObj rfds, ScmObj wfds, ScmObj efds, 286 ScmObj timeout); 287 #else /*!HAVE_SELECT*/ 288 /* dummy definitions */ 289 typedef struct ScmHeaderRec ScmSysFdset; 290 #define SCM_SYS_FDSET(obj) (obj) 291 #define SCM_SYS_FDSET_P(obj) (FALSE) 292 #endif /*!HAVE_SELECT*/ 293 294 /*============================================================== 295 * Miscellaneous 296 */ 297 298 SCM_EXTERN int Scm_Mkstemp(char *tmpl); 299 SCM_EXTERN ScmObj Scm_SysMkstemp(ScmString *tmpl); 300 SCM_EXTERN ScmObj Scm_SysMkdtemp(ScmString *tmpl); 301 SCM_EXTERN ScmObj Scm_Environ(void); 302 SCM_EXTERN const char *Scm_GetEnv(const char *name); 303 SCM_EXTERN void Scm_SetEnv(const char *name, const char *value, int overwrite); 304 SCM_EXTERN void Scm_UnsetEnv(const char *name); 305 SCM_EXTERN void Scm_ClearEnv(void); 306 SCM_EXTERN int Scm_AvailableProcessors(void); 307 308 /*============================================================== 309 * Windows-specific utility functions 310 */ 311 312 #if defined(GAUCHE_WINDOWS) 313 /* special object to wrap windows handle */ 314 SCM_EXTERN ScmObj Scm_MakeWinHandle(HANDLE h, ScmObj type); 315 SCM_EXTERN int Scm_WinHandleP(ScmObj obj, ScmObj type); 316 SCM_EXTERN HANDLE Scm_WinHandle(ScmObj h, ScmObj type); 317 318 SCM_EXTERN ScmObj Scm_MakeWinProcess(HANDLE h); 319 SCM_EXTERN int Scm_WinProcessP(ScmObj p); 320 SCM_EXTERN pid_t Scm_WinProcessPID(ScmObj p); 321 SCM_EXTERN HANDLE Scm_WinProcess(ScmObj p); 322 323 SCM_EXTERN ScmObj Scm_WinGetPipeName(HANDLE h); 324 #endif /* GAUCHE_WINDOWS */ 325 326 #endif /* GAUCHE_SYSTEM_H */ 327 328