(scm_i_dowinds): Removed unused code that would call the unexisting
[bpt/guile.git] / libguile / posix.c
CommitLineData
d675a50f 1/* Copyright (C) 1995,1996,1997,1998,1999,2000,2001, 2002, 2003, 2004 Free Software Foundation, Inc.
0f2d19dd 2 *
73be1d9e
MV
3 * This library is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU Lesser General Public
5 * License as published by the Free Software Foundation; either
6 * version 2.1 of the License, or (at your option) any later version.
0f2d19dd 7 *
73be1d9e
MV
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
0f2d19dd 12 *
73be1d9e
MV
13 * You should have received a copy of the GNU Lesser General Public
14 * License along with this library; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 */
1bbd0b84 17
1bbd0b84 18
0f2d19dd 19\f
2546b5c3
RB
20#if HAVE_CONFIG_H
21# include <config.h>
22#endif
0f2d19dd 23
8b50fe8e
MV
24/* Make GNU/Linux libc declare everything it has. */
25#define _GNU_SOURCE
26
0f2d19dd 27#include <stdio.h>
e6e2e95a
MD
28#include <errno.h>
29
a0599745 30#include "libguile/_scm.h"
b28f5b3c 31#include "libguile/dynwind.h"
a0599745
MD
32#include "libguile/fports.h"
33#include "libguile/scmsigs.h"
34#include "libguile/feature.h"
35#include "libguile/strings.h"
36#include "libguile/vectors.h"
c96d76b8 37#include "libguile/lang.h"
a0599745
MD
38
39#include "libguile/validate.h"
40#include "libguile/posix.h"
0f2d19dd
JB
41\f
42
02b754d3
GH
43#ifdef HAVE_STRING_H
44#include <string.h>
45#endif
0f2d19dd
JB
46#ifdef TIME_WITH_SYS_TIME
47# include <sys/time.h>
48# include <time.h>
49#else
50# if HAVE_SYS_TIME_H
51# include <sys/time.h>
52# else
53# include <time.h>
54# endif
55#endif
56
57#ifdef HAVE_UNISTD_H
58#include <unistd.h>
95b88819
GH
59#else
60#ifndef ttyname
61extern char *ttyname();
62#endif
0f2d19dd
JB
63#endif
64
3594582b 65#ifdef LIBC_H_WITH_UNISTD_H
bab0f4e5
JB
66#include <libc.h>
67#endif
68
8cc71382 69#include <sys/types.h>
0f2d19dd
JB
70#include <sys/stat.h>
71#include <fcntl.h>
72
82893676 73#ifdef HAVE_PWD_H
0f2d19dd 74#include <pwd.h>
82893676
MG
75#endif
76#ifdef HAVE_IO_H
77#include <io.h>
78#endif
f87c105a 79#ifdef HAVE_WINSOCK2_H
82893676
MG
80#include <winsock2.h>
81#endif
82
83#ifdef __MINGW32__
84/* Some defines for Windows here. */
7beabedb 85# include <process.h>
82893676
MG
86# define pipe(fd) _pipe (fd, 256, O_BINARY)
87#endif /* __MINGW32__ */
0f2d19dd
JB
88
89#if HAVE_SYS_WAIT_H
90# include <sys/wait.h>
91#endif
92#ifndef WEXITSTATUS
93# define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
94#endif
95#ifndef WIFEXITED
96# define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
97#endif
98
99#include <signal.h>
100
0f2d19dd
JB
101extern char ** environ;
102
82893676 103#ifdef HAVE_GRP_H
0f2d19dd 104#include <grp.h>
82893676
MG
105#endif
106#ifdef HAVE_SYS_UTSNAME_H
0f2d19dd 107#include <sys/utsname.h>
82893676 108#endif
0f2d19dd 109
0f2d19dd
JB
110#ifdef HAVE_SETLOCALE
111#include <locale.h>
112#endif
113
b9a7b725 114#if HAVE_CRYPT_H
94e6d793
MG
115# include <crypt.h>
116#endif
117
0eaf1055
KR
118#ifdef HAVE_NETDB_H
119#include <netdb.h> /* for MAXHOSTNAMELEN on Solaris */
120#endif
121
122#ifdef HAVE_SYS_PARAM_H
123#include <sys/param.h> /* for MAXHOSTNAMELEN */
124#endif
125
94e6d793
MG
126#if HAVE_SYS_RESOURCE_H
127# include <sys/resource.h>
128#endif
129
130#if HAVE_SYS_FILE_H
131# include <sys/file.h>
132#endif
133
eb7e1603
KR
134#if HAVE_CRT_EXTERNS_H
135#include <crt_externs.h> /* for Darwin _NSGetEnviron */
136#endif
137
bab0f4e5
JB
138/* Some Unix systems don't define these. CPP hair is dangerous, but
139 this seems safe enough... */
140#ifndef R_OK
141#define R_OK 4
142#endif
143
144#ifndef W_OK
145#define W_OK 2
146#endif
147
148#ifndef X_OK
149#define X_OK 1
150#endif
151
152#ifndef F_OK
153#define F_OK 0
154#endif
398609a5
JB
155
156/* On NextStep, <utime.h> doesn't define struct utime, unless we
157 #define _POSIX_SOURCE before #including it. I think this is less
158 of a kludge than defining struct utimbuf ourselves. */
159#ifdef UTIMBUF_NEEDS_POSIX
160#define _POSIX_SOURCE
161#endif
162
163#ifdef HAVE_SYS_UTIME_H
164#include <sys/utime.h>
165#endif
166
167#ifdef HAVE_UTIME_H
168#include <utime.h>
169#endif
170
171/* Please don't add any more #includes or #defines here. The hack
172 above means that _POSIX_SOURCE may be #defined, which will
eb7e1603
KR
173 encourage header files to do strange things.
174
175 FIXME: Maybe should undef _POSIX_SOURCE after it's done its job.
176
177 FIXME: Probably should do all the includes first, then all the fallback
178 declarations and defines, in case things are not in the header we
179 imagine. */
180
181
182
183
184/* On Apple Darwin in a shared library there's no "environ" to access
185 directly, instead the address of that variable must be obtained with
186 _NSGetEnviron(). */
187#if HAVE__NSGETENVIRON && defined (PIC)
188#define environ (*_NSGetEnviron())
189#endif
398609a5 190
0f2d19dd 191\f
bc45012d
JB
192SCM_SYMBOL (sym_read_pipe, "read pipe");
193SCM_SYMBOL (sym_write_pipe, "write pipe");
0f2d19dd 194
a1ec6916 195SCM_DEFINE (scm_pipe, "pipe", 0, 0, 0,
1bbd0b84 196 (),
1e6808ea
MG
197 "Return a newly created pipe: a pair of ports which are linked\n"
198 "together on the local machine. The @emph{car} is the input\n"
199 "port and the @emph{cdr} is the output port. Data written (and\n"
200 "flushed) to the output port can be read from the input port.\n"
201 "Pipes are commonly used for communication with a newly forked\n"
202 "child process. The need to flush the output port can be\n"
203 "avoided by making it unbuffered using @code{setvbuf}.\n"
204 "\n"
205 "Writes occur atomically provided the size of the data in bytes\n"
206 "is not greater than the value of @code{PIPE_BUF}. Note that\n"
207 "the output port is likely to block if too much data (typically\n"
208 "equal to @code{PIPE_BUF}) has been written but not yet read\n"
209 "from the input port.")
1bbd0b84 210#define FUNC_NAME s_scm_pipe
0f2d19dd
JB
211{
212 int fd[2], rv;
0f2d19dd 213 SCM p_rd, p_wt;
02b754d3 214
0f2d19dd
JB
215 rv = pipe (fd);
216 if (rv)
1bbd0b84 217 SCM_SYSERROR;
ee149d03
JB
218
219 p_rd = scm_fdes_to_port (fd[0], "r", sym_read_pipe);
220 p_wt = scm_fdes_to_port (fd[1], "w", sym_write_pipe);
0f2d19dd
JB
221 return scm_cons (p_rd, p_wt);
222}
1bbd0b84 223#undef FUNC_NAME
0f2d19dd
JB
224
225
0e958795 226#ifdef HAVE_GETGROUPS
a1ec6916 227SCM_DEFINE (scm_getgroups, "getgroups", 0, 0, 0,
1bbd0b84 228 (),
1e6808ea 229 "Return a vector of integers representing the current\n"
bb2c02f2 230 "supplementary group IDs.")
1bbd0b84 231#define FUNC_NAME s_scm_getgroups
0f2d19dd 232{
1d1559ce 233 SCM result;
66460dfb 234 int ngroups;
1be6b49c 235 size_t size;
66460dfb
DH
236 GETGROUPS_T *groups;
237
238 ngroups = getgroups (0, NULL);
239 if (ngroups <= 0)
1bbd0b84 240 SCM_SYSERROR;
66460dfb
DH
241
242 size = ngroups * sizeof (GETGROUPS_T);
4c9419ac 243 groups = scm_malloc (size);
66460dfb
DH
244 getgroups (ngroups, groups);
245
f360a962
MV
246 result = scm_c_make_vector (ngroups, SCM_BOOL_F);
247 while (--ngroups >= 0)
248 SCM_VECTOR_SET (result, ngroups, scm_ulong2num (groups[ngroups]));
66460dfb 249
4c9419ac 250 free (groups);
1d1559ce 251 return result;
1bbd0b84
GB
252}
253#undef FUNC_NAME
0e958795 254#endif
0f2d19dd 255
f360a962
MV
256#ifdef HAVE_SETGROUPS
257SCM_DEFINE (scm_setgroups, "setgroups", 1, 0, 0,
258 (SCM group_vec),
259 "Set the supplementary group IDs to those found in the vector argument.")
260#define FUNC_NAME s_scm_setgroups
261{
262 size_t ngroups;
263 size_t size;
264 size_t i;
265 int result;
266 int save_errno;
267 GETGROUPS_T *groups;
268
269 SCM_VALIDATE_VECTOR (SCM_ARG1, group_vec);
270
271 ngroups = SCM_VECTOR_LENGTH (group_vec);
272
273 /* validate before allocating, so we don't have to worry about leaks */
274 for (i = 0; i < ngroups; i++)
275 {
276 unsigned long ulong_gid;
277 GETGROUPS_T gid;
278 SCM_VALIDATE_ULONG_COPY (1, SCM_VECTOR_REF (group_vec, i), ulong_gid);
279 gid = ulong_gid;
280 if (gid != ulong_gid)
281 SCM_OUT_OF_RANGE (1, SCM_VECTOR_REF (group_vec, i));
282 }
283
284 size = ngroups * sizeof (GETGROUPS_T);
2eb78d06 285 if (size / sizeof (GETGROUPS_T) != ngroups)
93ccaef0 286 SCM_OUT_OF_RANGE (SCM_ARG1, SCM_I_MAKINUM (ngroups));
f360a962
MV
287 groups = scm_malloc (size);
288 for(i = 0; i < ngroups; i++)
289 groups [i] = SCM_NUM2ULONG (1, SCM_VECTOR_REF (group_vec, i));
290
291 result = setgroups (ngroups, groups);
292 save_errno = errno; /* don't let free() touch errno */
293 free (groups);
294 errno = save_errno;
295 if (result < 0)
296 SCM_SYSERROR;
297 return SCM_UNSPECIFIED;
298}
299#undef FUNC_NAME
300#endif
301
82893676 302#ifdef HAVE_GETPWENT
a1ec6916 303SCM_DEFINE (scm_getpwuid, "getpw", 0, 1, 0,
1bbd0b84 304 (SCM user),
b380b885
MD
305 "Look up an entry in the user database. @var{obj} can be an integer,\n"
306 "a string, or omitted, giving the behaviour of getpwuid, getpwnam\n"
307 "or getpwent respectively.")
1bbd0b84 308#define FUNC_NAME s_scm_getpwuid
0f2d19dd 309{
0f2d19dd 310 struct passwd *entry;
0f2d19dd 311
1d1559ce 312 SCM result = scm_c_make_vector (7, SCM_UNSPECIFIED);
7888309b 313 if (SCM_UNBNDP (user) || scm_is_false (user))
0f2d19dd 314 {
0f2d19dd 315 SCM_SYSCALL (entry = getpwent ());
3d781d49
JB
316 if (! entry)
317 {
3d781d49
JB
318 return SCM_BOOL_F;
319 }
0f2d19dd
JB
320 }
321 else if (SCM_INUMP (user))
322 {
0f2d19dd
JB
323 entry = getpwuid (SCM_INUM (user));
324 }
325 else
326 {
a6d9e5ab 327 SCM_VALIDATE_STRING (1, user);
a6d9e5ab 328 entry = getpwnam (SCM_STRING_CHARS (user));
0f2d19dd
JB
329 }
330 if (!entry)
1bbd0b84 331 SCM_MISC_ERROR ("entry not found", SCM_EOL);
02b754d3 332
1d1559ce
HWN
333 SCM_VECTOR_SET(result, 0, scm_makfrom0str (entry->pw_name));
334 SCM_VECTOR_SET(result, 1, scm_makfrom0str (entry->pw_passwd));
335 SCM_VECTOR_SET(result, 2, scm_ulong2num ((unsigned long) entry->pw_uid));
336 SCM_VECTOR_SET(result, 3, scm_ulong2num ((unsigned long) entry->pw_gid));
337 SCM_VECTOR_SET(result, 4, scm_makfrom0str (entry->pw_gecos));
0f2d19dd 338 if (!entry->pw_dir)
1d1559ce 339 SCM_VECTOR_SET(result, 5, scm_makfrom0str (""));
0f2d19dd 340 else
1d1559ce 341 SCM_VECTOR_SET(result, 5, scm_makfrom0str (entry->pw_dir));
0f2d19dd 342 if (!entry->pw_shell)
1d1559ce 343 SCM_VECTOR_SET(result, 6, scm_makfrom0str (""));
0f2d19dd 344 else
1d1559ce
HWN
345 SCM_VECTOR_SET(result, 6, scm_makfrom0str (entry->pw_shell));
346 return result;
0f2d19dd 347}
1bbd0b84 348#undef FUNC_NAME
82893676 349#endif /* HAVE_GETPWENT */
0f2d19dd
JB
350
351
0e958795 352#ifdef HAVE_SETPWENT
a1ec6916 353SCM_DEFINE (scm_setpwent, "setpw", 0, 1, 0,
1bbd0b84 354 (SCM arg),
b380b885
MD
355 "If called with a true argument, initialize or reset the password data\n"
356 "stream. Otherwise, close the stream. The @code{setpwent} and\n"
357 "@code{endpwent} procedures are implemented on top of this.")
1bbd0b84 358#define FUNC_NAME s_scm_setpwent
0f2d19dd 359{
7888309b 360 if (SCM_UNBNDP (arg) || scm_is_false (arg))
0f2d19dd
JB
361 endpwent ();
362 else
363 setpwent ();
364 return SCM_UNSPECIFIED;
365}
1bbd0b84 366#undef FUNC_NAME
0e958795 367#endif
0f2d19dd
JB
368
369
82893676 370#ifdef HAVE_GETGRENT
0f2d19dd 371/* Combines getgrgid and getgrnam. */
a1ec6916 372SCM_DEFINE (scm_getgrgid, "getgr", 0, 1, 0,
1bbd0b84 373 (SCM name),
b380b885
MD
374 "Look up an entry in the group database. @var{obj} can be an integer,\n"
375 "a string, or omitted, giving the behaviour of getgrgid, getgrnam\n"
376 "or getgrent respectively.")
1bbd0b84 377#define FUNC_NAME s_scm_getgrgid
0f2d19dd 378{
0f2d19dd 379 struct group *entry;
1d1559ce 380 SCM result = scm_c_make_vector (4, SCM_UNSPECIFIED);
34d19ef6 381
7888309b 382 if (SCM_UNBNDP (name) || scm_is_false (name))
3d781d49
JB
383 {
384 SCM_SYSCALL (entry = getgrent ());
385 if (! entry)
386 {
3d781d49
JB
387 return SCM_BOOL_F;
388 }
389 }
0f2d19dd
JB
390 else if (SCM_INUMP (name))
391 SCM_SYSCALL (entry = getgrgid (SCM_INUM (name)));
392 else
393 {
a6d9e5ab 394 SCM_VALIDATE_STRING (1, name);
a6d9e5ab 395 SCM_SYSCALL (entry = getgrnam (SCM_STRING_CHARS (name)));
0f2d19dd
JB
396 }
397 if (!entry)
1bbd0b84 398 SCM_SYSERROR;
02b754d3 399
1d1559ce
HWN
400 SCM_VECTOR_SET(result, 0, scm_makfrom0str (entry->gr_name));
401 SCM_VECTOR_SET(result, 1, scm_makfrom0str (entry->gr_passwd));
402 SCM_VECTOR_SET(result, 2, scm_ulong2num ((unsigned long) entry->gr_gid));
403 SCM_VECTOR_SET(result, 3, scm_makfromstrs (-1, entry->gr_mem));
404 return result;
0f2d19dd 405}
1bbd0b84 406#undef FUNC_NAME
0f2d19dd
JB
407
408
409
a1ec6916 410SCM_DEFINE (scm_setgrent, "setgr", 0, 1, 0,
1bbd0b84 411 (SCM arg),
b380b885
MD
412 "If called with a true argument, initialize or reset the group data\n"
413 "stream. Otherwise, close the stream. The @code{setgrent} and\n"
414 "@code{endgrent} procedures are implemented on top of this.")
1bbd0b84 415#define FUNC_NAME s_scm_setgrent
0f2d19dd 416{
7888309b 417 if (SCM_UNBNDP (arg) || scm_is_false (arg))
0f2d19dd
JB
418 endgrent ();
419 else
420 setgrent ();
421 return SCM_UNSPECIFIED;
422}
1bbd0b84 423#undef FUNC_NAME
82893676 424#endif /* HAVE_GETGRENT */
0f2d19dd
JB
425
426
a1ec6916 427SCM_DEFINE (scm_kill, "kill", 2, 0, 0,
1bbd0b84 428 (SCM pid, SCM sig),
b380b885
MD
429 "Sends a signal to the specified process or group of processes.\n\n"
430 "@var{pid} specifies the processes to which the signal is sent:\n\n"
431 "@table @r\n"
432 "@item @var{pid} greater than 0\n"
433 "The process whose identifier is @var{pid}.\n"
434 "@item @var{pid} equal to 0\n"
435 "All processes in the current process group.\n"
436 "@item @var{pid} less than -1\n"
437 "The process group whose identifier is -@var{pid}\n"
438 "@item @var{pid} equal to -1\n"
439 "If the process is privileged, all processes except for some special\n"
440 "system processes. Otherwise, all processes with the current effective\n"
441 "user ID.\n"
442 "@end table\n\n"
443 "@var{sig} should be specified using a variable corresponding to\n"
444 "the Unix symbolic name, e.g.,\n\n"
445 "@defvar SIGHUP\n"
446 "Hang-up signal.\n"
447 "@end defvar\n\n"
448 "@defvar SIGINT\n"
449 "Interrupt signal.\n"
450 "@end defvar")
1bbd0b84 451#define FUNC_NAME s_scm_kill
0f2d19dd 452{
0f2d19dd 453 /* Signal values are interned in scm_init_posix(). */
82893676 454#ifdef HAVE_KILL
a55c2b68 455 if (kill (scm_to_int (pid), scm_to_int (sig)) != 0)
82893676 456#else
a55c2b68
MV
457 if (scm_to_int (pid) == getpid ())
458 if (raise (scm_to_int (sig)) != 0)
82893676
MG
459#endif
460 SCM_SYSERROR;
02b754d3 461 return SCM_UNSPECIFIED;
0f2d19dd 462}
1bbd0b84 463#undef FUNC_NAME
0f2d19dd 464
d00ae47e 465#ifdef HAVE_WAITPID
a1ec6916 466SCM_DEFINE (scm_waitpid, "waitpid", 1, 1, 0,
1bbd0b84 467 (SCM pid, SCM options),
b380b885
MD
468 "This procedure collects status information from a child process which\n"
469 "has terminated or (optionally) stopped. Normally it will\n"
470 "suspend the calling process until this can be done. If more than one\n"
471 "child process is eligible then one will be chosen by the operating system.\n\n"
472 "The value of @var{pid} determines the behaviour:\n\n"
473 "@table @r\n"
474 "@item @var{pid} greater than 0\n"
475 "Request status information from the specified child process.\n"
476 "@item @var{pid} equal to -1 or WAIT_ANY\n"
477 "Request status information for any child process.\n"
478 "@item @var{pid} equal to 0 or WAIT_MYPGRP\n"
479 "Request status information for any child process in the current process\n"
480 "group.\n"
481 "@item @var{pid} less than -1\n"
482 "Request status information for any child process whose process group ID\n"
483 "is -@var{PID}.\n"
484 "@end table\n\n"
485 "The @var{options} argument, if supplied, should be the bitwise OR of the\n"
486 "values of zero or more of the following variables:\n\n"
487 "@defvar WNOHANG\n"
488 "Return immediately even if there are no child processes to be collected.\n"
489 "@end defvar\n\n"
490 "@defvar WUNTRACED\n"
491 "Report status information for stopped processes as well as terminated\n"
492 "processes.\n"
493 "@end defvar\n\n"
494 "The return value is a pair containing:\n\n"
495 "@enumerate\n"
496 "@item\n"
497 "The process ID of the child process, or 0 if @code{WNOHANG} was\n"
498 "specified and no process was collected.\n"
499 "@item\n"
500 "The integer status value.\n"
501 "@end enumerate")
1bbd0b84 502#define FUNC_NAME s_scm_waitpid
0f2d19dd
JB
503{
504 int i;
505 int status;
506 int ioptions;
0f2d19dd
JB
507 if (SCM_UNBNDP (options))
508 ioptions = 0;
509 else
510 {
0f2d19dd 511 /* Flags are interned in scm_init_posix. */
a55c2b68 512 ioptions = scm_to_int (options);
0f2d19dd 513 }
a55c2b68 514 SCM_SYSCALL (i = waitpid (scm_to_int (pid), &status, ioptions));
02b754d3 515 if (i == -1)
1bbd0b84 516 SCM_SYSERROR;
a55c2b68 517 return scm_cons (scm_from_int (i), scm_from_int (status));
0f2d19dd 518}
1bbd0b84 519#undef FUNC_NAME
d00ae47e 520#endif /* HAVE_WAITPID */
0f2d19dd 521
82893676 522#ifndef __MINGW32__
a1ec6916 523SCM_DEFINE (scm_status_exit_val, "status:exit-val", 1, 0, 0,
1bbd0b84 524 (SCM status),
1e6808ea
MG
525 "Return the exit status value, as would be set if a process\n"
526 "ended normally through a call to @code{exit} or @code{_exit},\n"
527 "if any, otherwise @code{#f}.")
1bbd0b84 528#define FUNC_NAME s_scm_status_exit_val
67ec3667 529{
e67dc2be
JB
530 int lstatus;
531
e67dc2be
JB
532 /* On Ultrix, the WIF... macros assume their argument is an lvalue;
533 go figure. SCM_INUM does not yield an lvalue. */
a55c2b68 534 lstatus = scm_to_int (status);
e67dc2be 535 if (WIFEXITED (lstatus))
a55c2b68 536 return (scm_from_int (WEXITSTATUS (lstatus)));
67ec3667
GH
537 else
538 return SCM_BOOL_F;
539}
1bbd0b84 540#undef FUNC_NAME
e67dc2be 541
a1ec6916 542SCM_DEFINE (scm_status_term_sig, "status:term-sig", 1, 0, 0,
1bbd0b84 543 (SCM status),
1e6808ea
MG
544 "Return the signal number which terminated the process, if any,\n"
545 "otherwise @code{#f}.")
1bbd0b84 546#define FUNC_NAME s_scm_status_term_sig
67ec3667 547{
e67dc2be
JB
548 int lstatus;
549
a55c2b68 550 lstatus = scm_to_int (status);
e67dc2be 551 if (WIFSIGNALED (lstatus))
a55c2b68 552 return scm_from_int (WTERMSIG (lstatus));
67ec3667
GH
553 else
554 return SCM_BOOL_F;
555}
1bbd0b84 556#undef FUNC_NAME
0f2d19dd 557
a1ec6916 558SCM_DEFINE (scm_status_stop_sig, "status:stop-sig", 1, 0, 0,
1bbd0b84 559 (SCM status),
1e6808ea
MG
560 "Return the signal number which stopped the process, if any,\n"
561 "otherwise @code{#f}.")
1bbd0b84 562#define FUNC_NAME s_scm_status_stop_sig
67ec3667 563{
e67dc2be
JB
564 int lstatus;
565
a55c2b68 566 lstatus = scm_to_int (status);
e67dc2be 567 if (WIFSTOPPED (lstatus))
a55c2b68 568 return scm_from_int (WSTOPSIG (lstatus));
67ec3667
GH
569 else
570 return SCM_BOOL_F;
571}
1bbd0b84 572#undef FUNC_NAME
82893676 573#endif /* __MINGW32__ */
0f2d19dd 574
82893676 575#ifdef HAVE_GETPPID
a1ec6916 576SCM_DEFINE (scm_getppid, "getppid", 0, 0, 0,
1bbd0b84 577 (),
1e6808ea
MG
578 "Return an integer representing the process ID of the parent\n"
579 "process.")
1bbd0b84 580#define FUNC_NAME s_scm_getppid
0f2d19dd 581{
93ccaef0 582 return SCM_I_MAKINUM (0L + getppid ());
0f2d19dd 583}
1bbd0b84 584#undef FUNC_NAME
82893676 585#endif /* HAVE_GETPPID */
0f2d19dd
JB
586
587
82893676 588#ifndef __MINGW32__
a1ec6916 589SCM_DEFINE (scm_getuid, "getuid", 0, 0, 0,
1bbd0b84 590 (),
1e6808ea 591 "Return an integer representing the current real user ID.")
1bbd0b84 592#define FUNC_NAME s_scm_getuid
0f2d19dd 593{
93ccaef0 594 return SCM_I_MAKINUM (0L + getuid ());
0f2d19dd 595}
1bbd0b84 596#undef FUNC_NAME
0f2d19dd
JB
597
598
599
a1ec6916 600SCM_DEFINE (scm_getgid, "getgid", 0, 0, 0,
1bbd0b84 601 (),
1e6808ea 602 "Return an integer representing the current real group ID.")
1bbd0b84 603#define FUNC_NAME s_scm_getgid
0f2d19dd 604{
93ccaef0 605 return SCM_I_MAKINUM (0L + getgid ());
0f2d19dd 606}
1bbd0b84 607#undef FUNC_NAME
0f2d19dd
JB
608
609
610
a1ec6916 611SCM_DEFINE (scm_geteuid, "geteuid", 0, 0, 0,
1bbd0b84 612 (),
1e6808ea 613 "Return an integer representing the current effective user ID.\n"
b380b885 614 "If the system does not support effective IDs, then the real ID\n"
480fa28d 615 "is returned. @code{(provided? 'EIDs)} reports whether the\n"
1e6808ea 616 "system supports effective IDs.")
1bbd0b84 617#define FUNC_NAME s_scm_geteuid
0f2d19dd
JB
618{
619#ifdef HAVE_GETEUID
93ccaef0 620 return SCM_I_MAKINUM (0L + geteuid ());
0f2d19dd 621#else
93ccaef0 622 return SCM_I_MAKINUM (0L + getuid ());
0f2d19dd
JB
623#endif
624}
1bbd0b84 625#undef FUNC_NAME
0f2d19dd
JB
626
627
a1ec6916 628SCM_DEFINE (scm_getegid, "getegid", 0, 0, 0,
1bbd0b84 629 (),
1e6808ea 630 "Return an integer representing the current effective group ID.\n"
b380b885 631 "If the system does not support effective IDs, then the real ID\n"
480fa28d 632 "is returned. @code{(provided? 'EIDs)} reports whether the\n"
1e6808ea 633 "system supports effective IDs.")
1bbd0b84 634#define FUNC_NAME s_scm_getegid
0f2d19dd
JB
635{
636#ifdef HAVE_GETEUID
93ccaef0 637 return SCM_I_MAKINUM (0L + getegid ());
0f2d19dd 638#else
93ccaef0 639 return SCM_I_MAKINUM (0L + getgid ());
0f2d19dd
JB
640#endif
641}
1bbd0b84 642#undef FUNC_NAME
0f2d19dd
JB
643
644
a1ec6916 645SCM_DEFINE (scm_setuid, "setuid", 1, 0, 0,
1bbd0b84 646 (SCM id),
b380b885
MD
647 "Sets both the real and effective user IDs to the integer @var{id}, provided\n"
648 "the process has appropriate privileges.\n"
649 "The return value is unspecified.")
1bbd0b84 650#define FUNC_NAME s_scm_setuid
0f2d19dd 651{
a55c2b68 652 if (setuid (scm_to_int (id)) != 0)
1bbd0b84 653 SCM_SYSERROR;
02b754d3 654 return SCM_UNSPECIFIED;
0f2d19dd 655}
1bbd0b84 656#undef FUNC_NAME
0f2d19dd 657
a1ec6916 658SCM_DEFINE (scm_setgid, "setgid", 1, 0, 0,
1bbd0b84 659 (SCM id),
b380b885
MD
660 "Sets both the real and effective group IDs to the integer @var{id}, provided\n"
661 "the process has appropriate privileges.\n"
662 "The return value is unspecified.")
1bbd0b84 663#define FUNC_NAME s_scm_setgid
0f2d19dd 664{
a55c2b68 665 if (setgid (scm_to_int (id)) != 0)
1bbd0b84 666 SCM_SYSERROR;
02b754d3 667 return SCM_UNSPECIFIED;
0f2d19dd 668}
1bbd0b84 669#undef FUNC_NAME
0f2d19dd 670
a1ec6916 671SCM_DEFINE (scm_seteuid, "seteuid", 1, 0, 0,
1bbd0b84 672 (SCM id),
b380b885
MD
673 "Sets the effective user ID to the integer @var{id}, provided the process\n"
674 "has appropriate privileges. If effective IDs are not supported, the\n"
480fa28d 675 "real ID is set instead -- @code{(provided? 'EIDs)} reports whether the\n"
b380b885
MD
676 "system supports effective IDs.\n"
677 "The return value is unspecified.")
1bbd0b84 678#define FUNC_NAME s_scm_seteuid
0f2d19dd 679{
02b754d3
GH
680 int rv;
681
0f2d19dd 682#ifdef HAVE_SETEUID
a55c2b68 683 rv = seteuid (scm_to_int (id));
0f2d19dd 684#else
a55c2b68 685 rv = setuid (scm_to_int (id));
0f2d19dd 686#endif
02b754d3 687 if (rv != 0)
1bbd0b84 688 SCM_SYSERROR;
02b754d3 689 return SCM_UNSPECIFIED;
0f2d19dd 690}
1bbd0b84 691#undef FUNC_NAME
7beabedb
MG
692#endif /* __MINGW32__ */
693
0f2d19dd 694
0e958795 695#ifdef HAVE_SETEGID
a1ec6916 696SCM_DEFINE (scm_setegid, "setegid", 1, 0, 0,
1bbd0b84 697 (SCM id),
b380b885
MD
698 "Sets the effective group ID to the integer @var{id}, provided the process\n"
699 "has appropriate privileges. If effective IDs are not supported, the\n"
480fa28d 700 "real ID is set instead -- @code{(provided? 'EIDs)} reports whether the\n"
b380b885
MD
701 "system supports effective IDs.\n"
702 "The return value is unspecified.")
1bbd0b84 703#define FUNC_NAME s_scm_setegid
0f2d19dd 704{
02b754d3
GH
705 int rv;
706
0f2d19dd 707#ifdef HAVE_SETEUID
a55c2b68 708 rv = setegid (scm_to_int (id));
0f2d19dd 709#else
a55c2b68 710 rv = setgid (scm_to_int (id));
0f2d19dd 711#endif
02b754d3 712 if (rv != 0)
1bbd0b84 713 SCM_SYSERROR;
02b754d3
GH
714 return SCM_UNSPECIFIED;
715
0f2d19dd 716}
1bbd0b84 717#undef FUNC_NAME
0e958795 718#endif
0f2d19dd 719
82893676
MG
720
721#ifdef HAVE_GETPGRP
a1ec6916 722SCM_DEFINE (scm_getpgrp, "getpgrp", 0, 0, 0,
1bbd0b84 723 (),
1e6808ea 724 "Return an integer representing the current process group ID.\n"
b380b885 725 "This is the POSIX definition, not BSD.")
1bbd0b84 726#define FUNC_NAME s_scm_getpgrp
0f2d19dd
JB
727{
728 int (*fn)();
4625e44f 729 fn = (int (*) ()) getpgrp;
93ccaef0 730 return SCM_I_MAKINUM (fn (0));
0f2d19dd 731}
1bbd0b84 732#undef FUNC_NAME
82893676
MG
733#endif /* HAVE_GETPGRP */
734
0f2d19dd 735
f25f761d 736#ifdef HAVE_SETPGID
a1ec6916 737SCM_DEFINE (scm_setpgid, "setpgid", 2, 0, 0,
1bbd0b84 738 (SCM pid, SCM pgid),
b380b885
MD
739 "Move the process @var{pid} into the process group @var{pgid}. @var{pid} or\n"
740 "@var{pgid} must be integers: they can be zero to indicate the ID of the\n"
741 "current process.\n"
742 "Fails on systems that do not support job control.\n"
743 "The return value is unspecified.")
1bbd0b84 744#define FUNC_NAME s_scm_setpgid
0f2d19dd 745{
02b754d3 746 /* FIXME(?): may be known as setpgrp. */
a55c2b68 747 if (setpgid (scm_to_int (pid), scm_to_int (pgid)) != 0)
1bbd0b84 748 SCM_SYSERROR;
02b754d3 749 return SCM_UNSPECIFIED;
0f2d19dd 750}
1bbd0b84 751#undef FUNC_NAME
f25f761d 752#endif /* HAVE_SETPGID */
0f2d19dd 753
f25f761d 754#ifdef HAVE_SETSID
a1ec6916 755SCM_DEFINE (scm_setsid, "setsid", 0, 0, 0,
1bbd0b84 756 (),
b380b885
MD
757 "Creates a new session. The current process becomes the session leader\n"
758 "and is put in a new process group. The process will be detached\n"
759 "from its controlling terminal if it has one.\n"
760 "The return value is an integer representing the new process group ID.")
1bbd0b84 761#define FUNC_NAME s_scm_setsid
0f2d19dd
JB
762{
763 pid_t sid = setsid ();
02b754d3 764 if (sid == -1)
1bbd0b84 765 SCM_SYSERROR;
02b754d3 766 return SCM_UNSPECIFIED;
0f2d19dd 767}
1bbd0b84 768#undef FUNC_NAME
f25f761d 769#endif /* HAVE_SETSID */
0f2d19dd 770
82893676 771#ifdef HAVE_TTYNAME
a1ec6916 772SCM_DEFINE (scm_ttyname, "ttyname", 1, 0, 0,
1bbd0b84 773 (SCM port),
1e6808ea
MG
774 "Return a string with the name of the serial terminal device\n"
775 "underlying @var{port}.")
1bbd0b84 776#define FUNC_NAME s_scm_ttyname
0f2d19dd 777{
1d1559ce 778 char *result;
0f2d19dd 779 int fd;
78446828
MV
780
781 port = SCM_COERCE_OUTPORT (port);
34d19ef6 782 SCM_VALIDATE_OPPORT (1, port);
a98bddfd 783 if (!SCM_FPORTP (port))
0f2d19dd 784 return SCM_BOOL_F;
ee149d03 785 fd = SCM_FPORT_FDES (port);
1d1559ce
HWN
786 SCM_SYSCALL (result = ttyname (fd));
787 if (!result)
1bbd0b84 788 SCM_SYSERROR;
1d1559ce
HWN
789 /* result could be overwritten by another call to ttyname */
790 return (scm_makfrom0str (result));
0f2d19dd 791}
1bbd0b84 792#undef FUNC_NAME
82893676 793#endif /* HAVE_TTYNAME */
0f2d19dd 794
f25f761d 795#ifdef HAVE_CTERMID
a1ec6916 796SCM_DEFINE (scm_ctermid, "ctermid", 0, 0, 0,
1bbd0b84 797 (),
1e6808ea
MG
798 "Return a string containing the file name of the controlling\n"
799 "terminal for the current process.")
1bbd0b84 800#define FUNC_NAME s_scm_ctermid
0f2d19dd
JB
801{
802 char *result = ctermid (NULL);
02b754d3 803 if (*result == '\0')
1bbd0b84 804 SCM_SYSERROR;
02b754d3 805 return scm_makfrom0str (result);
0f2d19dd 806}
1bbd0b84 807#undef FUNC_NAME
f25f761d 808#endif /* HAVE_CTERMID */
0f2d19dd 809
f25f761d 810#ifdef HAVE_TCGETPGRP
a1ec6916 811SCM_DEFINE (scm_tcgetpgrp, "tcgetpgrp", 1, 0, 0,
1bbd0b84 812 (SCM port),
1e6808ea
MG
813 "Return the process group ID of the foreground process group\n"
814 "associated with the terminal open on the file descriptor\n"
815 "underlying @var{port}.\n"
816 "\n"
b380b885
MD
817 "If there is no foreground process group, the return value is a\n"
818 "number greater than 1 that does not match the process group ID\n"
819 "of any existing process group. This can happen if all of the\n"
820 "processes in the job that was formerly the foreground job have\n"
821 "terminated, and no other job has yet been moved into the\n"
822 "foreground.")
1bbd0b84 823#define FUNC_NAME s_scm_tcgetpgrp
0f2d19dd
JB
824{
825 int fd;
826 pid_t pgid;
78446828
MV
827
828 port = SCM_COERCE_OUTPORT (port);
829
34d19ef6 830 SCM_VALIDATE_OPFPORT (1, port);
ee149d03
JB
831 fd = SCM_FPORT_FDES (port);
832 if ((pgid = tcgetpgrp (fd)) == -1)
1bbd0b84 833 SCM_SYSERROR;
93ccaef0 834 return SCM_I_MAKINUM (pgid);
1bbd0b84
GB
835}
836#undef FUNC_NAME
f25f761d 837#endif /* HAVE_TCGETPGRP */
0f2d19dd 838
f25f761d 839#ifdef HAVE_TCSETPGRP
a1ec6916 840SCM_DEFINE (scm_tcsetpgrp, "tcsetpgrp", 2, 0, 0,
1bbd0b84 841 (SCM port, SCM pgid),
b380b885
MD
842 "Set the foreground process group ID for the terminal used by the file\n"
843 "descriptor underlying @var{port} to the integer @var{pgid}.\n"
844 "The calling process\n"
845 "must be a member of the same session as @var{pgid} and must have the same\n"
846 "controlling terminal. The return value is unspecified.")
1bbd0b84 847#define FUNC_NAME s_scm_tcsetpgrp
0f2d19dd
JB
848{
849 int fd;
78446828
MV
850
851 port = SCM_COERCE_OUTPORT (port);
852
34d19ef6 853 SCM_VALIDATE_OPFPORT (1, port);
ee149d03 854 fd = SCM_FPORT_FDES (port);
a55c2b68 855 if (tcsetpgrp (fd, scm_to_int (pgid)) == -1)
1bbd0b84 856 SCM_SYSERROR;
02b754d3 857 return SCM_UNSPECIFIED;
1bbd0b84
GB
858}
859#undef FUNC_NAME
f25f761d 860#endif /* HAVE_TCSETPGRP */
0f2d19dd 861
2ee08a28
GH
862/* return a newly allocated array of char pointers to each of the strings
863 in args, with a terminating NULL pointer. */
864/* Note: a similar function is defined in dynl.c, but we don't necessarily
865 want to export it. */
866static char **allocate_string_pointers (SCM args)
0f2d19dd 867{
2ee08a28
GH
868 char **result;
869 int n_args = scm_ilength (args);
0f2d19dd 870 int i;
6afcd3b2 871
2ee08a28
GH
872 SCM_ASSERT (n_args >= 0, args, SCM_ARGn, "allocate_string_pointers");
873 result = (char **) scm_malloc ((n_args + 1) * sizeof (char *));
874 result[n_args] = NULL;
875 for (i = 0; i < n_args; i++)
0f2d19dd 876 {
2ee08a28 877 SCM car = SCM_CAR (args);
a6d9e5ab 878
2ee08a28
GH
879 if (!SCM_STRINGP (car))
880 {
881 free (result);
882 scm_wrong_type_arg ("allocate_string_pointers", SCM_ARGn, car);
883 }
884 result[i] = SCM_STRING_CHARS (SCM_CAR (args));
885 args = SCM_CDR (args);
0f2d19dd 886 }
2ee08a28 887 return result;
0f2d19dd
JB
888}
889
a1ec6916 890SCM_DEFINE (scm_execl, "execl", 1, 0, 1,
1bbd0b84 891 (SCM filename, SCM args),
b380b885
MD
892 "Executes the file named by @var{path} as a new process image.\n"
893 "The remaining arguments are supplied to the process; from a C program\n"
bb2c02f2 894 "they are accessible as the @code{argv} argument to @code{main}.\n"
b380b885 895 "Conventionally the first @var{arg} is the same as @var{path}.\n"
8f85c0c6 896 "All arguments must be strings.\n\n"
b380b885
MD
897 "If @var{arg} is missing, @var{path} is executed with a null\n"
898 "argument list, which may have system-dependent side-effects.\n\n"
899 "This procedure is currently implemented using the @code{execv} system\n"
900 "call, but we call it @code{execl} because of its Scheme calling interface.")
1bbd0b84 901#define FUNC_NAME s_scm_execl
0f2d19dd
JB
902{
903 char **execargv;
807f353f 904 int save_errno;
a6d9e5ab 905 SCM_VALIDATE_STRING (1, filename);
2ee08a28 906 execargv = allocate_string_pointers (args);
a6d9e5ab 907 execv (SCM_STRING_CHARS (filename), execargv);
807f353f
KR
908 save_errno = errno;
909 free (execargv);
910 errno = save_errno;
1bbd0b84 911 SCM_SYSERROR;
02b754d3
GH
912 /* not reached. */
913 return SCM_BOOL_F;
0f2d19dd 914}
1bbd0b84 915#undef FUNC_NAME
0f2d19dd 916
a1ec6916 917SCM_DEFINE (scm_execlp, "execlp", 1, 0, 1,
1bbd0b84 918 (SCM filename, SCM args),
b380b885
MD
919 "Similar to @code{execl}, however if\n"
920 "@var{filename} does not contain a slash\n"
921 "then the file to execute will be located by searching the\n"
922 "directories listed in the @code{PATH} environment variable.\n\n"
6bcd01fc 923 "This procedure is currently implemented using the @code{execvp} system\n"
b380b885 924 "call, but we call it @code{execlp} because of its Scheme calling interface.")
1bbd0b84 925#define FUNC_NAME s_scm_execlp
0f2d19dd
JB
926{
927 char **execargv;
807f353f 928 int save_errno;
a6d9e5ab 929 SCM_VALIDATE_STRING (1, filename);
2ee08a28 930 execargv = allocate_string_pointers (args);
a6d9e5ab 931 execvp (SCM_STRING_CHARS (filename), execargv);
807f353f
KR
932 save_errno = errno;
933 free (execargv);
934 errno = save_errno;
1bbd0b84 935 SCM_SYSERROR;
02b754d3
GH
936 /* not reached. */
937 return SCM_BOOL_F;
0f2d19dd 938}
1bbd0b84 939#undef FUNC_NAME
0f2d19dd 940
6afcd3b2 941static char **
3eeba8d4 942environ_list_to_c (SCM envlist, int arg, const char *proc)
6afcd3b2
GH
943{
944 int num_strings;
945 char **result;
a6d9e5ab 946 int i;
6afcd3b2 947
6afcd3b2 948 num_strings = scm_ilength (envlist);
a6d9e5ab 949 SCM_ASSERT (num_strings >= 0, envlist, arg, proc);
67329a9e 950 result = (char **) scm_malloc ((num_strings + 1) * sizeof (char *));
6afcd3b2
GH
951 if (result == NULL)
952 scm_memory_error (proc);
c96d76b8 953 for (i = 0; !SCM_NULL_OR_NIL_P (envlist); ++i, envlist = SCM_CDR (envlist))
6afcd3b2 954 {
a6d9e5ab 955 SCM str = SCM_CAR (envlist);
6afcd3b2
GH
956 int len;
957 char *src;
958
a6d9e5ab
DH
959 SCM_ASSERT (SCM_STRINGP (str), envlist, arg, proc);
960 len = SCM_STRING_LENGTH (str);
34f0f2b8 961 src = SCM_STRING_CHARS (str);
67329a9e 962 result[i] = scm_malloc (len + 1);
6afcd3b2
GH
963 if (result[i] == NULL)
964 scm_memory_error (proc);
a6d9e5ab
DH
965 memcpy (result[i], src, len);
966 result[i][len] = 0;
6afcd3b2
GH
967 }
968 result[i] = 0;
6afcd3b2
GH
969 return result;
970}
971
807f353f
KR
972/* OPTIMIZE-ME: scm_execle doesn't need malloced copies of the environment
973 list strings the way environ_list_to_c gives. */
974
a1ec6916 975SCM_DEFINE (scm_execle, "execle", 2, 0, 1,
1bbd0b84 976 (SCM filename, SCM env, SCM args),
b380b885
MD
977 "Similar to @code{execl}, but the environment of the new process is\n"
978 "specified by @var{env}, which must be a list of strings as returned by the\n"
979 "@code{environ} procedure.\n\n"
980 "This procedure is currently implemented using the @code{execve} system\n"
981 "call, but we call it @code{execle} because of its Scheme calling interface.")
1bbd0b84 982#define FUNC_NAME s_scm_execle
6afcd3b2
GH
983{
984 char **execargv;
985 char **exec_env;
807f353f 986 int save_errno, i;
6afcd3b2 987
a6d9e5ab 988 SCM_VALIDATE_STRING (1, filename);
6afcd3b2 989
2ee08a28 990 execargv = allocate_string_pointers (args);
1bbd0b84 991 exec_env = environ_list_to_c (env, SCM_ARG2, FUNC_NAME);
a6d9e5ab 992 execve (SCM_STRING_CHARS (filename), execargv, exec_env);
807f353f
KR
993 save_errno = errno;
994 free (execargv);
995 for (i = 0; exec_env[i] != NULL; i++)
996 free (exec_env[i]);
997 free (exec_env);
998 errno = save_errno;
1bbd0b84 999 SCM_SYSERROR;
6afcd3b2
GH
1000 /* not reached. */
1001 return SCM_BOOL_F;
1002}
1bbd0b84 1003#undef FUNC_NAME
6afcd3b2 1004
82893676 1005#ifdef HAVE_FORK
a1ec6916 1006SCM_DEFINE (scm_fork, "primitive-fork", 0, 0, 0,
1bbd0b84 1007 (),
b380b885
MD
1008 "Creates a new \"child\" process by duplicating the current \"parent\" process.\n"
1009 "In the child the return value is 0. In the parent the return value is\n"
1010 "the integer process ID of the child.\n\n"
1011 "This procedure has been renamed from @code{fork} to avoid a naming conflict\n"
1012 "with the scsh fork.")
1bbd0b84 1013#define FUNC_NAME s_scm_fork
0f2d19dd 1014{
bab0f4e5 1015 int pid;
0f2d19dd
JB
1016 pid = fork ();
1017 if (pid == -1)
1bbd0b84 1018 SCM_SYSERROR;
93ccaef0 1019 return SCM_I_MAKINUM (0L+pid);
0f2d19dd 1020}
1bbd0b84 1021#undef FUNC_NAME
82893676 1022#endif /* HAVE_FORK */
0f2d19dd 1023
4f68365d
MV
1024#ifdef __MINGW32__
1025# include "win32-uname.h"
1026#endif
1027
1028#if defined (HAVE_UNAME) || defined (__MINGW32__)
a1ec6916 1029SCM_DEFINE (scm_uname, "uname", 0, 0, 0,
1bbd0b84 1030 (),
1e6808ea
MG
1031 "Return an object with some information about the computer\n"
1032 "system the program is running on.")
1bbd0b84 1033#define FUNC_NAME s_scm_uname
0f2d19dd 1034{
0f2d19dd 1035 struct utsname buf;
1d1559ce 1036 SCM result = scm_c_make_vector (5, SCM_UNSPECIFIED);
e1a191a8 1037 if (uname (&buf) < 0)
1bbd0b84 1038 SCM_SYSERROR;
1d1559ce
HWN
1039 SCM_VECTOR_SET(result, 0, scm_makfrom0str (buf.sysname));
1040 SCM_VECTOR_SET(result, 1, scm_makfrom0str (buf.nodename));
1041 SCM_VECTOR_SET(result, 2, scm_makfrom0str (buf.release));
1042 SCM_VECTOR_SET(result, 3, scm_makfrom0str (buf.version));
1043 SCM_VECTOR_SET(result, 4, scm_makfrom0str (buf.machine));
0f2d19dd 1044/*
02b754d3 1045 a linux special?
1d1559ce 1046 SCM_VECTOR_SET(result, 5, scm_makfrom0str (buf.domainname));
0f2d19dd 1047*/
1d1559ce 1048 return result;
0f2d19dd 1049}
1bbd0b84 1050#undef FUNC_NAME
f25f761d 1051#endif /* HAVE_UNAME */
0f2d19dd 1052
a1ec6916 1053SCM_DEFINE (scm_environ, "environ", 0, 1, 0,
1bbd0b84 1054 (SCM env),
1e6808ea
MG
1055 "If @var{env} is omitted, return the current environment (in the\n"
1056 "Unix sense) as a list of strings. Otherwise set the current\n"
1057 "environment, which is also the default environment for child\n"
1058 "processes, to the supplied list of strings. Each member of\n"
1059 "@var{env} should be of the form @code{NAME=VALUE} and values of\n"
1060 "@code{NAME} should not be duplicated. If @var{env} is supplied\n"
1061 "then the return value is unspecified.")
1bbd0b84 1062#define FUNC_NAME s_scm_environ
0f2d19dd
JB
1063{
1064 if (SCM_UNBNDP (env))
1065 return scm_makfromstrs (-1, environ);
1066 else
1067 {
0f2d19dd 1068 char **new_environ;
6afcd3b2 1069
1bbd0b84 1070 new_environ = environ_list_to_c (env, SCM_ARG1, FUNC_NAME);
0f2d19dd
JB
1071 /* Free the old environment, except when called for the first
1072 * time.
1073 */
1074 {
1075 char **ep;
1076 static int first = 1;
1077 if (!first)
1078 {
1079 for (ep = environ; *ep != NULL; ep++)
19468eff
GH
1080 free (*ep);
1081 free ((char *) environ);
0f2d19dd
JB
1082 }
1083 first = 0;
1084 }
1085 environ = new_environ;
1086 return SCM_UNSPECIFIED;
1087 }
1088}
1bbd0b84 1089#undef FUNC_NAME
0f2d19dd 1090
9ee5fce4
MD
1091#ifdef L_tmpnam
1092
a1ec6916 1093SCM_DEFINE (scm_tmpnam, "tmpnam", 0, 0, 0,
1bbd0b84 1094 (),
1e6808ea
MG
1095 "Return a name in the file system that does not match any\n"
1096 "existing file. However there is no guarantee that another\n"
1097 "process will not create the file after @code{tmpnam} is called.\n"
1098 "Care should be taken if opening the file, e.g., use the\n"
1099 "@code{O_EXCL} open flag or use @code{mkstemp!} instead.")
1bbd0b84 1100#define FUNC_NAME s_scm_tmpnam
9ee5fce4
MD
1101{
1102 char name[L_tmpnam];
6d163216
GH
1103 char *rv;
1104
1105 SCM_SYSCALL (rv = tmpnam (name));
1106 if (rv == NULL)
1107 /* not SCM_SYSERROR since errno probably not set. */
1108 SCM_MISC_ERROR ("tmpnam failed", SCM_EOL);
9ee5fce4
MD
1109 return scm_makfrom0str (name);
1110}
0f981281 1111#undef FUNC_NAME
0f2d19dd 1112
1bbd0b84 1113#endif
1cc91f1b 1114
4f68365d
MV
1115#ifndef HAVE_MKSTEMP
1116extern int mkstemp (char *);
1117#endif
1118
6d163216
GH
1119SCM_DEFINE (scm_mkstemp, "mkstemp!", 1, 0, 0,
1120 (SCM tmpl),
1e6808ea
MG
1121 "Create a new unique file in the file system and returns a new\n"
1122 "buffered port open for reading and writing to the file.\n"
1123 "@var{tmpl} is a string specifying where the file should be\n"
1124 "created: it must end with @code{XXXXXX} and will be changed in\n"
1125 "place to return the name of the temporary file.")
6d163216
GH
1126#define FUNC_NAME s_scm_mkstemp
1127{
1128 char *c_tmpl;
1129 int rv;
1130
6d163216
GH
1131 SCM_VALIDATE_STRING_COPY (1, tmpl, c_tmpl);
1132 SCM_SYSCALL (rv = mkstemp (c_tmpl));
1133 if (rv == -1)
1134 SCM_SYSERROR;
1135 return scm_fdes_to_port (rv, "w+", tmpl);
1136}
1137#undef FUNC_NAME
1138
a1ec6916 1139SCM_DEFINE (scm_utime, "utime", 1, 2, 0,
1bbd0b84 1140 (SCM pathname, SCM actime, SCM modtime),
1e6808ea
MG
1141 "@code{utime} sets the access and modification times for the\n"
1142 "file named by @var{path}. If @var{actime} or @var{modtime} is\n"
1143 "not supplied, then the current time is used. @var{actime} and\n"
1144 "@var{modtime} must be integer time values as returned by the\n"
1145 "@code{current-time} procedure.\n"
1146 "@lisp\n"
b380b885 1147 "(utime \"foo\" (- (current-time) 3600))\n"
1e6808ea
MG
1148 "@end lisp\n"
1149 "will set the access time to one hour in the past and the\n"
1150 "modification time to the current time.")
1bbd0b84 1151#define FUNC_NAME s_scm_utime
0f2d19dd
JB
1152{
1153 int rv;
1154 struct utimbuf utm_tmp;
1155
a6d9e5ab 1156 SCM_VALIDATE_STRING (1, pathname);
0f2d19dd
JB
1157 if (SCM_UNBNDP (actime))
1158 SCM_SYSCALL (time (&utm_tmp.actime));
1159 else
e4b265d8 1160 utm_tmp.actime = SCM_NUM2ULONG (2, actime);
0f2d19dd
JB
1161
1162 if (SCM_UNBNDP (modtime))
1163 SCM_SYSCALL (time (&utm_tmp.modtime));
1164 else
e4b265d8 1165 utm_tmp.modtime = SCM_NUM2ULONG (3, modtime);
0f2d19dd 1166
a6d9e5ab 1167 SCM_SYSCALL (rv = utime (SCM_STRING_CHARS (pathname), &utm_tmp));
02b754d3 1168 if (rv != 0)
1bbd0b84 1169 SCM_SYSERROR;
02b754d3 1170 return SCM_UNSPECIFIED;
0f2d19dd 1171}
1bbd0b84 1172#undef FUNC_NAME
0f2d19dd 1173
a1ec6916 1174SCM_DEFINE (scm_access, "access?", 2, 0, 0,
1bbd0b84 1175 (SCM path, SCM how),
1e6808ea
MG
1176 "Return @code{#t} if @var{path} corresponds to an existing file\n"
1177 "and the current process has the type of access specified by\n"
1178 "@var{how}, otherwise @code{#f}. @var{how} should be specified\n"
1179 "using the values of the variables listed below. Multiple\n"
1180 "values can be combined using a bitwise or, in which case\n"
1181 "@code{#t} will only be returned if all accesses are granted.\n"
1182 "\n"
1183 "Permissions are checked using the real id of the current\n"
1184 "process, not the effective id, although it's the effective id\n"
1185 "which determines whether the access would actually be granted.\n"
1186 "\n"
b380b885
MD
1187 "@defvar R_OK\n"
1188 "test for read permission.\n"
1189 "@end defvar\n"
1190 "@defvar W_OK\n"
1191 "test for write permission.\n"
1192 "@end defvar\n"
1193 "@defvar X_OK\n"
1194 "test for execute permission.\n"
1195 "@end defvar\n"
1196 "@defvar F_OK\n"
1197 "test for existence of the file.\n"
1198 "@end defvar")
1bbd0b84 1199#define FUNC_NAME s_scm_access
0f2d19dd
JB
1200{
1201 int rv;
1202
a6d9e5ab 1203 SCM_VALIDATE_STRING (1, path);
a55c2b68 1204 rv = access (SCM_STRING_CHARS (path), scm_to_int (how));
7888309b 1205 return scm_from_bool (!rv);
0f2d19dd 1206}
1bbd0b84 1207#undef FUNC_NAME
0f2d19dd 1208
a1ec6916 1209SCM_DEFINE (scm_getpid, "getpid", 0, 0, 0,
1bbd0b84 1210 (),
1e6808ea 1211 "Return an integer representing the current process ID.")
1bbd0b84 1212#define FUNC_NAME s_scm_getpid
0f2d19dd 1213{
93ccaef0 1214 return SCM_I_MAKINUM ((unsigned long) getpid ());
0f2d19dd 1215}
1bbd0b84 1216#undef FUNC_NAME
0f2d19dd 1217
a1ec6916 1218SCM_DEFINE (scm_putenv, "putenv", 1, 0, 0,
1bbd0b84 1219 (SCM str),
b380b885
MD
1220 "Modifies the environment of the current process, which is\n"
1221 "also the default environment inherited by child processes.\n\n"
1222 "If @var{string} is of the form @code{NAME=VALUE} then it will be written\n"
1223 "directly into the environment, replacing any existing environment string\n"
1224 "with\n"
1225 "name matching @code{NAME}. If @var{string} does not contain an equal\n"
1226 "sign, then any existing string with name matching @var{string} will\n"
1227 "be removed.\n\n"
1228 "The return value is unspecified.")
1bbd0b84 1229#define FUNC_NAME s_scm_putenv
0f2d19dd 1230{
f158788f 1231 int rv;
19468eff 1232 char *ptr;
f93ddd39 1233
9fd38a3d 1234 SCM_VALIDATE_STRING (1, str);
002409fe
MV
1235
1236 if (strchr (SCM_STRING_CHARS (str), '=') == NULL)
1237 {
1e498fbd 1238#ifdef HAVE_UNSETENV
002409fe 1239 /* No '=' in argument means we should remove the variable from
ff4b8391
KR
1240 the environment. Not all putenvs understand this (for instance
1241 FreeBSD 4.8 doesn't). To be safe, we do it explicitely using
1242 unsetenv. */
002409fe 1243 unsetenv (SCM_STRING_CHARS (str));
1e498fbd
SJ
1244#else
1245 /* On e.g. Win32 hosts putenv() called with 'name=' removes the
1246 environment variable 'name'. */
f158788f 1247 int e;
1e498fbd 1248 ptr = scm_malloc (SCM_STRING_LENGTH (str) + 2);
fcc5d734
SJ
1249 if (ptr == NULL)
1250 SCM_MEMORY_ERROR;
1e498fbd
SJ
1251 strncpy (ptr, SCM_STRING_CHARS (str), SCM_STRING_LENGTH (str));
1252 ptr[SCM_STRING_LENGTH (str)] = '=';
1253 ptr[SCM_STRING_LENGTH (str) + 1] = 0;
1254 rv = putenv (ptr);
dd65e90f 1255 e = errno; free (ptr); errno = e;
1e498fbd
SJ
1256 if (rv < 0)
1257 SCM_SYSERROR;
fcc5d734 1258#endif /* !HAVE_UNSETENV */
002409fe
MV
1259 }
1260 else
1261 {
1262 /* must make a new copy to be left in the environment, safe from gc. */
67329a9e 1263 ptr = scm_malloc (SCM_STRING_LENGTH (str) + 1);
002409fe
MV
1264 if (ptr == NULL)
1265 SCM_MEMORY_ERROR;
1266 strncpy (ptr, SCM_STRING_CHARS (str), SCM_STRING_LENGTH (str));
fcc5d734
SJ
1267
1268#ifdef __MINGW32__
1269 /* If str is "FOO=", ie. attempting to set an empty string, then
1270 we need to see if it's been successful. On MINGW, "FOO="
1271 means remove FOO from the environment. As a workaround, we
1272 set "FOO= ", ie. a space, and then modify the string returned
1273 by getenv. It's not enough just to modify the string we set,
1274 because MINGW putenv copies it. */
1275 if (ptr[SCM_STRING_LENGTH (str) - 1] == '=')
1276 {
1277 char *alt;
93ccaef0
MV
1278 SCM name = scm_substring (str, SCM_I_MAKINUM (0),
1279 SCM_I_MAKINUM (SCM_STRING_LENGTH (str) - 1));
fcc5d734
SJ
1280 if (getenv (SCM_STRING_CHARS (name)) == NULL)
1281 {
1282 alt = scm_malloc (SCM_STRING_LENGTH (str) + 2);
1283 if (alt == NULL)
1284 {
1285 free (ptr);
1286 SCM_MEMORY_ERROR;
1287 }
1288 memcpy (alt, SCM_STRING_CHARS (str), SCM_STRING_LENGTH (str));
1289 alt[SCM_STRING_LENGTH (str)] = ' ';
1290 alt[SCM_STRING_LENGTH (str) + 1] = '\0';
1291 rv = putenv (alt);
1292 if (rv < 0)
1293 SCM_SYSERROR;
1294 free (ptr); /* don't need the old string we gave to putenv */
1295 }
1296 alt = getenv (SCM_STRING_CHARS (name));
1297 alt[0] = '\0';
1298 return SCM_UNSPECIFIED;
1299 }
1300#endif /* __MINGW32__ */
1301
002409fe
MV
1302 ptr[SCM_STRING_LENGTH (str)] = 0;
1303 rv = putenv (ptr);
1304 if (rv < 0)
1305 SCM_SYSERROR;
1306 }
f93ddd39 1307 return SCM_UNSPECIFIED;
0f2d19dd 1308}
1bbd0b84 1309#undef FUNC_NAME
0f2d19dd 1310
f25f761d 1311#ifdef HAVE_SETLOCALE
a1ec6916 1312SCM_DEFINE (scm_setlocale, "setlocale", 1, 1, 0,
1bbd0b84 1313 (SCM category, SCM locale),
1e6808ea
MG
1314 "If @var{locale} is omitted, return the current value of the\n"
1315 "specified locale category as a system-dependent string.\n"
1316 "@var{category} should be specified using the values\n"
1317 "@code{LC_COLLATE}, @code{LC_ALL} etc.\n"
1318 "\n"
1319 "Otherwise the specified locale category is set to the string\n"
1320 "@var{locale} and the new value is returned as a\n"
1321 "system-dependent string. If @var{locale} is an empty string,\n"
bb2c02f2 1322 "the locale will be set using environment variables.")
1bbd0b84 1323#define FUNC_NAME s_scm_setlocale
0f2d19dd 1324{
0f2d19dd
JB
1325 char *clocale;
1326 char *rv;
1327
0f2d19dd
JB
1328 if (SCM_UNBNDP (locale))
1329 {
1330 clocale = NULL;
1331 }
1332 else
1333 {
a6d9e5ab 1334 SCM_VALIDATE_STRING (2, locale);
a6d9e5ab 1335 clocale = SCM_STRING_CHARS (locale);
0f2d19dd
JB
1336 }
1337
a55c2b68 1338 rv = setlocale (scm_to_int (category), clocale);
02b754d3 1339 if (rv == NULL)
1bbd0b84 1340 SCM_SYSERROR;
02b754d3 1341 return scm_makfrom0str (rv);
0f2d19dd 1342}
1bbd0b84 1343#undef FUNC_NAME
f25f761d 1344#endif /* HAVE_SETLOCALE */
0f2d19dd 1345
f25f761d 1346#ifdef HAVE_MKNOD
a1ec6916 1347SCM_DEFINE (scm_mknod, "mknod", 4, 0, 0,
1bbd0b84 1348 (SCM path, SCM type, SCM perms, SCM dev),
b380b885
MD
1349 "Creates a new special file, such as a file corresponding to a device.\n"
1350 "@var{path} specifies the name of the file. @var{type} should\n"
1351 "be one of the following symbols:\n"
1352 "regular, directory, symlink, block-special, char-special,\n"
1353 "fifo, or socket. @var{perms} (an integer) specifies the file permissions.\n"
1354 "@var{dev} (an integer) specifies which device the special file refers\n"
1355 "to. Its exact interpretation depends on the kind of special file\n"
1356 "being created.\n\n"
1357 "E.g.,\n"
1e6808ea 1358 "@lisp\n"
09831f94 1359 "(mknod \"/dev/fd0\" 'block-special #o660 (+ (* 2 256) 2))\n"
1e6808ea 1360 "@end lisp\n\n"
a3c8b9fc 1361 "The return value is unspecified.")
1bbd0b84 1362#define FUNC_NAME s_scm_mknod
0f2d19dd 1363{
0f2d19dd 1364 int val;
19468eff 1365 char *p;
82a76bdf 1366 int ctype = 0;
19468eff 1367
a6d9e5ab 1368 SCM_VALIDATE_STRING (1, path);
34d19ef6 1369 SCM_VALIDATE_SYMBOL (2, type);
19468eff 1370
86c991c2 1371 p = SCM_SYMBOL_CHARS (type);
19468eff
GH
1372 if (strcmp (p, "regular") == 0)
1373 ctype = S_IFREG;
1374 else if (strcmp (p, "directory") == 0)
1375 ctype = S_IFDIR;
1376 else if (strcmp (p, "symlink") == 0)
1377 ctype = S_IFLNK;
1378 else if (strcmp (p, "block-special") == 0)
1379 ctype = S_IFBLK;
1380 else if (strcmp (p, "char-special") == 0)
1381 ctype = S_IFCHR;
1382 else if (strcmp (p, "fifo") == 0)
1383 ctype = S_IFIFO;
e655d034 1384#ifdef S_IFSOCK
19468eff
GH
1385 else if (strcmp (p, "socket") == 0)
1386 ctype = S_IFSOCK;
e655d034 1387#endif
19468eff 1388 else
34d19ef6 1389 SCM_OUT_OF_RANGE (2, type);
19468eff 1390
a55c2b68
MV
1391 SCM_SYSCALL (val = mknod (SCM_STRING_CHARS (path),
1392 ctype | scm_to_int (perms),
1393 scm_to_int (dev)));
02b754d3 1394 if (val != 0)
1bbd0b84 1395 SCM_SYSERROR;
02b754d3 1396 return SCM_UNSPECIFIED;
0f2d19dd 1397}
1bbd0b84 1398#undef FUNC_NAME
f25f761d 1399#endif /* HAVE_MKNOD */
0f2d19dd 1400
f25f761d 1401#ifdef HAVE_NICE
a1ec6916 1402SCM_DEFINE (scm_nice, "nice", 1, 0, 0,
1bbd0b84 1403 (SCM incr),
b380b885
MD
1404 "Increment the priority of the current process by @var{incr}. A higher\n"
1405 "priority value means that the process runs less often.\n"
1406 "The return value is unspecified.")
1bbd0b84 1407#define FUNC_NAME s_scm_nice
0f2d19dd 1408{
a55c2b68 1409 if (nice (scm_to_int (incr)) != 0)
1bbd0b84 1410 SCM_SYSERROR;
02b754d3 1411 return SCM_UNSPECIFIED;
0f2d19dd 1412}
1bbd0b84 1413#undef FUNC_NAME
f25f761d 1414#endif /* HAVE_NICE */
0f2d19dd 1415
f25f761d 1416#ifdef HAVE_SYNC
a1ec6916 1417SCM_DEFINE (scm_sync, "sync", 0, 0, 0,
1bbd0b84 1418 (),
b380b885
MD
1419 "Flush the operating system disk buffers.\n"
1420 "The return value is unspecified.")
1bbd0b84 1421#define FUNC_NAME s_scm_sync
0f2d19dd 1422{
0f2d19dd 1423 sync();
127ec750 1424 return SCM_UNSPECIFIED;
0f2d19dd 1425}
1bbd0b84 1426#undef FUNC_NAME
f25f761d 1427#endif /* HAVE_SYNC */
0f2d19dd 1428
b9a7b725 1429#if HAVE_CRYPT
94e6d793
MG
1430SCM_DEFINE (scm_crypt, "crypt", 2, 0, 0,
1431 (SCM key, SCM salt),
1432 "Encrypt @var{key} using @var{salt} as the salt value to the\n"
9401323e 1433 "crypt(3) library call.")
94e6d793
MG
1434#define FUNC_NAME s_scm_crypt
1435{
1436 char * p;
1437
1438 SCM_VALIDATE_STRING (1, key);
1439 SCM_VALIDATE_STRING (2, salt);
94e6d793
MG
1440
1441 p = crypt (SCM_STRING_CHARS (key), SCM_STRING_CHARS (salt));
1442 return scm_makfrom0str (p);
1443}
1444#undef FUNC_NAME
b9a7b725 1445#endif /* HAVE_CRYPT */
94e6d793
MG
1446
1447#if HAVE_CHROOT
1448SCM_DEFINE (scm_chroot, "chroot", 1, 0, 0,
1449 (SCM path),
1450 "Change the root directory to that specified in @var{path}.\n"
1451 "This directory will be used for path names beginning with\n"
1452 "@file{/}. The root directory is inherited by all children\n"
1453 "of the current process. Only the superuser may change the\n"
1454 "root directory.")
1455#define FUNC_NAME s_scm_chroot
1456{
1457 SCM_VALIDATE_STRING (1, path);
94e6d793
MG
1458
1459 if (chroot (SCM_STRING_CHARS (path)) == -1)
1460 SCM_SYSERROR;
1461 return SCM_UNSPECIFIED;
1462}
1463#undef FUNC_NAME
1464#endif /* HAVE_CHROOT */
1465
7beabedb
MG
1466
1467#ifdef __MINGW32__
1468/* Wrapper function to supplying `getlogin()' under Windows. */
1469static char * getlogin (void)
1470{
1471 static char user[256];
1472 static unsigned long len = 256;
1473
1474 if (!GetUserName (user, &len))
1475 return NULL;
1476 return user;
1477}
1478#endif /* __MINGW32__ */
1479
1480
4f68365d 1481#if defined (HAVE_GETLOGIN) || defined (__MINGW32__)
94e6d793
MG
1482SCM_DEFINE (scm_getlogin, "getlogin", 0, 0, 0,
1483 (void),
1484 "Return a string containing the name of the user logged in on\n"
1485 "the controlling terminal of the process, or @code{#f} if this\n"
1486 "information cannot be obtained.")
1487#define FUNC_NAME s_scm_getlogin
1488{
1489 char * p;
1490
1491 p = getlogin ();
1492 if (!p || !*p)
1493 return SCM_BOOL_F;
1494 return scm_makfrom0str (p);
1495}
1496#undef FUNC_NAME
1497#endif /* HAVE_GETLOGIN */
1498
1499#if HAVE_CUSERID
1500SCM_DEFINE (scm_cuserid, "cuserid", 0, 0, 0,
1501 (void),
1502 "Return a string containing a user name associated with the\n"
1503 "effective user id of the process. Return @code{#f} if this\n"
1504 "information cannot be obtained.")
1505#define FUNC_NAME s_scm_cuserid
1506{
1b317eb1 1507 char buf[L_cuserid];
94e6d793
MG
1508 char * p;
1509
1b317eb1 1510 p = cuserid (buf);
94e6d793
MG
1511 if (!p || !*p)
1512 return SCM_BOOL_F;
1513 return scm_makfrom0str (p);
1514}
1515#undef FUNC_NAME
1516#endif /* HAVE_CUSERID */
1517
1518#if HAVE_GETPRIORITY
1519SCM_DEFINE (scm_getpriority, "getpriority", 2, 0, 0,
1520 (SCM which, SCM who),
1521 "Return the scheduling priority of the process, process group\n"
1522 "or user, as indicated by @var{which} and @var{who}. @var{which}\n"
1523 "is one of the variables @code{PRIO_PROCESS}, @code{PRIO_PGRP}\n"
1524 "or @code{PRIO_USER}, and @var{who} is interpreted relative to\n"
1525 "@var{which} (a process identifier for @code{PRIO_PROCESS},\n"
1526 "process group identifier for @code{PRIO_PGRP}, and a user\n"
1527 "identifier for @code{PRIO_USER}. A zero value of @var{who}\n"
1528 "denotes the current process, process group, or user. Return\n"
1529 "the highest priority (lowest numerical value) of any of the\n"
1530 "specified processes.")
1531#define FUNC_NAME s_scm_getpriority
1532{
1533 int cwhich, cwho, ret;
1534
a55c2b68
MV
1535 cwhich = scm_to_int (which);
1536 cwho = scm_to_int (who);
94e6d793
MG
1537
1538 /* We have to clear errno and examine it later, because -1 is a
1539 legal return value for getpriority(). */
1540 errno = 0;
1541 ret = getpriority (cwhich, cwho);
1542 if (errno != 0)
1543 SCM_SYSERROR;
a55c2b68 1544 return scm_from_int (ret);
94e6d793
MG
1545}
1546#undef FUNC_NAME
1547#endif /* HAVE_GETPRIORITY */
1548
1549#if HAVE_SETPRIORITY
1550SCM_DEFINE (scm_setpriority, "setpriority", 3, 0, 0,
1551 (SCM which, SCM who, SCM prio),
1552 "Set the scheduling priority of the process, process group\n"
1553 "or user, as indicated by @var{which} and @var{who}. @var{which}\n"
1554 "is one of the variables @code{PRIO_PROCESS}, @code{PRIO_PGRP}\n"
1555 "or @code{PRIO_USER}, and @var{who} is interpreted relative to\n"
1556 "@var{which} (a process identifier for @code{PRIO_PROCESS},\n"
1557 "process group identifier for @code{PRIO_PGRP}, and a user\n"
1558 "identifier for @code{PRIO_USER}. A zero value of @var{who}\n"
1559 "denotes the current process, process group, or user.\n"
1560 "@var{prio} is a value in the range -20 and 20, the default\n"
1561 "priority is 0; lower priorities cause more favorable\n"
1562 "scheduling. Sets the priority of all of the specified\n"
1563 "processes. Only the super-user may lower priorities.\n"
1564 "The return value is not specified.")
1565#define FUNC_NAME s_scm_setpriority
1566{
1567 int cwhich, cwho, cprio;
1568
a55c2b68
MV
1569 cwhich = scm_to_int (which);
1570 cwho = scm_to_int (who);
1571 cprio = scm_to_int (prio);
94e6d793
MG
1572
1573 if (setpriority (cwhich, cwho, cprio) == -1)
1574 SCM_SYSERROR;
1575 return SCM_UNSPECIFIED;
1576}
1577#undef FUNC_NAME
1578#endif /* HAVE_SETPRIORITY */
1579
1580#if HAVE_GETPASS
1581SCM_DEFINE (scm_getpass, "getpass", 1, 0, 0,
1582 (SCM prompt),
1583 "Display @var{prompt} to the standard error output and read\n"
1584 "a password from @file{/dev/tty}. If this file is not\n"
1585 "accessible, it reads from standard input. The password may be\n"
1586 "up to 127 characters in length. Additional characters and the\n"
1587 "terminating newline character are discarded. While reading\n"
1588 "the password, echoing and the generation of signals by special\n"
1589 "characters is disabled.")
1590#define FUNC_NAME s_scm_getpass
1591{
1592 char * p;
1593 SCM passwd;
1594
1595 SCM_VALIDATE_STRING (1, prompt);
94e6d793
MG
1596
1597 p = getpass(SCM_STRING_CHARS (prompt));
1598 passwd = scm_makfrom0str (p);
1599
1600 /* Clear out the password in the static buffer. */
1601 memset (p, 0, strlen (p));
1602
1603 return passwd;
1604}
1605#undef FUNC_NAME
1606#endif /* HAVE_GETPASS */
1607
8f99e3f3
SJ
1608/* Wrapper function for flock() support under M$-Windows. */
1609#ifdef __MINGW32__
1610# include <io.h>
1611# include <sys/locking.h>
1612# include <errno.h>
1613# ifndef _LK_UNLCK
1614 /* Current MinGW package fails to define this. *sigh* */
1615# define _LK_UNLCK 0
1616# endif
1617# define LOCK_EX 1
1618# define LOCK_UN 2
1619# define LOCK_SH 4
1620# define LOCK_NB 8
1621
1622static int flock (int fd, int operation)
1623{
1624 long pos, len;
1625 int ret, err;
1626
1627 /* Disable invalid arguments. */
1628 if (((operation & (LOCK_EX | LOCK_SH)) == (LOCK_EX | LOCK_SH)) ||
1629 ((operation & (LOCK_EX | LOCK_UN)) == (LOCK_EX | LOCK_UN)) ||
1630 ((operation & (LOCK_SH | LOCK_UN)) == (LOCK_SH | LOCK_UN)))
1631 {
1632 errno = EINVAL;
1633 return -1;
1634 }
1635
1636 /* Determine mode of operation and discard unsupported ones. */
1637 if (operation == (LOCK_NB | LOCK_EX))
1638 operation = _LK_NBLCK;
1639 else if (operation & LOCK_UN)
1640 operation = _LK_UNLCK;
1641 else if (operation == LOCK_EX)
1642 operation = _LK_LOCK;
1643 else
1644 {
1645 errno = EINVAL;
1646 return -1;
1647 }
1648
1649 /* Save current file pointer and seek to beginning. */
1650 if ((pos = lseek (fd, 0, SEEK_CUR)) == -1 || (len = filelength (fd)) == -1)
1651 return -1;
1652 lseek (fd, 0L, SEEK_SET);
1653
1654 /* Deadlock if necessary. */
1655 do
1656 {
1657 ret = _locking (fd, operation, len);
1658 }
1659 while (ret == -1 && errno == EDEADLOCK);
1660
1661 /* Produce meaningful error message. */
1662 if (errno == EACCES && operation == _LK_NBLCK)
1663 err = EDEADLOCK;
1664 else
1665 err = errno;
1666
1667 /* Return to saved file position pointer. */
1668 lseek (fd, pos, SEEK_SET);
1669 errno = err;
1670 return ret;
1671}
1672#endif /* __MINGW32__ */
1673
1674#if HAVE_FLOCK || defined (__MINGW32__)
94e6d793
MG
1675SCM_DEFINE (scm_flock, "flock", 2, 0, 0,
1676 (SCM file, SCM operation),
1677 "Apply or remove an advisory lock on an open file.\n"
1678 "@var{operation} specifies the action to be done:\n"
1679 "@table @code\n"
1680 "@item LOCK_SH\n"
1681 "Shared lock. More than one process may hold a shared lock\n"
1682 "for a given file at a given time.\n"
1683 "@item LOCK_EX\n"
1684 "Exclusive lock. Only one process may hold an exclusive lock\n"
1685 "for a given file at a given time.\n"
1686 "@item LOCK_UN\n"
1687 "Unlock the file.\n"
1688 "@item LOCK_NB\n"
1689 "Don't block when locking. May be specified by bitwise OR'ing\n"
1690 "it to one of the other operations.\n"
1691 "@end table\n"
1692 "The return value is not specified. @var{file} may be an open\n"
bb2c02f2 1693 "file descriptor or an open file descriptor port.")
94e6d793
MG
1694#define FUNC_NAME s_scm_flock
1695{
a55c2b68 1696 int fdes;
94e6d793 1697
a55c2b68
MV
1698 if (scm_is_integer (file))
1699 fdes = scm_to_int (file);
94e6d793
MG
1700 else
1701 {
1702 SCM_VALIDATE_OPFPORT (2, file);
1703
1704 fdes = SCM_FPORT_FDES (file);
1705 }
a55c2b68 1706 if (flock (fdes, scm_to_int (operation)) == -1)
94e6d793
MG
1707 SCM_SYSERROR;
1708 return SCM_UNSPECIFIED;
1709}
1710#undef FUNC_NAME
1711#endif /* HAVE_FLOCK */
1712
1713#if HAVE_SETHOSTNAME
1714SCM_DEFINE (scm_sethostname, "sethostname", 1, 0, 0,
1715 (SCM name),
1716 "Set the host name of the current processor to @var{name}. May\n"
1717 "only be used by the superuser. The return value is not\n"
1718 "specified.")
1719#define FUNC_NAME s_scm_sethostname
1720{
1721 SCM_VALIDATE_STRING (1, name);
94e6d793
MG
1722
1723 if (sethostname (SCM_STRING_CHARS (name), SCM_STRING_LENGTH (name)) == -1)
1724 SCM_SYSERROR;
1725 return SCM_UNSPECIFIED;
1726}
1727#undef FUNC_NAME
1728#endif /* HAVE_SETHOSTNAME */
1729
b28f5b3c 1730
94e6d793
MG
1731#if HAVE_GETHOSTNAME
1732SCM_DEFINE (scm_gethostname, "gethostname", 0, 0, 0,
1733 (void),
1734 "Return the host name of the current processor.")
1735#define FUNC_NAME s_scm_gethostname
1736{
b28f5b3c
DH
1737#ifdef MAXHOSTNAMELEN
1738
1739 /* Various systems define MAXHOSTNAMELEN (including Solaris in fact).
1740 * On GNU/Linux this doesn't include the terminating '\0', hence "+ 1". */
1741 const int len = MAXHOSTNAMELEN + 1;
1742 char *const p = scm_malloc (len);
1743 const int res = gethostname (p, len);
1744
1745 scm_frame_begin (0);
1746 scm_frame_unwind_handler (free, p, 0);
1747
1748#else
94e6d793 1749
0eaf1055 1750 /* Default 256 is for Solaris, under Linux ENAMETOOLONG is returned if not
b28f5b3c
DH
1751 * large enough. SUSv2 specifies 255 maximum too, apparently. */
1752 int len = 256;
1753 int res;
1754 char *p;
0eaf1055 1755
b28f5b3c 1756# if HAVE_SYSCONF && defined (_SC_HOST_NAME_MAX)
0eaf1055
KR
1757
1758 /* POSIX specifies the HOST_NAME_MAX system parameter for the max size,
b28f5b3c
DH
1759 * which may reflect a particular kernel configuration.
1760 * Must watch out for this existing but giving -1, as happens for instance
1761 * in gnu/linux glibc 2.3.2. */
0eaf1055 1762 {
b28f5b3c 1763 const long int n = sysconf (_SC_HOST_NAME_MAX);
0eaf1055
KR
1764 if (n != -1L)
1765 len = n;
1766 }
b28f5b3c
DH
1767
1768# endif
1769
1770 p = scm_malloc (len);
1771
1772 scm_frame_begin (0);
1773 scm_frame_unwind_handler (free, p, 0);
0eaf1055 1774
94e6d793
MG
1775 res = gethostname (p, len);
1776 while (res == -1 && errno == ENAMETOOLONG)
1777 {
94e6d793 1778 len *= 2;
b28f5b3c
DH
1779
1780 /* scm_realloc may throw an exception. */
1781 p = scm_realloc (p, len);
94e6d793
MG
1782 res = gethostname (p, len);
1783 }
b28f5b3c
DH
1784
1785#endif
1786
94e6d793
MG
1787 if (res == -1)
1788 {
b28f5b3c
DH
1789 const int save_errno = errno;
1790
1791 // No guile exceptions can occur before we have freed p's memory.
1792 scm_frame_end ();
4c9419ac 1793 free (p);
b28f5b3c 1794
22865124 1795 errno = save_errno;
94e6d793
MG
1796 SCM_SYSERROR;
1797 }
b28f5b3c
DH
1798 else
1799 {
1800 /* scm_makfrom0str may throw an exception. */
1801 const SCM name = scm_makfrom0str (p);
1802
1803 // No guile exceptions can occur before we have freed p's memory.
1804 scm_frame_end ();
1805 free (p);
1806
1807 return name;
1808 }
94e6d793
MG
1809}
1810#undef FUNC_NAME
1811#endif /* HAVE_GETHOSTNAME */
1812
b28f5b3c 1813
0f2d19dd
JB
1814void
1815scm_init_posix ()
0f2d19dd
JB
1816{
1817 scm_add_feature ("posix");
1818#ifdef HAVE_GETEUID
1819 scm_add_feature ("EIDs");
1820#endif
1821#ifdef WAIT_ANY
93ccaef0 1822 scm_c_define ("WAIT_ANY", SCM_I_MAKINUM (WAIT_ANY));
0f2d19dd
JB
1823#endif
1824#ifdef WAIT_MYPGRP
93ccaef0 1825 scm_c_define ("WAIT_MYPGRP", SCM_I_MAKINUM (WAIT_MYPGRP));
0f2d19dd
JB
1826#endif
1827#ifdef WNOHANG
93ccaef0 1828 scm_c_define ("WNOHANG", SCM_I_MAKINUM (WNOHANG));
0f2d19dd
JB
1829#endif
1830#ifdef WUNTRACED
93ccaef0 1831 scm_c_define ("WUNTRACED", SCM_I_MAKINUM (WUNTRACED));
0f2d19dd
JB
1832#endif
1833
0f2d19dd 1834 /* access() symbols. */
93ccaef0
MV
1835 scm_c_define ("R_OK", SCM_I_MAKINUM (R_OK));
1836 scm_c_define ("W_OK", SCM_I_MAKINUM (W_OK));
1837 scm_c_define ("X_OK", SCM_I_MAKINUM (X_OK));
1838 scm_c_define ("F_OK", SCM_I_MAKINUM (F_OK));
0f2d19dd
JB
1839
1840#ifdef LC_COLLATE
93ccaef0 1841 scm_c_define ("LC_COLLATE", SCM_I_MAKINUM (LC_COLLATE));
0f2d19dd
JB
1842#endif
1843#ifdef LC_CTYPE
93ccaef0 1844 scm_c_define ("LC_CTYPE", SCM_I_MAKINUM (LC_CTYPE));
0f2d19dd
JB
1845#endif
1846#ifdef LC_MONETARY
93ccaef0 1847 scm_c_define ("LC_MONETARY", SCM_I_MAKINUM (LC_MONETARY));
0f2d19dd
JB
1848#endif
1849#ifdef LC_NUMERIC
93ccaef0 1850 scm_c_define ("LC_NUMERIC", SCM_I_MAKINUM (LC_NUMERIC));
0f2d19dd
JB
1851#endif
1852#ifdef LC_TIME
93ccaef0 1853 scm_c_define ("LC_TIME", SCM_I_MAKINUM (LC_TIME));
0f2d19dd
JB
1854#endif
1855#ifdef LC_MESSAGES
93ccaef0 1856 scm_c_define ("LC_MESSAGES", SCM_I_MAKINUM (LC_MESSAGES));
0f2d19dd
JB
1857#endif
1858#ifdef LC_ALL
93ccaef0 1859 scm_c_define ("LC_ALL", SCM_I_MAKINUM (LC_ALL));
0f2d19dd 1860#endif
bd9e24b3 1861#ifdef PIPE_BUF
86d31dfe 1862 scm_c_define ("PIPE_BUF", scm_long2num (PIPE_BUF));
bd9e24b3
GH
1863#endif
1864
94e6d793 1865#ifdef PRIO_PROCESS
93ccaef0 1866 scm_c_define ("PRIO_PROCESS", SCM_I_MAKINUM (PRIO_PROCESS));
94e6d793
MG
1867#endif
1868#ifdef PRIO_PGRP
93ccaef0 1869 scm_c_define ("PRIO_PGRP", SCM_I_MAKINUM (PRIO_PGRP));
94e6d793
MG
1870#endif
1871#ifdef PRIO_USER
93ccaef0 1872 scm_c_define ("PRIO_USER", SCM_I_MAKINUM (PRIO_USER));
94e6d793
MG
1873#endif
1874
1875#ifdef LOCK_SH
93ccaef0 1876 scm_c_define ("LOCK_SH", SCM_I_MAKINUM (LOCK_SH));
94e6d793
MG
1877#endif
1878#ifdef LOCK_EX
93ccaef0 1879 scm_c_define ("LOCK_EX", SCM_I_MAKINUM (LOCK_EX));
94e6d793
MG
1880#endif
1881#ifdef LOCK_UN
93ccaef0 1882 scm_c_define ("LOCK_UN", SCM_I_MAKINUM (LOCK_UN));
94e6d793
MG
1883#endif
1884#ifdef LOCK_NB
93ccaef0 1885 scm_c_define ("LOCK_NB", SCM_I_MAKINUM (LOCK_NB));
94e6d793
MG
1886#endif
1887
a0599745
MD
1888#include "libguile/cpp_sig_symbols.c"
1889#include "libguile/posix.x"
0f2d19dd 1890}
89e00824
ML
1891
1892/*
1893 Local Variables:
1894 c-file-style: "gnu"
1895 End:
1896*/