simplify posix.c
[bpt/guile.git] / libguile / posix.c
CommitLineData
712ca51f 1/* Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
03a2f598 2 * 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc.
712ca51f 3 *
73be1d9e 4 * This library is free software; you can redistribute it and/or
53befeb7
NJ
5 * modify it under the terms of the GNU Lesser General Public License
6 * as published by the Free Software Foundation; either version 3 of
7 * the License, or (at your option) any later version.
0f2d19dd 8 *
53befeb7
NJ
9 * This library is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
73be1d9e
MV
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
0f2d19dd 13 *
73be1d9e
MV
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
53befeb7
NJ
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 * 02110-1301 USA
73be1d9e 18 */
1bbd0b84 19
1bbd0b84 20
0f2d19dd 21\f
dbb605f5 22#ifdef HAVE_CONFIG_H
2546b5c3
RB
23# include <config.h>
24#endif
0f2d19dd 25
3731192f 26#include <stdlib.h>
0f2d19dd 27#include <stdio.h>
e6e2e95a 28#include <errno.h>
889975e5 29#include <uniconv.h>
e6e2e95a 30
22072f21
LC
31#ifdef HAVE_SCHED_H
32# include <sched.h>
33#endif
34
02b754d3
GH
35#ifdef HAVE_STRING_H
36#include <string.h>
37#endif
0f2d19dd
JB
38#ifdef TIME_WITH_SYS_TIME
39# include <sys/time.h>
40# include <time.h>
41#else
42# if HAVE_SYS_TIME_H
43# include <sys/time.h>
44# else
45# include <time.h>
46# endif
47#endif
48
49#ifdef HAVE_UNISTD_H
50#include <unistd.h>
51#endif
52
3594582b 53#ifdef LIBC_H_WITH_UNISTD_H
bab0f4e5
JB
54#include <libc.h>
55#endif
56
8cc71382 57#include <sys/types.h>
0f2d19dd
JB
58#include <sys/stat.h>
59#include <fcntl.h>
60
82893676 61#ifdef HAVE_PWD_H
0f2d19dd 62#include <pwd.h>
82893676
MG
63#endif
64#ifdef HAVE_IO_H
65#include <io.h>
66#endif
82893676 67
d3c88f18
AW
68#include "libguile/_scm.h"
69#include "libguile/dynwind.h"
70#include "libguile/fports.h"
71#include "libguile/scmsigs.h"
72#include "libguile/feature.h"
73#include "libguile/strings.h"
74#include "libguile/srfi-13.h"
75#include "libguile/srfi-14.h"
76#include "libguile/vectors.h"
77#include "libguile/values.h"
78
79#include "libguile/validate.h"
80#include "libguile/posix.h"
81#include "libguile/gettext.h"
82#include "libguile/threads.h"
83\f
0f2d19dd
JB
84
85#if HAVE_SYS_WAIT_H
86# include <sys/wait.h>
87#endif
88#ifndef WEXITSTATUS
89# define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
90#endif
91#ifndef WIFEXITED
92# define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
93#endif
94
95#include <signal.h>
96
82893676 97#ifdef HAVE_GRP_H
0f2d19dd 98#include <grp.h>
82893676
MG
99#endif
100#ifdef HAVE_SYS_UTSNAME_H
0f2d19dd 101#include <sys/utsname.h>
82893676 102#endif
0f2d19dd 103
0f2d19dd
JB
104#ifdef HAVE_SETLOCALE
105#include <locale.h>
106#endif
107
b89c4943
LC
108#if (defined HAVE_NEWLOCALE) && (defined HAVE_STRCOLL_L)
109# define USE_GNU_LOCALE_API
110#endif
111
a2f00b9b
LC
112#if (defined USE_GNU_LOCALE_API) && (defined HAVE_XLOCALE_H)
113# include <xlocale.h>
114#endif
115
534bbcc1 116#ifdef HAVE_CRYPT_H
94e6d793
MG
117# include <crypt.h>
118#endif
119
0eaf1055
KR
120#ifdef HAVE_NETDB_H
121#include <netdb.h> /* for MAXHOSTNAMELEN on Solaris */
122#endif
123
124#ifdef HAVE_SYS_PARAM_H
125#include <sys/param.h> /* for MAXHOSTNAMELEN */
126#endif
127
94e6d793
MG
128#if HAVE_SYS_RESOURCE_H
129# include <sys/resource.h>
130#endif
131
837b0ae0 132#include <sys/file.h> /* from Gnulib */
eb7e1603 133
bab0f4e5
JB
134/* Some Unix systems don't define these. CPP hair is dangerous, but
135 this seems safe enough... */
136#ifndef R_OK
137#define R_OK 4
138#endif
139
140#ifndef W_OK
141#define W_OK 2
142#endif
143
144#ifndef X_OK
145#define X_OK 1
146#endif
147
148#ifndef F_OK
149#define F_OK 0
150#endif
398609a5 151
8ab3d8a0
KR
152/* No prototype for this on Solaris 10. The man page says it's in
153 <unistd.h> ... but it lies. */
154#if ! HAVE_DECL_SETHOSTNAME
155int sethostname (char *name, size_t namelen);
156#endif
157
398609a5
JB
158/* On NextStep, <utime.h> doesn't define struct utime, unless we
159 #define _POSIX_SOURCE before #including it. I think this is less
160 of a kludge than defining struct utimbuf ourselves. */
161#ifdef UTIMBUF_NEEDS_POSIX
162#define _POSIX_SOURCE
163#endif
164
165#ifdef HAVE_SYS_UTIME_H
166#include <sys/utime.h>
167#endif
168
169#ifdef HAVE_UTIME_H
170#include <utime.h>
171#endif
172
173/* Please don't add any more #includes or #defines here. The hack
174 above means that _POSIX_SOURCE may be #defined, which will
eb7e1603
KR
175 encourage header files to do strange things.
176
177 FIXME: Maybe should undef _POSIX_SOURCE after it's done its job.
178
179 FIXME: Probably should do all the includes first, then all the fallback
180 declarations and defines, in case things are not in the header we
181 imagine. */
182
183
184
185
0f2d19dd 186\f
f015614a
MV
187
188/* Two often used patterns
189 */
190
191#define WITH_STRING(str,cstr,code) \
192 do { \
193 char *cstr = scm_to_locale_string (str); \
194 code; \
195 free (cstr); \
196 } while (0)
197
198#define STRING_SYSCALL(str,cstr,code) \
199 do { \
200 int eno; \
201 char *cstr = scm_to_locale_string (str); \
202 SCM_SYSCALL (code); \
203 eno = errno; free (cstr); errno = eno; \
204 } while (0)
205
206
207\f
bc45012d
JB
208SCM_SYMBOL (sym_read_pipe, "read pipe");
209SCM_SYMBOL (sym_write_pipe, "write pipe");
0f2d19dd 210
a1ec6916 211SCM_DEFINE (scm_pipe, "pipe", 0, 0, 0,
1bbd0b84 212 (),
1e6808ea
MG
213 "Return a newly created pipe: a pair of ports which are linked\n"
214 "together on the local machine. The @emph{car} is the input\n"
215 "port and the @emph{cdr} is the output port. Data written (and\n"
216 "flushed) to the output port can be read from the input port.\n"
217 "Pipes are commonly used for communication with a newly forked\n"
218 "child process. The need to flush the output port can be\n"
219 "avoided by making it unbuffered using @code{setvbuf}.\n"
220 "\n"
221 "Writes occur atomically provided the size of the data in bytes\n"
222 "is not greater than the value of @code{PIPE_BUF}. Note that\n"
223 "the output port is likely to block if too much data (typically\n"
224 "equal to @code{PIPE_BUF}) has been written but not yet read\n"
225 "from the input port.")
1bbd0b84 226#define FUNC_NAME s_scm_pipe
0f2d19dd
JB
227{
228 int fd[2], rv;
0f2d19dd 229 SCM p_rd, p_wt;
02b754d3 230
0f2d19dd
JB
231 rv = pipe (fd);
232 if (rv)
1bbd0b84 233 SCM_SYSERROR;
ee149d03
JB
234
235 p_rd = scm_fdes_to_port (fd[0], "r", sym_read_pipe);
236 p_wt = scm_fdes_to_port (fd[1], "w", sym_write_pipe);
0f2d19dd
JB
237 return scm_cons (p_rd, p_wt);
238}
1bbd0b84 239#undef FUNC_NAME
0f2d19dd
JB
240
241
0e958795 242#ifdef HAVE_GETGROUPS
a1ec6916 243SCM_DEFINE (scm_getgroups, "getgroups", 0, 0, 0,
1bbd0b84 244 (),
1e6808ea 245 "Return a vector of integers representing the current\n"
bb2c02f2 246 "supplementary group IDs.")
1bbd0b84 247#define FUNC_NAME s_scm_getgroups
0f2d19dd 248{
1d1559ce 249 SCM result;
66460dfb 250 int ngroups;
1be6b49c 251 size_t size;
66460dfb
DH
252 GETGROUPS_T *groups;
253
254 ngroups = getgroups (0, NULL);
3d2b2676 255 if (ngroups < 0)
1bbd0b84 256 SCM_SYSERROR;
3d2b2676
LC
257 else if (ngroups == 0)
258 return scm_c_make_vector (0, SCM_BOOL_F);
66460dfb
DH
259
260 size = ngroups * sizeof (GETGROUPS_T);
4c9419ac 261 groups = scm_malloc (size);
634aa8de 262 ngroups = getgroups (ngroups, groups);
66460dfb 263
f360a962
MV
264 result = scm_c_make_vector (ngroups, SCM_BOOL_F);
265 while (--ngroups >= 0)
4057a3e0 266 SCM_SIMPLE_VECTOR_SET (result, ngroups, scm_from_ulong (groups[ngroups]));
66460dfb 267
4c9419ac 268 free (groups);
1d1559ce 269 return result;
1bbd0b84
GB
270}
271#undef FUNC_NAME
0e958795 272#endif
0f2d19dd 273
f360a962
MV
274#ifdef HAVE_SETGROUPS
275SCM_DEFINE (scm_setgroups, "setgroups", 1, 0, 0,
276 (SCM group_vec),
fcc3adc2 277 "Set the current set of supplementary group IDs to the integers\n"
b7e64f8b 278 "in the given vector @var{group_vec}. The return value is\n"
fcc3adc2
KR
279 "unspecified.\n"
280 "\n"
281 "Generally only the superuser can set the process group IDs.")
f360a962
MV
282#define FUNC_NAME s_scm_setgroups
283{
284 size_t ngroups;
285 size_t size;
286 size_t i;
287 int result;
288 int save_errno;
289 GETGROUPS_T *groups;
290
291 SCM_VALIDATE_VECTOR (SCM_ARG1, group_vec);
292
4057a3e0 293 ngroups = SCM_SIMPLE_VECTOR_LENGTH (group_vec);
f360a962
MV
294
295 /* validate before allocating, so we don't have to worry about leaks */
296 for (i = 0; i < ngroups; i++)
297 {
298 unsigned long ulong_gid;
299 GETGROUPS_T gid;
4057a3e0
MV
300 SCM_VALIDATE_ULONG_COPY (1, SCM_SIMPLE_VECTOR_REF (group_vec, i),
301 ulong_gid);
f360a962
MV
302 gid = ulong_gid;
303 if (gid != ulong_gid)
4057a3e0 304 SCM_OUT_OF_RANGE (1, SCM_SIMPLE_VECTOR_REF (group_vec, i));
f360a962
MV
305 }
306
307 size = ngroups * sizeof (GETGROUPS_T);
2eb78d06 308 if (size / sizeof (GETGROUPS_T) != ngroups)
e11e83f3 309 SCM_OUT_OF_RANGE (SCM_ARG1, scm_from_int (ngroups));
f360a962
MV
310 groups = scm_malloc (size);
311 for(i = 0; i < ngroups; i++)
4057a3e0 312 groups [i] = SCM_NUM2ULONG (1, SCM_SIMPLE_VECTOR_REF (group_vec, i));
f360a962
MV
313
314 result = setgroups (ngroups, groups);
315 save_errno = errno; /* don't let free() touch errno */
316 free (groups);
317 errno = save_errno;
318 if (result < 0)
319 SCM_SYSERROR;
320 return SCM_UNSPECIFIED;
321}
322#undef FUNC_NAME
323#endif
324
82893676 325#ifdef HAVE_GETPWENT
a1ec6916 326SCM_DEFINE (scm_getpwuid, "getpw", 0, 1, 0,
1bbd0b84 327 (SCM user),
b7e64f8b
BT
328 "Look up an entry in the user database. @var{user} can be an\n"
329 "integer, a string, or omitted, giving the behaviour of\n"
330 "@code{getpwuid}, @code{getpwnam} or @code{getpwent}\n"
331 "respectively.")
1bbd0b84 332#define FUNC_NAME s_scm_getpwuid
0f2d19dd 333{
0f2d19dd 334 struct passwd *entry;
0f2d19dd 335
1d1559ce 336 SCM result = scm_c_make_vector (7, SCM_UNSPECIFIED);
7888309b 337 if (SCM_UNBNDP (user) || scm_is_false (user))
0f2d19dd 338 {
0f2d19dd 339 SCM_SYSCALL (entry = getpwent ());
3d781d49
JB
340 if (! entry)
341 {
3d781d49
JB
342 return SCM_BOOL_F;
343 }
0f2d19dd 344 }
e11e83f3 345 else if (scm_is_integer (user))
0f2d19dd 346 {
e11e83f3 347 entry = getpwuid (scm_to_int (user));
0f2d19dd
JB
348 }
349 else
350 {
f015614a
MV
351 WITH_STRING (user, c_user,
352 entry = getpwnam (c_user));
0f2d19dd
JB
353 }
354 if (!entry)
1bbd0b84 355 SCM_MISC_ERROR ("entry not found", SCM_EOL);
02b754d3 356
4057a3e0
MV
357 SCM_SIMPLE_VECTOR_SET(result, 0, scm_from_locale_string (entry->pw_name));
358 SCM_SIMPLE_VECTOR_SET(result, 1, scm_from_locale_string (entry->pw_passwd));
359 SCM_SIMPLE_VECTOR_SET(result, 2, scm_from_ulong (entry->pw_uid));
360 SCM_SIMPLE_VECTOR_SET(result, 3, scm_from_ulong (entry->pw_gid));
361 SCM_SIMPLE_VECTOR_SET(result, 4, scm_from_locale_string (entry->pw_gecos));
0f2d19dd 362 if (!entry->pw_dir)
4057a3e0 363 SCM_SIMPLE_VECTOR_SET(result, 5, scm_from_locale_string (""));
0f2d19dd 364 else
4057a3e0 365 SCM_SIMPLE_VECTOR_SET(result, 5, scm_from_locale_string (entry->pw_dir));
0f2d19dd 366 if (!entry->pw_shell)
4057a3e0 367 SCM_SIMPLE_VECTOR_SET(result, 6, scm_from_locale_string (""));
0f2d19dd 368 else
4057a3e0 369 SCM_SIMPLE_VECTOR_SET(result, 6, scm_from_locale_string (entry->pw_shell));
1d1559ce 370 return result;
0f2d19dd 371}
1bbd0b84 372#undef FUNC_NAME
82893676 373#endif /* HAVE_GETPWENT */
0f2d19dd
JB
374
375
0e958795 376#ifdef HAVE_SETPWENT
a1ec6916 377SCM_DEFINE (scm_setpwent, "setpw", 0, 1, 0,
1bbd0b84 378 (SCM arg),
b380b885
MD
379 "If called with a true argument, initialize or reset the password data\n"
380 "stream. Otherwise, close the stream. The @code{setpwent} and\n"
381 "@code{endpwent} procedures are implemented on top of this.")
1bbd0b84 382#define FUNC_NAME s_scm_setpwent
0f2d19dd 383{
7888309b 384 if (SCM_UNBNDP (arg) || scm_is_false (arg))
0f2d19dd
JB
385 endpwent ();
386 else
387 setpwent ();
388 return SCM_UNSPECIFIED;
389}
1bbd0b84 390#undef FUNC_NAME
0e958795 391#endif
0f2d19dd
JB
392
393
82893676 394#ifdef HAVE_GETGRENT
0f2d19dd 395/* Combines getgrgid and getgrnam. */
a1ec6916 396SCM_DEFINE (scm_getgrgid, "getgr", 0, 1, 0,
1bbd0b84 397 (SCM name),
b7e64f8b
BT
398 "Look up an entry in the group database. @var{name} can be an\n"
399 "integer, a string, or omitted, giving the behaviour of\n"
400 "@code{getgrgid}, @code{getgrnam} or @code{getgrent}\n"
401 "respectively.")
1bbd0b84 402#define FUNC_NAME s_scm_getgrgid
0f2d19dd 403{
0f2d19dd 404 struct group *entry;
1d1559ce 405 SCM result = scm_c_make_vector (4, SCM_UNSPECIFIED);
34d19ef6 406
7888309b 407 if (SCM_UNBNDP (name) || scm_is_false (name))
3d781d49
JB
408 {
409 SCM_SYSCALL (entry = getgrent ());
410 if (! entry)
411 {
3d781d49
JB
412 return SCM_BOOL_F;
413 }
414 }
e11e83f3
MV
415 else if (scm_is_integer (name))
416 SCM_SYSCALL (entry = getgrgid (scm_to_int (name)));
0f2d19dd 417 else
f015614a
MV
418 STRING_SYSCALL (name, c_name,
419 entry = getgrnam (c_name));
0f2d19dd 420 if (!entry)
1bbd0b84 421 SCM_SYSERROR;
02b754d3 422
4057a3e0
MV
423 SCM_SIMPLE_VECTOR_SET(result, 0, scm_from_locale_string (entry->gr_name));
424 SCM_SIMPLE_VECTOR_SET(result, 1, scm_from_locale_string (entry->gr_passwd));
425 SCM_SIMPLE_VECTOR_SET(result, 2, scm_from_ulong (entry->gr_gid));
426 SCM_SIMPLE_VECTOR_SET(result, 3, scm_makfromstrs (-1, entry->gr_mem));
1d1559ce 427 return result;
0f2d19dd 428}
1bbd0b84 429#undef FUNC_NAME
0f2d19dd
JB
430
431
432
a1ec6916 433SCM_DEFINE (scm_setgrent, "setgr", 0, 1, 0,
1bbd0b84 434 (SCM arg),
b380b885
MD
435 "If called with a true argument, initialize or reset the group data\n"
436 "stream. Otherwise, close the stream. The @code{setgrent} and\n"
437 "@code{endgrent} procedures are implemented on top of this.")
1bbd0b84 438#define FUNC_NAME s_scm_setgrent
0f2d19dd 439{
7888309b 440 if (SCM_UNBNDP (arg) || scm_is_false (arg))
0f2d19dd
JB
441 endgrent ();
442 else
443 setgrent ();
444 return SCM_UNSPECIFIED;
445}
1bbd0b84 446#undef FUNC_NAME
82893676 447#endif /* HAVE_GETGRENT */
0f2d19dd
JB
448
449
4ea9429e
AW
450#ifdef HAVE_GETRLIMIT
451#ifdef RLIMIT_AS
452SCM_SYMBOL (sym_as, "as");
453#endif
454#ifdef RLIMIT_CORE
455SCM_SYMBOL (sym_core, "core");
456#endif
457#ifdef RLIMIT_CPU
458SCM_SYMBOL (sym_cpu, "cpu");
459#endif
460#ifdef RLIMIT_DATA
461SCM_SYMBOL (sym_data, "data");
462#endif
463#ifdef RLIMIT_FSIZE
464SCM_SYMBOL (sym_fsize, "fsize");
465#endif
466#ifdef RLIMIT_MEMLOCK
467SCM_SYMBOL (sym_memlock, "memlock");
468#endif
469#ifdef RLIMIT_MSGQUEUE
470SCM_SYMBOL (sym_msgqueue, "msgqueue");
471#endif
472#ifdef RLIMIT_NICE
473SCM_SYMBOL (sym_nice, "nice");
474#endif
475#ifdef RLIMIT_NOFILE
476SCM_SYMBOL (sym_nofile, "nofile");
477#endif
478#ifdef RLIMIT_NPROC
479SCM_SYMBOL (sym_nproc, "nproc");
480#endif
481#ifdef RLIMIT_RSS
482SCM_SYMBOL (sym_rss, "rss");
483#endif
484#ifdef RLIMIT_RTPRIO
485SCM_SYMBOL (sym_rtprio, "rtprio");
486#endif
487#ifdef RLIMIT_RTPRIO
488SCM_SYMBOL (sym_rttime, "rttime");
489#endif
490#ifdef RLIMIT_SIGPENDING
491SCM_SYMBOL (sym_sigpending, "sigpending");
492#endif
493#ifdef RLIMIT_STACK
494SCM_SYMBOL (sym_stack, "stack");
495#endif
496
497static int
498scm_to_resource (SCM s, const char *func, int pos)
499{
500 if (scm_is_number (s))
501 return scm_to_int (s);
502
503 SCM_ASSERT_TYPE (scm_is_symbol (s), s, pos, func, "symbol");
504
505#ifdef RLIMIT_AS
d223c3fc 506 if (scm_is_eq (s, sym_as))
4ea9429e
AW
507 return RLIMIT_AS;
508#endif
509#ifdef RLIMIT_CORE
d223c3fc 510 if (scm_is_eq (s, sym_core))
4ea9429e
AW
511 return RLIMIT_CORE;
512#endif
513#ifdef RLIMIT_CPU
d223c3fc 514 if (scm_is_eq (s, sym_cpu))
4ea9429e
AW
515 return RLIMIT_CPU;
516#endif
517#ifdef RLIMIT_DATA
d223c3fc 518 if (scm_is_eq (s, sym_data))
4ea9429e
AW
519 return RLIMIT_DATA;
520#endif
521#ifdef RLIMIT_FSIZE
d223c3fc 522 if (scm_is_eq (s, sym_fsize))
4ea9429e
AW
523 return RLIMIT_FSIZE;
524#endif
525#ifdef RLIMIT_MEMLOCK
d223c3fc 526 if (scm_is_eq (s, sym_memlock))
4ea9429e
AW
527 return RLIMIT_MEMLOCK;
528#endif
529#ifdef RLIMIT_MSGQUEUE
d223c3fc 530 if (scm_is_eq (s, sym_msgqueue))
4ea9429e
AW
531 return RLIMIT_MSGQUEUE;
532#endif
533#ifdef RLIMIT_NICE
d223c3fc 534 if (scm_is_eq (s, sym_nice))
4ea9429e
AW
535 return RLIMIT_NICE;
536#endif
537#ifdef RLIMIT_NOFILE
d223c3fc 538 if (scm_is_eq (s, sym_nofile))
4ea9429e
AW
539 return RLIMIT_NOFILE;
540#endif
541#ifdef RLIMIT_NPROC
d223c3fc 542 if (scm_is_eq (s, sym_nproc))
4ea9429e
AW
543 return RLIMIT_NPROC;
544#endif
545#ifdef RLIMIT_RSS
d223c3fc 546 if (scm_is_eq (s, sym_rss))
4ea9429e
AW
547 return RLIMIT_RSS;
548#endif
549#ifdef RLIMIT_RTPRIO
d223c3fc 550 if (scm_is_eq (s, sym_rtprio))
4ea9429e
AW
551 return RLIMIT_RTPRIO;
552#endif
553#ifdef RLIMIT_RTPRIO
d223c3fc 554 if (scm_is_eq (s, sym_rttime))
4ea9429e
AW
555 return RLIMIT_RTPRIO;
556#endif
557#ifdef RLIMIT_SIGPENDING
d223c3fc 558 if (scm_is_eq (s, sym_sigpending))
4ea9429e
AW
559 return RLIMIT_SIGPENDING;
560#endif
561#ifdef RLIMIT_STACK
d223c3fc 562 if (scm_is_eq (s, sym_stack))
4ea9429e
AW
563 return RLIMIT_STACK;
564#endif
565
566 scm_misc_error (func, "invalid rlimit resource ~A", scm_list_1 (s));
567 return 0;
568}
569
570SCM_DEFINE (scm_getrlimit, "getrlimit", 1, 0, 0,
571 (SCM resource),
572 "Get a resource limit for this process. @var{resource} identifies the resource,\n"
573 "either as an integer or as a symbol. For example, @code{(getrlimit 'stack)}\n"
574 "gets the limits associated with @code{RLIMIT_STACK}.\n\n"
575 "@code{getrlimit} returns two values, the soft and the hard limit. If no\n"
576 "limit is set for the resource in question, the returned limit will be @code{#f}.")
577#define FUNC_NAME s_scm_getrlimit
578{
579 int iresource;
580 struct rlimit lim = { 0, 0 };
581
582 iresource = scm_to_resource (resource, FUNC_NAME, 1);
583
584 if (getrlimit (iresource, &lim) != 0)
585 scm_syserror (FUNC_NAME);
586
587 return scm_values (scm_list_2 ((lim.rlim_cur == RLIM_INFINITY) ? SCM_BOOL_F
588 : scm_from_long (lim.rlim_cur),
589 (lim.rlim_max == RLIM_INFINITY) ? SCM_BOOL_F
590 : scm_from_long (lim.rlim_max)));
591}
592#undef FUNC_NAME
593
594
595#ifdef HAVE_SETRLIMIT
596SCM_DEFINE (scm_setrlimit, "setrlimit", 3, 0, 0,
597 (SCM resource, SCM soft, SCM hard),
598 "Set a resource limit for this process. @var{resource} identifies the resource,\n"
599 "either as an integer or as a symbol. @var{soft} and @var{hard} should be integers,\n"
600 "or @code{#f} to indicate no limit (i.e., @code{RLIM_INFINITY}).\n\n"
601 "For example, @code{(setrlimit 'stack 150000 300000)} sets the @code{RLIMIT_STACK}\n"
602 "limit to 150 kilobytes, with a hard limit of 300 kB.")
603#define FUNC_NAME s_scm_setrlimit
604{
605 int iresource;
606 struct rlimit lim = { 0, 0 };
607
608 iresource = scm_to_resource (resource, FUNC_NAME, 1);
609
393baa8a
AW
610 lim.rlim_cur = scm_is_false (soft) ? RLIM_INFINITY : scm_to_long (soft);
611 lim.rlim_max = scm_is_false (hard) ? RLIM_INFINITY : scm_to_long (hard);
4ea9429e
AW
612
613 if (setrlimit (iresource, &lim) != 0)
614 scm_syserror (FUNC_NAME);
615
616 return SCM_UNSPECIFIED;
617}
618#undef FUNC_NAME
619#endif /* HAVE_SETRLIMIT */
620#endif /* HAVE_GETRLIMIT */
621
622
a1ec6916 623SCM_DEFINE (scm_kill, "kill", 2, 0, 0,
1bbd0b84 624 (SCM pid, SCM sig),
b380b885
MD
625 "Sends a signal to the specified process or group of processes.\n\n"
626 "@var{pid} specifies the processes to which the signal is sent:\n\n"
627 "@table @r\n"
628 "@item @var{pid} greater than 0\n"
629 "The process whose identifier is @var{pid}.\n"
630 "@item @var{pid} equal to 0\n"
631 "All processes in the current process group.\n"
632 "@item @var{pid} less than -1\n"
633 "The process group whose identifier is -@var{pid}\n"
634 "@item @var{pid} equal to -1\n"
635 "If the process is privileged, all processes except for some special\n"
636 "system processes. Otherwise, all processes with the current effective\n"
637 "user ID.\n"
638 "@end table\n\n"
639 "@var{sig} should be specified using a variable corresponding to\n"
640 "the Unix symbolic name, e.g.,\n\n"
641 "@defvar SIGHUP\n"
642 "Hang-up signal.\n"
643 "@end defvar\n\n"
644 "@defvar SIGINT\n"
645 "Interrupt signal.\n"
646 "@end defvar")
1bbd0b84 647#define FUNC_NAME s_scm_kill
0f2d19dd 648{
0f2d19dd 649 /* Signal values are interned in scm_init_posix(). */
82893676 650#ifdef HAVE_KILL
a55c2b68 651 if (kill (scm_to_int (pid), scm_to_int (sig)) != 0)
23d72566 652 SCM_SYSERROR;
82893676 653#else
23d72566
KR
654 /* Mingw has raise(), but not kill(). (Other raw DOS environments might
655 be similar.) Use raise() when the requested pid is our own process,
656 otherwise bomb. */
a55c2b68 657 if (scm_to_int (pid) == getpid ())
23d72566
KR
658 {
659 if (raise (scm_to_int (sig)) != 0)
660 {
661 err:
662 SCM_SYSERROR;
663 }
664 else
665 {
666 errno = ENOSYS;
667 goto err;
668 }
669 }
82893676 670#endif
02b754d3 671 return SCM_UNSPECIFIED;
0f2d19dd 672}
1bbd0b84 673#undef FUNC_NAME
0f2d19dd 674
d00ae47e 675#ifdef HAVE_WAITPID
a1ec6916 676SCM_DEFINE (scm_waitpid, "waitpid", 1, 1, 0,
1bbd0b84 677 (SCM pid, SCM options),
b380b885
MD
678 "This procedure collects status information from a child process which\n"
679 "has terminated or (optionally) stopped. Normally it will\n"
680 "suspend the calling process until this can be done. If more than one\n"
681 "child process is eligible then one will be chosen by the operating system.\n\n"
682 "The value of @var{pid} determines the behaviour:\n\n"
683 "@table @r\n"
684 "@item @var{pid} greater than 0\n"
685 "Request status information from the specified child process.\n"
686 "@item @var{pid} equal to -1 or WAIT_ANY\n"
687 "Request status information for any child process.\n"
688 "@item @var{pid} equal to 0 or WAIT_MYPGRP\n"
689 "Request status information for any child process in the current process\n"
690 "group.\n"
691 "@item @var{pid} less than -1\n"
692 "Request status information for any child process whose process group ID\n"
b7e64f8b 693 "is -@var{pid}.\n"
b380b885
MD
694 "@end table\n\n"
695 "The @var{options} argument, if supplied, should be the bitwise OR of the\n"
696 "values of zero or more of the following variables:\n\n"
697 "@defvar WNOHANG\n"
698 "Return immediately even if there are no child processes to be collected.\n"
699 "@end defvar\n\n"
700 "@defvar WUNTRACED\n"
701 "Report status information for stopped processes as well as terminated\n"
702 "processes.\n"
703 "@end defvar\n\n"
704 "The return value is a pair containing:\n\n"
705 "@enumerate\n"
706 "@item\n"
707 "The process ID of the child process, or 0 if @code{WNOHANG} was\n"
708 "specified and no process was collected.\n"
709 "@item\n"
710 "The integer status value.\n"
711 "@end enumerate")
1bbd0b84 712#define FUNC_NAME s_scm_waitpid
0f2d19dd
JB
713{
714 int i;
715 int status;
716 int ioptions;
0f2d19dd
JB
717 if (SCM_UNBNDP (options))
718 ioptions = 0;
719 else
720 {
0f2d19dd 721 /* Flags are interned in scm_init_posix. */
a55c2b68 722 ioptions = scm_to_int (options);
0f2d19dd 723 }
a55c2b68 724 SCM_SYSCALL (i = waitpid (scm_to_int (pid), &status, ioptions));
02b754d3 725 if (i == -1)
1bbd0b84 726 SCM_SYSERROR;
a55c2b68 727 return scm_cons (scm_from_int (i), scm_from_int (status));
0f2d19dd 728}
1bbd0b84 729#undef FUNC_NAME
d00ae47e 730#endif /* HAVE_WAITPID */
0f2d19dd 731
82893676 732#ifndef __MINGW32__
a1ec6916 733SCM_DEFINE (scm_status_exit_val, "status:exit-val", 1, 0, 0,
1bbd0b84 734 (SCM status),
1e6808ea
MG
735 "Return the exit status value, as would be set if a process\n"
736 "ended normally through a call to @code{exit} or @code{_exit},\n"
737 "if any, otherwise @code{#f}.")
1bbd0b84 738#define FUNC_NAME s_scm_status_exit_val
67ec3667 739{
e67dc2be
JB
740 int lstatus;
741
e67dc2be 742 /* On Ultrix, the WIF... macros assume their argument is an lvalue;
e11e83f3 743 go figure. */
a55c2b68 744 lstatus = scm_to_int (status);
e67dc2be 745 if (WIFEXITED (lstatus))
a55c2b68 746 return (scm_from_int (WEXITSTATUS (lstatus)));
67ec3667
GH
747 else
748 return SCM_BOOL_F;
749}
1bbd0b84 750#undef FUNC_NAME
e67dc2be 751
a1ec6916 752SCM_DEFINE (scm_status_term_sig, "status:term-sig", 1, 0, 0,
1bbd0b84 753 (SCM status),
1e6808ea
MG
754 "Return the signal number which terminated the process, if any,\n"
755 "otherwise @code{#f}.")
1bbd0b84 756#define FUNC_NAME s_scm_status_term_sig
67ec3667 757{
e67dc2be
JB
758 int lstatus;
759
a55c2b68 760 lstatus = scm_to_int (status);
e67dc2be 761 if (WIFSIGNALED (lstatus))
a55c2b68 762 return scm_from_int (WTERMSIG (lstatus));
67ec3667
GH
763 else
764 return SCM_BOOL_F;
765}
1bbd0b84 766#undef FUNC_NAME
0f2d19dd 767
a1ec6916 768SCM_DEFINE (scm_status_stop_sig, "status:stop-sig", 1, 0, 0,
1bbd0b84 769 (SCM status),
1e6808ea
MG
770 "Return the signal number which stopped the process, if any,\n"
771 "otherwise @code{#f}.")
1bbd0b84 772#define FUNC_NAME s_scm_status_stop_sig
67ec3667 773{
e67dc2be
JB
774 int lstatus;
775
a55c2b68 776 lstatus = scm_to_int (status);
e67dc2be 777 if (WIFSTOPPED (lstatus))
a55c2b68 778 return scm_from_int (WSTOPSIG (lstatus));
67ec3667
GH
779 else
780 return SCM_BOOL_F;
781}
1bbd0b84 782#undef FUNC_NAME
82893676 783#endif /* __MINGW32__ */
0f2d19dd 784
82893676 785#ifdef HAVE_GETPPID
a1ec6916 786SCM_DEFINE (scm_getppid, "getppid", 0, 0, 0,
1bbd0b84 787 (),
1e6808ea
MG
788 "Return an integer representing the process ID of the parent\n"
789 "process.")
1bbd0b84 790#define FUNC_NAME s_scm_getppid
0f2d19dd 791{
e11e83f3 792 return scm_from_int (getppid ());
0f2d19dd 793}
1bbd0b84 794#undef FUNC_NAME
82893676 795#endif /* HAVE_GETPPID */
0f2d19dd
JB
796
797
82893676 798#ifndef __MINGW32__
a1ec6916 799SCM_DEFINE (scm_getuid, "getuid", 0, 0, 0,
1bbd0b84 800 (),
1e6808ea 801 "Return an integer representing the current real user ID.")
1bbd0b84 802#define FUNC_NAME s_scm_getuid
0f2d19dd 803{
e11e83f3 804 return scm_from_int (getuid ());
0f2d19dd 805}
1bbd0b84 806#undef FUNC_NAME
0f2d19dd
JB
807
808
809
a1ec6916 810SCM_DEFINE (scm_getgid, "getgid", 0, 0, 0,
1bbd0b84 811 (),
1e6808ea 812 "Return an integer representing the current real group ID.")
1bbd0b84 813#define FUNC_NAME s_scm_getgid
0f2d19dd 814{
e11e83f3 815 return scm_from_int (getgid ());
0f2d19dd 816}
1bbd0b84 817#undef FUNC_NAME
0f2d19dd
JB
818
819
820
a1ec6916 821SCM_DEFINE (scm_geteuid, "geteuid", 0, 0, 0,
1bbd0b84 822 (),
1e6808ea 823 "Return an integer representing the current effective user ID.\n"
b380b885 824 "If the system does not support effective IDs, then the real ID\n"
480fa28d 825 "is returned. @code{(provided? 'EIDs)} reports whether the\n"
1e6808ea 826 "system supports effective IDs.")
1bbd0b84 827#define FUNC_NAME s_scm_geteuid
0f2d19dd
JB
828{
829#ifdef HAVE_GETEUID
e11e83f3 830 return scm_from_int (geteuid ());
0f2d19dd 831#else
e11e83f3 832 return scm_from_int (getuid ());
0f2d19dd
JB
833#endif
834}
1bbd0b84 835#undef FUNC_NAME
0f2d19dd
JB
836
837
a1ec6916 838SCM_DEFINE (scm_getegid, "getegid", 0, 0, 0,
1bbd0b84 839 (),
1e6808ea 840 "Return an integer representing the current effective group ID.\n"
b380b885 841 "If the system does not support effective IDs, then the real ID\n"
480fa28d 842 "is returned. @code{(provided? 'EIDs)} reports whether the\n"
1e6808ea 843 "system supports effective IDs.")
1bbd0b84 844#define FUNC_NAME s_scm_getegid
0f2d19dd
JB
845{
846#ifdef HAVE_GETEUID
e11e83f3 847 return scm_from_int (getegid ());
0f2d19dd 848#else
e11e83f3 849 return scm_from_int (getgid ());
0f2d19dd
JB
850#endif
851}
1bbd0b84 852#undef FUNC_NAME
0f2d19dd
JB
853
854
a1ec6916 855SCM_DEFINE (scm_setuid, "setuid", 1, 0, 0,
1bbd0b84 856 (SCM id),
b380b885
MD
857 "Sets both the real and effective user IDs to the integer @var{id}, provided\n"
858 "the process has appropriate privileges.\n"
859 "The return value is unspecified.")
1bbd0b84 860#define FUNC_NAME s_scm_setuid
0f2d19dd 861{
a55c2b68 862 if (setuid (scm_to_int (id)) != 0)
1bbd0b84 863 SCM_SYSERROR;
02b754d3 864 return SCM_UNSPECIFIED;
0f2d19dd 865}
1bbd0b84 866#undef FUNC_NAME
0f2d19dd 867
a1ec6916 868SCM_DEFINE (scm_setgid, "setgid", 1, 0, 0,
1bbd0b84 869 (SCM id),
b380b885
MD
870 "Sets both the real and effective group IDs to the integer @var{id}, provided\n"
871 "the process has appropriate privileges.\n"
872 "The return value is unspecified.")
1bbd0b84 873#define FUNC_NAME s_scm_setgid
0f2d19dd 874{
a55c2b68 875 if (setgid (scm_to_int (id)) != 0)
1bbd0b84 876 SCM_SYSERROR;
02b754d3 877 return SCM_UNSPECIFIED;
0f2d19dd 878}
1bbd0b84 879#undef FUNC_NAME
0f2d19dd 880
a1ec6916 881SCM_DEFINE (scm_seteuid, "seteuid", 1, 0, 0,
1bbd0b84 882 (SCM id),
b380b885
MD
883 "Sets the effective user ID to the integer @var{id}, provided the process\n"
884 "has appropriate privileges. If effective IDs are not supported, the\n"
480fa28d 885 "real ID is set instead -- @code{(provided? 'EIDs)} reports whether the\n"
b380b885
MD
886 "system supports effective IDs.\n"
887 "The return value is unspecified.")
1bbd0b84 888#define FUNC_NAME s_scm_seteuid
0f2d19dd 889{
02b754d3
GH
890 int rv;
891
0f2d19dd 892#ifdef HAVE_SETEUID
a55c2b68 893 rv = seteuid (scm_to_int (id));
0f2d19dd 894#else
a55c2b68 895 rv = setuid (scm_to_int (id));
0f2d19dd 896#endif
02b754d3 897 if (rv != 0)
1bbd0b84 898 SCM_SYSERROR;
02b754d3 899 return SCM_UNSPECIFIED;
0f2d19dd 900}
1bbd0b84 901#undef FUNC_NAME
7beabedb
MG
902#endif /* __MINGW32__ */
903
0f2d19dd 904
0e958795 905#ifdef HAVE_SETEGID
a1ec6916 906SCM_DEFINE (scm_setegid, "setegid", 1, 0, 0,
1bbd0b84 907 (SCM id),
b380b885
MD
908 "Sets the effective group ID to the integer @var{id}, provided the process\n"
909 "has appropriate privileges. If effective IDs are not supported, the\n"
480fa28d 910 "real ID is set instead -- @code{(provided? 'EIDs)} reports whether the\n"
b380b885
MD
911 "system supports effective IDs.\n"
912 "The return value is unspecified.")
1bbd0b84 913#define FUNC_NAME s_scm_setegid
0f2d19dd 914{
02b754d3
GH
915 int rv;
916
0f2d19dd 917#ifdef HAVE_SETEUID
a55c2b68 918 rv = setegid (scm_to_int (id));
0f2d19dd 919#else
a55c2b68 920 rv = setgid (scm_to_int (id));
0f2d19dd 921#endif
02b754d3 922 if (rv != 0)
1bbd0b84 923 SCM_SYSERROR;
02b754d3
GH
924 return SCM_UNSPECIFIED;
925
0f2d19dd 926}
1bbd0b84 927#undef FUNC_NAME
0e958795 928#endif
0f2d19dd 929
82893676
MG
930
931#ifdef HAVE_GETPGRP
a1ec6916 932SCM_DEFINE (scm_getpgrp, "getpgrp", 0, 0, 0,
1bbd0b84 933 (),
1e6808ea 934 "Return an integer representing the current process group ID.\n"
b380b885 935 "This is the POSIX definition, not BSD.")
1bbd0b84 936#define FUNC_NAME s_scm_getpgrp
0f2d19dd
JB
937{
938 int (*fn)();
4625e44f 939 fn = (int (*) ()) getpgrp;
e11e83f3 940 return scm_from_int (fn (0));
0f2d19dd 941}
1bbd0b84 942#undef FUNC_NAME
82893676
MG
943#endif /* HAVE_GETPGRP */
944
0f2d19dd 945
f25f761d 946#ifdef HAVE_SETPGID
a1ec6916 947SCM_DEFINE (scm_setpgid, "setpgid", 2, 0, 0,
1bbd0b84 948 (SCM pid, SCM pgid),
b380b885
MD
949 "Move the process @var{pid} into the process group @var{pgid}. @var{pid} or\n"
950 "@var{pgid} must be integers: they can be zero to indicate the ID of the\n"
951 "current process.\n"
952 "Fails on systems that do not support job control.\n"
953 "The return value is unspecified.")
1bbd0b84 954#define FUNC_NAME s_scm_setpgid
0f2d19dd 955{
02b754d3 956 /* FIXME(?): may be known as setpgrp. */
a55c2b68 957 if (setpgid (scm_to_int (pid), scm_to_int (pgid)) != 0)
1bbd0b84 958 SCM_SYSERROR;
02b754d3 959 return SCM_UNSPECIFIED;
0f2d19dd 960}
1bbd0b84 961#undef FUNC_NAME
f25f761d 962#endif /* HAVE_SETPGID */
0f2d19dd 963
f25f761d 964#ifdef HAVE_SETSID
a1ec6916 965SCM_DEFINE (scm_setsid, "setsid", 0, 0, 0,
1bbd0b84 966 (),
b380b885
MD
967 "Creates a new session. The current process becomes the session leader\n"
968 "and is put in a new process group. The process will be detached\n"
969 "from its controlling terminal if it has one.\n"
970 "The return value is an integer representing the new process group ID.")
1bbd0b84 971#define FUNC_NAME s_scm_setsid
0f2d19dd
JB
972{
973 pid_t sid = setsid ();
02b754d3 974 if (sid == -1)
1bbd0b84 975 SCM_SYSERROR;
02b754d3 976 return SCM_UNSPECIFIED;
0f2d19dd 977}
1bbd0b84 978#undef FUNC_NAME
f25f761d 979#endif /* HAVE_SETSID */
0f2d19dd 980
3e5aed1c
NJ
981#ifdef HAVE_GETSID
982SCM_DEFINE (scm_getsid, "getsid", 1, 0, 0,
983 (SCM pid),
984 "Returns the session ID of process @var{pid}. (The session\n"
985 "ID of a process is the process group ID of its session leader.)")
986#define FUNC_NAME s_scm_getsid
987{
988 return scm_from_int (getsid (scm_to_int (pid)));
989}
990#undef FUNC_NAME
991#endif /* HAVE_GETSID */
992
e8a59063
KR
993
994/* ttyname returns its result in a single static buffer, hence
995 scm_i_misc_mutex for thread safety. In glibc 2.3.2 two threads
996 continuously calling ttyname will otherwise get an overwrite quite
997 easily.
998
999 ttyname_r (when available) could be used instead of scm_i_misc_mutex, but
1000 there's probably little to be gained in either speed or parallelism. */
1001
82893676 1002#ifdef HAVE_TTYNAME
a1ec6916 1003SCM_DEFINE (scm_ttyname, "ttyname", 1, 0, 0,
1bbd0b84 1004 (SCM port),
1e6808ea
MG
1005 "Return a string with the name of the serial terminal device\n"
1006 "underlying @var{port}.")
1bbd0b84 1007#define FUNC_NAME s_scm_ttyname
0f2d19dd 1008{
1d1559ce 1009 char *result;
e8a59063 1010 int fd, err;
a1ef7406 1011 SCM ret = SCM_BOOL_F;
78446828
MV
1012
1013 port = SCM_COERCE_OUTPORT (port);
34d19ef6 1014 SCM_VALIDATE_OPPORT (1, port);
a98bddfd 1015 if (!SCM_FPORTP (port))
0f2d19dd 1016 return SCM_BOOL_F;
ee149d03 1017 fd = SCM_FPORT_FDES (port);
e8a59063 1018
9de87eea 1019 scm_i_scm_pthread_mutex_lock (&scm_i_misc_mutex);
a1ef7406 1020
1d1559ce 1021 SCM_SYSCALL (result = ttyname (fd));
e8a59063 1022 err = errno;
a1ef7406
LC
1023 if (result != NULL)
1024 result = strdup (result);
1025
9de87eea 1026 scm_i_pthread_mutex_unlock (&scm_i_misc_mutex);
e8a59063 1027
1d1559ce 1028 if (!result)
e8a59063
KR
1029 {
1030 errno = err;
1031 SCM_SYSERROR;
1032 }
a1ef7406
LC
1033 else
1034 ret = scm_take_locale_string (result);
1035
e8a59063 1036 return ret;
0f2d19dd 1037}
1bbd0b84 1038#undef FUNC_NAME
82893676 1039#endif /* HAVE_TTYNAME */
0f2d19dd 1040
e8a59063 1041
0a9d83b0
KR
1042/* For thread safety "buf" is used instead of NULL for the ctermid static
1043 buffer. Actually it's unlikely the controlling terminal will change
1044 during program execution, and indeed on glibc (2.3.2) it's always just
1045 "/dev/tty", but L_ctermid on the stack is easy and fast and guarantees
1046 safety everywhere. */
f25f761d 1047#ifdef HAVE_CTERMID
a1ec6916 1048SCM_DEFINE (scm_ctermid, "ctermid", 0, 0, 0,
1bbd0b84 1049 (),
1e6808ea
MG
1050 "Return a string containing the file name of the controlling\n"
1051 "terminal for the current process.")
1bbd0b84 1052#define FUNC_NAME s_scm_ctermid
0f2d19dd 1053{
0a9d83b0
KR
1054 char buf[L_ctermid];
1055 char *result = ctermid (buf);
02b754d3 1056 if (*result == '\0')
1bbd0b84 1057 SCM_SYSERROR;
cc95e00a 1058 return scm_from_locale_string (result);
0f2d19dd 1059}
1bbd0b84 1060#undef FUNC_NAME
f25f761d 1061#endif /* HAVE_CTERMID */
0f2d19dd 1062
f25f761d 1063#ifdef HAVE_TCGETPGRP
a1ec6916 1064SCM_DEFINE (scm_tcgetpgrp, "tcgetpgrp", 1, 0, 0,
1bbd0b84 1065 (SCM port),
1e6808ea
MG
1066 "Return the process group ID of the foreground process group\n"
1067 "associated with the terminal open on the file descriptor\n"
1068 "underlying @var{port}.\n"
1069 "\n"
b380b885
MD
1070 "If there is no foreground process group, the return value is a\n"
1071 "number greater than 1 that does not match the process group ID\n"
1072 "of any existing process group. This can happen if all of the\n"
1073 "processes in the job that was formerly the foreground job have\n"
1074 "terminated, and no other job has yet been moved into the\n"
1075 "foreground.")
1bbd0b84 1076#define FUNC_NAME s_scm_tcgetpgrp
0f2d19dd
JB
1077{
1078 int fd;
1079 pid_t pgid;
78446828
MV
1080
1081 port = SCM_COERCE_OUTPORT (port);
1082
34d19ef6 1083 SCM_VALIDATE_OPFPORT (1, port);
ee149d03
JB
1084 fd = SCM_FPORT_FDES (port);
1085 if ((pgid = tcgetpgrp (fd)) == -1)
1bbd0b84 1086 SCM_SYSERROR;
e11e83f3 1087 return scm_from_int (pgid);
1bbd0b84
GB
1088}
1089#undef FUNC_NAME
f25f761d 1090#endif /* HAVE_TCGETPGRP */
0f2d19dd 1091
f25f761d 1092#ifdef HAVE_TCSETPGRP
a1ec6916 1093SCM_DEFINE (scm_tcsetpgrp, "tcsetpgrp", 2, 0, 0,
1bbd0b84 1094 (SCM port, SCM pgid),
b380b885
MD
1095 "Set the foreground process group ID for the terminal used by the file\n"
1096 "descriptor underlying @var{port} to the integer @var{pgid}.\n"
1097 "The calling process\n"
1098 "must be a member of the same session as @var{pgid} and must have the same\n"
1099 "controlling terminal. The return value is unspecified.")
1bbd0b84 1100#define FUNC_NAME s_scm_tcsetpgrp
0f2d19dd
JB
1101{
1102 int fd;
78446828
MV
1103
1104 port = SCM_COERCE_OUTPORT (port);
1105
34d19ef6 1106 SCM_VALIDATE_OPFPORT (1, port);
ee149d03 1107 fd = SCM_FPORT_FDES (port);
a55c2b68 1108 if (tcsetpgrp (fd, scm_to_int (pgid)) == -1)
1bbd0b84 1109 SCM_SYSERROR;
02b754d3 1110 return SCM_UNSPECIFIED;
1bbd0b84
GB
1111}
1112#undef FUNC_NAME
f25f761d 1113#endif /* HAVE_TCSETPGRP */
0f2d19dd 1114
a1ec6916 1115SCM_DEFINE (scm_execl, "execl", 1, 0, 1,
1bbd0b84 1116 (SCM filename, SCM args),
b7e64f8b 1117 "Executes the file named by @var{filename} as a new process image.\n"
b380b885 1118 "The remaining arguments are supplied to the process; from a C program\n"
bb2c02f2 1119 "they are accessible as the @code{argv} argument to @code{main}.\n"
b7e64f8b 1120 "Conventionally the first @var{arg} is the same as @var{filename}.\n"
8f85c0c6 1121 "All arguments must be strings.\n\n"
b380b885
MD
1122 "If @var{arg} is missing, @var{path} is executed with a null\n"
1123 "argument list, which may have system-dependent side-effects.\n\n"
1124 "This procedure is currently implemented using the @code{execv} system\n"
1125 "call, but we call it @code{execl} because of its Scheme calling interface.")
1bbd0b84 1126#define FUNC_NAME s_scm_execl
0f2d19dd 1127{
7f03f970
MV
1128 char *exec_file;
1129 char **exec_argv;
1130
661ae7ab 1131 scm_dynwind_begin (0);
7f03f970
MV
1132
1133 exec_file = scm_to_locale_string (filename);
661ae7ab 1134 scm_dynwind_free (exec_file);
7f03f970
MV
1135
1136 exec_argv = scm_i_allocate_string_pointers (args);
7f03f970 1137
8ab3d8a0
KR
1138 execv (exec_file,
1139#ifdef __MINGW32__
1140 /* extra "const" in mingw formals, provokes warning from gcc */
1141 (const char * const *)
1142#endif
1143 exec_argv);
1bbd0b84 1144 SCM_SYSERROR;
7f03f970 1145
02b754d3 1146 /* not reached. */
661ae7ab 1147 scm_dynwind_end ();
02b754d3 1148 return SCM_BOOL_F;
0f2d19dd 1149}
1bbd0b84 1150#undef FUNC_NAME
0f2d19dd 1151
a1ec6916 1152SCM_DEFINE (scm_execlp, "execlp", 1, 0, 1,
1bbd0b84 1153 (SCM filename, SCM args),
b380b885
MD
1154 "Similar to @code{execl}, however if\n"
1155 "@var{filename} does not contain a slash\n"
1156 "then the file to execute will be located by searching the\n"
1157 "directories listed in the @code{PATH} environment variable.\n\n"
6bcd01fc 1158 "This procedure is currently implemented using the @code{execvp} system\n"
b380b885 1159 "call, but we call it @code{execlp} because of its Scheme calling interface.")
1bbd0b84 1160#define FUNC_NAME s_scm_execlp
0f2d19dd 1161{
7f03f970
MV
1162 char *exec_file;
1163 char **exec_argv;
1164
661ae7ab 1165 scm_dynwind_begin (0);
7f03f970
MV
1166
1167 exec_file = scm_to_locale_string (filename);
661ae7ab 1168 scm_dynwind_free (exec_file);
7f03f970
MV
1169
1170 exec_argv = scm_i_allocate_string_pointers (args);
7f03f970 1171
8ab3d8a0
KR
1172 execvp (exec_file,
1173#ifdef __MINGW32__
1174 /* extra "const" in mingw formals, provokes warning from gcc */
1175 (const char * const *)
1176#endif
1177 exec_argv);
1bbd0b84 1178 SCM_SYSERROR;
7f03f970 1179
02b754d3 1180 /* not reached. */
661ae7ab 1181 scm_dynwind_end ();
02b754d3 1182 return SCM_BOOL_F;
0f2d19dd 1183}
1bbd0b84 1184#undef FUNC_NAME
0f2d19dd 1185
6afcd3b2 1186
807f353f
KR
1187/* OPTIMIZE-ME: scm_execle doesn't need malloced copies of the environment
1188 list strings the way environ_list_to_c gives. */
1189
a1ec6916 1190SCM_DEFINE (scm_execle, "execle", 2, 0, 1,
1bbd0b84 1191 (SCM filename, SCM env, SCM args),
b380b885
MD
1192 "Similar to @code{execl}, but the environment of the new process is\n"
1193 "specified by @var{env}, which must be a list of strings as returned by the\n"
1194 "@code{environ} procedure.\n\n"
1195 "This procedure is currently implemented using the @code{execve} system\n"
1196 "call, but we call it @code{execle} because of its Scheme calling interface.")
1bbd0b84 1197#define FUNC_NAME s_scm_execle
6afcd3b2 1198{
7f03f970 1199 char **exec_argv;
6afcd3b2 1200 char **exec_env;
7f03f970 1201 char *exec_file;
6afcd3b2 1202
661ae7ab 1203 scm_dynwind_begin (0);
7f03f970
MV
1204
1205 exec_file = scm_to_locale_string (filename);
661ae7ab 1206 scm_dynwind_free (exec_file);
7f03f970
MV
1207
1208 exec_argv = scm_i_allocate_string_pointers (args);
7f03f970 1209 exec_env = scm_i_allocate_string_pointers (env);
7f03f970 1210
8ab3d8a0
KR
1211 execve (exec_file,
1212#ifdef __MINGW32__
1213 /* extra "const" in mingw formals, provokes warning from gcc */
1214 (const char * const *)
1215#endif
1216 exec_argv,
1217#ifdef __MINGW32__
1218 /* extra "const" in mingw formals, provokes warning from gcc */
1219 (const char * const *)
1220#endif
1221 exec_env);
1bbd0b84 1222 SCM_SYSERROR;
7f03f970 1223
6afcd3b2 1224 /* not reached. */
661ae7ab 1225 scm_dynwind_end ();
6afcd3b2
GH
1226 return SCM_BOOL_F;
1227}
1bbd0b84 1228#undef FUNC_NAME
6afcd3b2 1229
82893676 1230#ifdef HAVE_FORK
a1ec6916 1231SCM_DEFINE (scm_fork, "primitive-fork", 0, 0, 0,
1bbd0b84 1232 (),
b380b885
MD
1233 "Creates a new \"child\" process by duplicating the current \"parent\" process.\n"
1234 "In the child the return value is 0. In the parent the return value is\n"
1235 "the integer process ID of the child.\n\n"
1236 "This procedure has been renamed from @code{fork} to avoid a naming conflict\n"
1237 "with the scsh fork.")
1bbd0b84 1238#define FUNC_NAME s_scm_fork
0f2d19dd 1239{
bab0f4e5 1240 int pid;
a796d0a9
AW
1241 if (scm_ilength (scm_all_threads ()) != 1)
1242 /* Other threads may be holding on to resources that Guile needs --
1243 it is not safe to permit one thread to fork while others are
1244 running.
1245
1246 In addition, POSIX clearly specifies that if a multi-threaded
1247 program forks, the child must only call functions that are
1248 async-signal-safe. We can't guarantee that in general. The best
1249 we can do is to allow forking only very early, before any call to
1250 sigaction spawns the signal-handling thread. */
1251 scm_display
1252 (scm_from_latin1_string
1253 ("warning: call to primitive-fork while multiple threads are running;\n"
1254 " further behavior unspecified. See \"Processes\" in the\n"
1255 " manual, for more information.\n"),
1256 scm_current_warning_port ());
0f2d19dd
JB
1257 pid = fork ();
1258 if (pid == -1)
1bbd0b84 1259 SCM_SYSERROR;
e11e83f3 1260 return scm_from_int (pid);
0f2d19dd 1261}
1bbd0b84 1262#undef FUNC_NAME
a2e946f1
AW
1263
1264/* Since Guile uses threads, we have to be very careful to avoid calling
1265 functions that are not async-signal-safe in the child. That's why
1266 this function is implemented in C. */
1267static SCM
1268scm_open_process (SCM mode, SCM prog, SCM args)
1269#define FUNC_NAME "open-process"
1270{
1271 long mode_bits;
1272 int reading, writing;
1273 int c2p[2]; /* Child to parent. */
1274 int p2c[2]; /* Parent to child. */
1275 int in = -1, out = -1, err = -1;
1276 int pid;
1277 char *exec_file;
1278 char **exec_argv;
1279 int max_fd = 1024;
1280
1281 exec_file = scm_to_locale_string (prog);
1282 exec_argv = scm_i_allocate_string_pointers (scm_cons (prog, args));
1283
1284 mode_bits = scm_i_mode_bits (mode);
1285 reading = mode_bits & SCM_RDNG;
1286 writing = mode_bits & SCM_WRTNG;
1287
1288 if (reading)
1289 {
1290 if (pipe (c2p))
1291 {
1292 int errno_save = errno;
1293 free (exec_file);
1294 errno = errno_save;
1295 SCM_SYSERROR;
1296 }
1297 out = c2p[1];
1298 }
1299
1300 if (writing)
1301 {
1302 if (pipe (p2c))
1303 {
1304 int errno_save = errno;
1305 free (exec_file);
1306 if (reading)
1307 {
1308 close (c2p[0]);
1309 close (c2p[1]);
1310 }
1311 errno = errno_save;
1312 SCM_SYSERROR;
1313 }
1314 in = p2c[0];
1315 }
1316
1317 {
1318 SCM port;
1319
1320 if (SCM_OPOUTFPORTP ((port = scm_current_error_port ())))
1321 err = SCM_FPORT_FDES (port);
1322 if (out == -1 && SCM_OPOUTFPORTP ((port = scm_current_output_port ())))
1323 out = SCM_FPORT_FDES (port);
1324 if (in == -1 && SCM_OPINFPORTP ((port = scm_current_input_port ())))
1325 in = SCM_FPORT_FDES (port);
1326 }
1327
1328#if defined (HAVE_GETRLIMIT) && defined (RLIMIT_NOFILE)
1329 {
1330 struct rlimit lim = { 0, 0 };
1331 if (getrlimit (RLIMIT_NOFILE, &lim) == 0)
1332 max_fd = lim.rlim_cur;
1333 }
1334#endif
1335
1336 pid = fork ();
1337
1338 if (pid == -1)
1339 {
1340 int errno_save = errno;
1341 free (exec_file);
1342 if (reading)
1343 {
1344 close (c2p[0]);
1345 close (c2p[1]);
1346 }
1347 if (writing)
1348 {
1349 close (p2c[0]);
1350 close (p2c[1]);
1351 }
1352 errno = errno_save;
1353 SCM_SYSERROR;
1354 }
1355
1356 if (pid)
1357 /* Parent. */
1358 {
03a2f598 1359 SCM read_port = SCM_BOOL_F, write_port = SCM_BOOL_F;
a2e946f1
AW
1360
1361 /* There is no sense in catching errors on close(). */
1362 if (reading)
1363 {
1364 close (c2p[1]);
1365 read_port = scm_fdes_to_port (c2p[0], "r", sym_read_pipe);
1366 scm_setvbuf (read_port, scm_from_int (_IONBF), SCM_UNDEFINED);
1367 }
1368 if (writing)
1369 {
1370 close (p2c[0]);
1371 write_port = scm_fdes_to_port (p2c[1], "w", sym_write_pipe);
1372 scm_setvbuf (write_port, scm_from_int (_IONBF), SCM_UNDEFINED);
1373 }
1374
03a2f598
AW
1375 return scm_values
1376 (scm_list_3 (read_port, write_port, scm_from_int (pid)));
a2e946f1
AW
1377 }
1378
1379 /* The child. */
1380 if (reading)
1381 close (c2p[0]);
1382 if (writing)
1383 close (p2c[1]);
1384
1385 /* Close all file descriptors in ports inherited from the parent
1386 except for in, out, and err. Heavy-handed, but robust. */
1387 while (max_fd--)
1388 if (max_fd != in && max_fd != out && max_fd != err)
1389 close (max_fd);
1390
1391 /* Ignore errors on these open() calls. */
1392 if (in == -1)
1393 in = open ("/dev/null", O_RDONLY);
1394 if (out == -1)
1395 out = open ("/dev/null", O_WRONLY);
1396 if (err == -1)
1397 err = open ("/dev/null", O_WRONLY);
1398
1399 if (in > 0)
1400 {
1401 if (out == 0)
1402 do out = dup (out); while (errno == EINTR);
1403 if (err == 0)
1404 do err = dup (err); while (errno == EINTR);
1405 do dup2 (in, 0); while (errno == EINTR);
1406 close (in);
1407 }
1408 if (out > 1)
1409 {
1410 if (err == 1)
1411 do err = dup (err); while (errno == EINTR);
1412 do dup2 (out, 1); while (errno == EINTR);
1413 close (out);
1414 }
1415 if (err > 2)
1416 {
1417 do dup2 (err, 2); while (errno == EINTR);
1418 close (err);
1419 }
1420
1421 execvp (exec_file,
1422#ifdef __MINGW32__
1423 /* extra "const" in mingw formals, provokes warning from gcc */
1424 (const char * const *)
1425#endif
1426 exec_argv);
1427
1428 /* The exec failed! There is nothing sensible to do. */
1429 if (err > 0)
1430 {
1431 char *msg = strerror (errno);
1432 fprintf (fdopen (err, "a"), "In execlp of %s: %s\n",
1433 exec_file, msg);
1434 }
1435
1436 _exit (EXIT_FAILURE);
1437 /* Not reached. */
1438 return SCM_BOOL_F;
1439}
1440#undef FUNC_NAME
82893676 1441#endif /* HAVE_FORK */
0f2d19dd 1442
4f68365d
MV
1443#ifdef __MINGW32__
1444# include "win32-uname.h"
1445#endif
1446
1447#if defined (HAVE_UNAME) || defined (__MINGW32__)
a1ec6916 1448SCM_DEFINE (scm_uname, "uname", 0, 0, 0,
1bbd0b84 1449 (),
1e6808ea
MG
1450 "Return an object with some information about the computer\n"
1451 "system the program is running on.")
1bbd0b84 1452#define FUNC_NAME s_scm_uname
0f2d19dd 1453{
0f2d19dd 1454 struct utsname buf;
1d1559ce 1455 SCM result = scm_c_make_vector (5, SCM_UNSPECIFIED);
e1a191a8 1456 if (uname (&buf) < 0)
1bbd0b84 1457 SCM_SYSERROR;
4057a3e0
MV
1458 SCM_SIMPLE_VECTOR_SET(result, 0, scm_from_locale_string (buf.sysname));
1459 SCM_SIMPLE_VECTOR_SET(result, 1, scm_from_locale_string (buf.nodename));
1460 SCM_SIMPLE_VECTOR_SET(result, 2, scm_from_locale_string (buf.release));
1461 SCM_SIMPLE_VECTOR_SET(result, 3, scm_from_locale_string (buf.version));
1462 SCM_SIMPLE_VECTOR_SET(result, 4, scm_from_locale_string (buf.machine));
0f2d19dd 1463/*
02b754d3 1464 a linux special?
4057a3e0 1465 SCM_SIMPLE_VECTOR_SET(result, 5, scm_from_locale_string (buf.domainname));
0f2d19dd 1466*/
1d1559ce 1467 return result;
0f2d19dd 1468}
1bbd0b84 1469#undef FUNC_NAME
f25f761d 1470#endif /* HAVE_UNAME */
0f2d19dd 1471
a1ec6916 1472SCM_DEFINE (scm_environ, "environ", 0, 1, 0,
1bbd0b84 1473 (SCM env),
1e6808ea
MG
1474 "If @var{env} is omitted, return the current environment (in the\n"
1475 "Unix sense) as a list of strings. Otherwise set the current\n"
1476 "environment, which is also the default environment for child\n"
1477 "processes, to the supplied list of strings. Each member of\n"
1478 "@var{env} should be of the form @code{NAME=VALUE} and values of\n"
1479 "@code{NAME} should not be duplicated. If @var{env} is supplied\n"
1480 "then the return value is unspecified.")
1bbd0b84 1481#define FUNC_NAME s_scm_environ
0f2d19dd
JB
1482{
1483 if (SCM_UNBNDP (env))
1484 return scm_makfromstrs (-1, environ);
1485 else
1486 {
2a776823 1487 environ = scm_i_allocate_string_pointers (env);
0f2d19dd
JB
1488 return SCM_UNSPECIFIED;
1489 }
1490}
1bbd0b84 1491#undef FUNC_NAME
0f2d19dd 1492
9ee5fce4
MD
1493#ifdef L_tmpnam
1494
a1ec6916 1495SCM_DEFINE (scm_tmpnam, "tmpnam", 0, 0, 0,
1bbd0b84 1496 (),
1e6808ea
MG
1497 "Return a name in the file system that does not match any\n"
1498 "existing file. However there is no guarantee that another\n"
1499 "process will not create the file after @code{tmpnam} is called.\n"
1500 "Care should be taken if opening the file, e.g., use the\n"
1501 "@code{O_EXCL} open flag or use @code{mkstemp!} instead.")
1bbd0b84 1502#define FUNC_NAME s_scm_tmpnam
9ee5fce4
MD
1503{
1504 char name[L_tmpnam];
6d163216
GH
1505 char *rv;
1506
1507 SCM_SYSCALL (rv = tmpnam (name));
1508 if (rv == NULL)
1509 /* not SCM_SYSERROR since errno probably not set. */
1510 SCM_MISC_ERROR ("tmpnam failed", SCM_EOL);
cc95e00a 1511 return scm_from_locale_string (name);
9ee5fce4 1512}
0f981281 1513#undef FUNC_NAME
0f2d19dd 1514
1bbd0b84 1515#endif
1cc91f1b 1516
cd53bd36
TTN
1517SCM_DEFINE (scm_tmpfile, "tmpfile", 0, 0, 0,
1518 (void),
1519 "Return an input/output port to a unique temporary file\n"
1520 "named using the path prefix @code{P_tmpdir} defined in\n"
1521 "@file{stdio.h}.\n"
1522 "The file is automatically deleted when the port is closed\n"
1523 "or the program terminates.")
1524#define FUNC_NAME s_scm_tmpfile
1525{
1526 FILE *rv;
81bda963 1527 int fd;
cd53bd36
TTN
1528
1529 if (! (rv = tmpfile ()))
1530 SCM_SYSERROR;
81bda963
AW
1531
1532#ifndef __MINGW32__
1533 fd = dup (fileno (rv));
1534 fclose (rv);
1535#else
1536 fd = fileno (rv);
1537 /* FIXME: leaking the file, it will never be closed! */
1538#endif
1539
1540 return scm_fdes_to_port (fd, "w+", SCM_BOOL_F);
cd53bd36
TTN
1541}
1542#undef FUNC_NAME
1543
06bfe276
AW
1544SCM_DEFINE (scm_utime, "utime", 1, 5, 0,
1545 (SCM pathname, SCM actime, SCM modtime, SCM actimens, SCM modtimens,
1546 SCM flags),
1e6808ea 1547 "@code{utime} sets the access and modification times for the\n"
b7e64f8b 1548 "file named by @var{pathname}. If @var{actime} or @var{modtime} is\n"
1e6808ea
MG
1549 "not supplied, then the current time is used. @var{actime} and\n"
1550 "@var{modtime} must be integer time values as returned by the\n"
06bfe276
AW
1551 "@code{current-time} procedure.\n\n"
1552 "The optional @var{actimens} and @var{modtimens} are nanoseconds\n"
1553 "to add @var{actime} and @var{modtime}. Nanosecond precision is\n"
477e4219 1554 "only supported on some combinations of file systems and operating\n"
06bfe276 1555 "systems.\n"
1e6808ea 1556 "@lisp\n"
b380b885 1557 "(utime \"foo\" (- (current-time) 3600))\n"
1e6808ea
MG
1558 "@end lisp\n"
1559 "will set the access time to one hour in the past and the\n"
1560 "modification time to the current time.")
1bbd0b84 1561#define FUNC_NAME s_scm_utime
0f2d19dd
JB
1562{
1563 int rv;
06bfe276
AW
1564 time_t atim_sec, mtim_sec;
1565 long atim_nsec, mtim_nsec;
1566 int f;
1567
0f2d19dd 1568 if (SCM_UNBNDP (actime))
06bfe276 1569 {
adfb4284 1570#ifdef HAVE_UTIMENSAT
06bfe276
AW
1571 atim_sec = 0;
1572 atim_nsec = UTIME_NOW;
1573#else
1574 SCM_SYSCALL (time (&atim_sec));
1575 atim_nsec = 0;
1576#endif
1577 }
0f2d19dd 1578 else
06bfe276
AW
1579 {
1580 atim_sec = SCM_NUM2ULONG (2, actime);
1581 if (SCM_UNBNDP (actimens))
1582 atim_nsec = 0;
1583 else
1584 atim_nsec = SCM_NUM2LONG (4, actimens);
1585 }
1586
0f2d19dd 1587 if (SCM_UNBNDP (modtime))
06bfe276 1588 {
adfb4284 1589#ifdef HAVE_UTIMENSAT
06bfe276
AW
1590 mtim_sec = 0;
1591 mtim_nsec = UTIME_NOW;
1592#else
1593 SCM_SYSCALL (time (&mtim_sec));
1594 mtim_nsec = 0;
1595#endif
1596 }
0f2d19dd 1597 else
06bfe276
AW
1598 {
1599 mtim_sec = SCM_NUM2ULONG (3, modtime);
1600 if (SCM_UNBNDP (modtimens))
1601 mtim_nsec = 0;
1602 else
1603 mtim_nsec = SCM_NUM2LONG (5, modtimens);
1604 }
1605
1606 if (SCM_UNBNDP (flags))
1607 f = 0;
1608 else
1609 f = SCM_NUM2INT (6, flags);
1610
adfb4284 1611#ifdef HAVE_UTIMENSAT
06bfe276
AW
1612 {
1613 struct timespec times[2];
1614 times[0].tv_sec = atim_sec;
1615 times[0].tv_nsec = atim_nsec;
1616 times[1].tv_sec = mtim_sec;
1617 times[1].tv_nsec = mtim_nsec;
1618
1619 STRING_SYSCALL (pathname, c_pathname,
adfb4284 1620 rv = utimensat (AT_FDCWD, c_pathname, times, f));
06bfe276
AW
1621 }
1622#else
1623 {
1624 struct utimbuf utm;
1625 utm.actime = atim_sec;
1626 utm.modtime = mtim_sec;
1627
1628 STRING_SYSCALL (pathname, c_pathname,
1629 rv = utime (c_pathname, &utm));
1630 }
1631#endif
0f2d19dd 1632
02b754d3 1633 if (rv != 0)
1bbd0b84 1634 SCM_SYSERROR;
02b754d3 1635 return SCM_UNSPECIFIED;
0f2d19dd 1636}
1bbd0b84 1637#undef FUNC_NAME
0f2d19dd 1638
a1ec6916 1639SCM_DEFINE (scm_getpid, "getpid", 0, 0, 0,
1bbd0b84 1640 (),
1e6808ea 1641 "Return an integer representing the current process ID.")
1bbd0b84 1642#define FUNC_NAME s_scm_getpid
0f2d19dd 1643{
e11e83f3 1644 return scm_from_ulong (getpid ());
0f2d19dd 1645}
1bbd0b84 1646#undef FUNC_NAME
0f2d19dd 1647
a1ec6916 1648SCM_DEFINE (scm_putenv, "putenv", 1, 0, 0,
1bbd0b84 1649 (SCM str),
b7e64f8b
BT
1650 "Modifies the environment of the current process, which is also\n"
1651 "the default environment inherited by child processes. If\n"
1652 "@var{str} is of the form @code{NAME=VALUE} then it will be\n"
1653 "written directly into the environment, replacing any existing\n"
1654 "environment string with name matching @code{NAME}. If\n"
1655 "@var{str} does not contain an equal sign, then any existing\n"
1656 "string with name matching @var{str} will be removed.\n"
1657 "\n"
b380b885 1658 "The return value is unspecified.")
1bbd0b84 1659#define FUNC_NAME s_scm_putenv
0f2d19dd 1660{
f158788f 1661 int rv;
f015614a 1662 char *c_str = scm_to_locale_string (str);
002409fe 1663
3731192f 1664 /* Leave C_STR in the environment. */
fcc5d734 1665
3731192f
LC
1666 /* Gnulib's `putenv' module honors the semantics described above. */
1667 rv = putenv (c_str);
1668 if (rv < 0)
1669 SCM_SYSERROR;
f015614a 1670
f93ddd39 1671 return SCM_UNSPECIFIED;
0f2d19dd 1672}
1bbd0b84 1673#undef FUNC_NAME
0f2d19dd 1674
b89c4943 1675/* This mutex is used to serialize invocations of `setlocale ()' on non-GNU
a2f00b9b
LC
1676 systems (i.e., systems where a reentrant locale API is not available). It
1677 is also acquired before calls to `nl_langinfo ()'. See `i18n.c' for
1678 details. */
1679scm_i_pthread_mutex_t scm_i_locale_mutex = SCM_I_PTHREAD_MUTEX_INITIALIZER;
b89c4943 1680
f25f761d 1681#ifdef HAVE_SETLOCALE
b89c4943 1682
a1ec6916 1683SCM_DEFINE (scm_setlocale, "setlocale", 1, 1, 0,
1bbd0b84 1684 (SCM category, SCM locale),
1e6808ea
MG
1685 "If @var{locale} is omitted, return the current value of the\n"
1686 "specified locale category as a system-dependent string.\n"
1687 "@var{category} should be specified using the values\n"
1688 "@code{LC_COLLATE}, @code{LC_ALL} etc.\n"
1689 "\n"
1690 "Otherwise the specified locale category is set to the string\n"
1691 "@var{locale} and the new value is returned as a\n"
1692 "system-dependent string. If @var{locale} is an empty string,\n"
889975e5
MG
1693 "the locale will be set using environment variables.\n"
1694 "\n"
1695 "When the locale is changed, the character encoding of the new\n"
1696 "locale (UTF-8, ISO-8859-1, etc.) is used for the current\n"
1697 "input, output, and error ports\n")
1bbd0b84 1698#define FUNC_NAME s_scm_setlocale
0f2d19dd 1699{
a2f00b9b 1700 int c_category;
0f2d19dd
JB
1701 char *clocale;
1702 char *rv;
889975e5 1703 const char *enc;
0f2d19dd 1704
661ae7ab 1705 scm_dynwind_begin (0);
f015614a 1706
0f2d19dd
JB
1707 if (SCM_UNBNDP (locale))
1708 {
1709 clocale = NULL;
1710 }
1711 else
1712 {
f015614a 1713 clocale = scm_to_locale_string (locale);
661ae7ab 1714 scm_dynwind_free (clocale);
0f2d19dd
JB
1715 }
1716
a2f00b9b
LC
1717 c_category = scm_i_to_lc_category (category, 1);
1718
b89c4943 1719 scm_i_pthread_mutex_lock (&scm_i_locale_mutex);
a2f00b9b 1720 rv = setlocale (c_category, clocale);
b89c4943 1721 scm_i_pthread_mutex_unlock (&scm_i_locale_mutex);
b89c4943 1722
02b754d3 1723 if (rv == NULL)
41b74b7d
KR
1724 {
1725 /* POSIX and C99 don't say anything about setlocale setting errno, so
1726 force a sensible value here. glibc leaves ENOENT, which would be
1727 fine, but it's not a documented feature. */
1728 errno = EINVAL;
1729 SCM_SYSERROR;
1730 }
f015614a 1731
889975e5 1732 enc = locale_charset ();
9d9c66ba 1733
889975e5 1734 /* Set the default encoding for new ports. */
9d9c66ba
LC
1735 scm_i_set_default_port_encoding (enc);
1736
889975e5
MG
1737 /* Set the encoding for the stdio ports. */
1738 scm_i_set_port_encoding_x (scm_current_input_port (), enc);
1739 scm_i_set_port_encoding_x (scm_current_output_port (), enc);
1740 scm_i_set_port_encoding_x (scm_current_error_port (), enc);
a17d2654 1741
661ae7ab 1742 scm_dynwind_end ();
f015614a 1743 return scm_from_locale_string (rv);
0f2d19dd 1744}
1bbd0b84 1745#undef FUNC_NAME
f25f761d 1746#endif /* HAVE_SETLOCALE */
0f2d19dd 1747
f25f761d 1748#ifdef HAVE_MKNOD
a1ec6916 1749SCM_DEFINE (scm_mknod, "mknod", 4, 0, 0,
1bbd0b84 1750 (SCM path, SCM type, SCM perms, SCM dev),
b380b885
MD
1751 "Creates a new special file, such as a file corresponding to a device.\n"
1752 "@var{path} specifies the name of the file. @var{type} should\n"
1753 "be one of the following symbols:\n"
1754 "regular, directory, symlink, block-special, char-special,\n"
1755 "fifo, or socket. @var{perms} (an integer) specifies the file permissions.\n"
1756 "@var{dev} (an integer) specifies which device the special file refers\n"
1757 "to. Its exact interpretation depends on the kind of special file\n"
1758 "being created.\n\n"
1759 "E.g.,\n"
1e6808ea 1760 "@lisp\n"
09831f94 1761 "(mknod \"/dev/fd0\" 'block-special #o660 (+ (* 2 256) 2))\n"
1e6808ea 1762 "@end lisp\n\n"
a3c8b9fc 1763 "The return value is unspecified.")
1bbd0b84 1764#define FUNC_NAME s_scm_mknod
0f2d19dd 1765{
0f2d19dd 1766 int val;
cc95e00a 1767 const char *p;
82a76bdf 1768 int ctype = 0;
19468eff 1769
a6d9e5ab 1770 SCM_VALIDATE_STRING (1, path);
34d19ef6 1771 SCM_VALIDATE_SYMBOL (2, type);
19468eff 1772
cc95e00a 1773 p = scm_i_symbol_chars (type);
19468eff
GH
1774 if (strcmp (p, "regular") == 0)
1775 ctype = S_IFREG;
1776 else if (strcmp (p, "directory") == 0)
1777 ctype = S_IFDIR;
23f2b9a3
KR
1778#ifdef S_IFLNK
1779 /* systems without symlinks probably don't have S_IFLNK defined */
19468eff
GH
1780 else if (strcmp (p, "symlink") == 0)
1781 ctype = S_IFLNK;
23f2b9a3 1782#endif
19468eff
GH
1783 else if (strcmp (p, "block-special") == 0)
1784 ctype = S_IFBLK;
1785 else if (strcmp (p, "char-special") == 0)
1786 ctype = S_IFCHR;
1787 else if (strcmp (p, "fifo") == 0)
1788 ctype = S_IFIFO;
e655d034 1789#ifdef S_IFSOCK
19468eff
GH
1790 else if (strcmp (p, "socket") == 0)
1791 ctype = S_IFSOCK;
e655d034 1792#endif
19468eff 1793 else
34d19ef6 1794 SCM_OUT_OF_RANGE (2, type);
19468eff 1795
f015614a
MV
1796 STRING_SYSCALL (path, c_path,
1797 val = mknod (c_path,
1798 ctype | scm_to_int (perms),
1799 scm_to_int (dev)));
02b754d3 1800 if (val != 0)
1bbd0b84 1801 SCM_SYSERROR;
02b754d3 1802 return SCM_UNSPECIFIED;
0f2d19dd 1803}
1bbd0b84 1804#undef FUNC_NAME
f25f761d 1805#endif /* HAVE_MKNOD */
0f2d19dd 1806
f25f761d 1807#ifdef HAVE_NICE
a1ec6916 1808SCM_DEFINE (scm_nice, "nice", 1, 0, 0,
1bbd0b84 1809 (SCM incr),
b380b885
MD
1810 "Increment the priority of the current process by @var{incr}. A higher\n"
1811 "priority value means that the process runs less often.\n"
1812 "The return value is unspecified.")
1bbd0b84 1813#define FUNC_NAME s_scm_nice
0f2d19dd 1814{
f1c82f55
KR
1815 /* nice() returns "prio-NZERO" on success or -1 on error, but -1 can arise
1816 from "prio-NZERO", so an error must be detected from errno changed */
1817 errno = 0;
03976fee 1818 nice (scm_to_int (incr));
f1c82f55 1819 if (errno != 0)
1bbd0b84 1820 SCM_SYSERROR;
634aa8de 1821
02b754d3 1822 return SCM_UNSPECIFIED;
0f2d19dd 1823}
1bbd0b84 1824#undef FUNC_NAME
f25f761d 1825#endif /* HAVE_NICE */
0f2d19dd 1826
f25f761d 1827#ifdef HAVE_SYNC
a1ec6916 1828SCM_DEFINE (scm_sync, "sync", 0, 0, 0,
1bbd0b84 1829 (),
b380b885
MD
1830 "Flush the operating system disk buffers.\n"
1831 "The return value is unspecified.")
1bbd0b84 1832#define FUNC_NAME s_scm_sync
0f2d19dd 1833{
0f2d19dd 1834 sync();
127ec750 1835 return SCM_UNSPECIFIED;
0f2d19dd 1836}
1bbd0b84 1837#undef FUNC_NAME
f25f761d 1838#endif /* HAVE_SYNC */
0f2d19dd 1839
33bea692
KR
1840
1841/* crypt() returns a pointer to a static buffer, so we use scm_i_misc_mutex
1842 to avoid another thread overwriting it. A test program running crypt
1843 continuously in two threads can be quickly seen tripping this problem.
1844 crypt() is pretty slow normally, so a mutex shouldn't add much overhead.
1845
1846 glibc has a thread-safe crypt_r, but (in version 2.3.2) it runs a lot
1847 slower (about 5x) than plain crypt if you pass an uninitialized data
1848 block each time. Presumably there's some one-time setups. The best way
1849 to use crypt_r for parallel execution in multiple threads would probably
1850 be to maintain a little pool of initialized crypt_data structures, take
1851 one and use it, then return it to the pool. That pool could be garbage
1852 collected so it didn't add permanently to memory use if only a few crypt
1853 calls are made. But we expect crypt will be used rarely, and even more
1854 rarely will there be any desire for lots of parallel execution on
1855 multiple cpus. So for now we don't bother with anything fancy, just
1856 ensure it works. */
1857
534bbcc1 1858#ifdef HAVE_CRYPT
33bea692 1859SCM_DEFINE (scm_crypt, "crypt", 2, 0, 0,
94e6d793
MG
1860 (SCM key, SCM salt),
1861 "Encrypt @var{key} using @var{salt} as the salt value to the\n"
9401323e 1862 "crypt(3) library call.")
94e6d793
MG
1863#define FUNC_NAME s_scm_crypt
1864{
33bea692 1865 SCM ret;
23d72566 1866 char *c_key, *c_salt, *c_ret;
94e6d793 1867
661ae7ab
MV
1868 scm_dynwind_begin (0);
1869 scm_i_dynwind_pthread_mutex_lock (&scm_i_misc_mutex);
33bea692 1870
f015614a 1871 c_key = scm_to_locale_string (key);
661ae7ab 1872 scm_dynwind_free (c_key);
f015614a 1873 c_salt = scm_to_locale_string (salt);
661ae7ab 1874 scm_dynwind_free (c_salt);
f015614a 1875
23d72566
KR
1876 /* The Linux crypt(3) man page says crypt will return NULL and set errno
1877 on error. (Eg. ENOSYS if legal restrictions mean it cannot be
1878 implemented). */
1879 c_ret = crypt (c_key, c_salt);
1880 if (c_ret == NULL)
1881 SCM_SYSERROR;
33bea692 1882
23d72566 1883 ret = scm_from_locale_string (c_ret);
661ae7ab 1884 scm_dynwind_end ();
33bea692 1885 return ret;
94e6d793
MG
1886}
1887#undef FUNC_NAME
b9a7b725 1888#endif /* HAVE_CRYPT */
94e6d793
MG
1889
1890#if HAVE_CHROOT
1891SCM_DEFINE (scm_chroot, "chroot", 1, 0, 0,
1892 (SCM path),
1893 "Change the root directory to that specified in @var{path}.\n"
1894 "This directory will be used for path names beginning with\n"
1895 "@file{/}. The root directory is inherited by all children\n"
1896 "of the current process. Only the superuser may change the\n"
1897 "root directory.")
1898#define FUNC_NAME s_scm_chroot
1899{
f015614a 1900 int rv;
94e6d793 1901
f015614a
MV
1902 WITH_STRING (path, c_path,
1903 rv = chroot (c_path));
1904 if (rv == -1)
94e6d793
MG
1905 SCM_SYSERROR;
1906 return SCM_UNSPECIFIED;
1907}
1908#undef FUNC_NAME
1909#endif /* HAVE_CHROOT */
1910
7beabedb 1911
d3c88f18 1912#if defined (HAVE_GETLOGIN)
94e6d793
MG
1913SCM_DEFINE (scm_getlogin, "getlogin", 0, 0, 0,
1914 (void),
1915 "Return a string containing the name of the user logged in on\n"
1916 "the controlling terminal of the process, or @code{#f} if this\n"
1917 "information cannot be obtained.")
1918#define FUNC_NAME s_scm_getlogin
1919{
1920 char * p;
1921
1922 p = getlogin ();
1923 if (!p || !*p)
1924 return SCM_BOOL_F;
cc95e00a 1925 return scm_from_locale_string (p);
94e6d793
MG
1926}
1927#undef FUNC_NAME
1928#endif /* HAVE_GETLOGIN */
1929
94e6d793
MG
1930#if HAVE_GETPRIORITY
1931SCM_DEFINE (scm_getpriority, "getpriority", 2, 0, 0,
1932 (SCM which, SCM who),
1933 "Return the scheduling priority of the process, process group\n"
1934 "or user, as indicated by @var{which} and @var{who}. @var{which}\n"
1935 "is one of the variables @code{PRIO_PROCESS}, @code{PRIO_PGRP}\n"
1936 "or @code{PRIO_USER}, and @var{who} is interpreted relative to\n"
1937 "@var{which} (a process identifier for @code{PRIO_PROCESS},\n"
1938 "process group identifier for @code{PRIO_PGRP}, and a user\n"
1939 "identifier for @code{PRIO_USER}. A zero value of @var{who}\n"
1940 "denotes the current process, process group, or user. Return\n"
1941 "the highest priority (lowest numerical value) of any of the\n"
1942 "specified processes.")
1943#define FUNC_NAME s_scm_getpriority
1944{
1945 int cwhich, cwho, ret;
1946
a55c2b68
MV
1947 cwhich = scm_to_int (which);
1948 cwho = scm_to_int (who);
94e6d793
MG
1949
1950 /* We have to clear errno and examine it later, because -1 is a
1951 legal return value for getpriority(). */
1952 errno = 0;
1953 ret = getpriority (cwhich, cwho);
1954 if (errno != 0)
1955 SCM_SYSERROR;
a55c2b68 1956 return scm_from_int (ret);
94e6d793
MG
1957}
1958#undef FUNC_NAME
1959#endif /* HAVE_GETPRIORITY */
1960
1961#if HAVE_SETPRIORITY
1962SCM_DEFINE (scm_setpriority, "setpriority", 3, 0, 0,
1963 (SCM which, SCM who, SCM prio),
1964 "Set the scheduling priority of the process, process group\n"
1965 "or user, as indicated by @var{which} and @var{who}. @var{which}\n"
1966 "is one of the variables @code{PRIO_PROCESS}, @code{PRIO_PGRP}\n"
1967 "or @code{PRIO_USER}, and @var{who} is interpreted relative to\n"
1968 "@var{which} (a process identifier for @code{PRIO_PROCESS},\n"
1969 "process group identifier for @code{PRIO_PGRP}, and a user\n"
1970 "identifier for @code{PRIO_USER}. A zero value of @var{who}\n"
1971 "denotes the current process, process group, or user.\n"
1972 "@var{prio} is a value in the range -20 and 20, the default\n"
1973 "priority is 0; lower priorities cause more favorable\n"
1974 "scheduling. Sets the priority of all of the specified\n"
1975 "processes. Only the super-user may lower priorities.\n"
1976 "The return value is not specified.")
1977#define FUNC_NAME s_scm_setpriority
1978{
1979 int cwhich, cwho, cprio;
1980
a55c2b68
MV
1981 cwhich = scm_to_int (which);
1982 cwho = scm_to_int (who);
1983 cprio = scm_to_int (prio);
94e6d793
MG
1984
1985 if (setpriority (cwhich, cwho, cprio) == -1)
1986 SCM_SYSERROR;
1987 return SCM_UNSPECIFIED;
1988}
1989#undef FUNC_NAME
1990#endif /* HAVE_SETPRIORITY */
1991
fe613fe2
LC
1992#ifdef HAVE_SCHED_GETAFFINITY
1993
1994static SCM
1995cpu_set_to_bitvector (const cpu_set_t *cs)
1996{
1997 SCM bv;
1998 size_t cpu;
1999
2000 bv = scm_c_make_bitvector (sizeof (*cs), SCM_BOOL_F);
2001
2002 for (cpu = 0; cpu < sizeof (*cs); cpu++)
2003 {
2004 if (CPU_ISSET (cpu, cs))
2005 /* XXX: This is inefficient but avoids code duplication. */
2006 scm_c_bitvector_set_x (bv, cpu, SCM_BOOL_T);
2007 }
2008
2009 return bv;
2010}
2011
2012SCM_DEFINE (scm_getaffinity, "getaffinity", 1, 0, 0,
2013 (SCM pid),
2014 "Return a bitvector representing the CPU affinity mask for\n"
2015 "process @var{pid}. Each CPU the process has affinity with\n"
2016 "has its corresponding bit set in the returned bitvector.\n"
2017 "The number of bits set is a good estimate of how many CPUs\n"
2018 "Guile can use without stepping on other processes' toes.\n\n"
3ae78cac
LC
2019 "Currently this procedure is only defined on GNU variants\n"
2020 "(@pxref{CPU Affinity, @code{sched_getaffinity},, libc, The\n"
2021 "GNU C Library Reference Manual}).\n")
fe613fe2
LC
2022#define FUNC_NAME s_scm_getaffinity
2023{
2024 int err;
2025 cpu_set_t cs;
2026
2027 CPU_ZERO (&cs);
2028 err = sched_getaffinity (scm_to_int (pid), sizeof (cs), &cs);
2029 if (err)
2030 SCM_SYSERROR;
2031
2032 return cpu_set_to_bitvector (&cs);
2033}
2034#undef FUNC_NAME
2035
2036#endif /* HAVE_SCHED_GETAFFINITY */
2037
2038#ifdef HAVE_SCHED_SETAFFINITY
2039
2040SCM_DEFINE (scm_setaffinity, "setaffinity", 2, 0, 0,
2041 (SCM pid, SCM mask),
2042 "Install the CPU affinity mask @var{mask}, a bitvector, for\n"
2043 "the process or thread with ID @var{pid}. The return value\n"
2044 "is unspecified.\n\n"
3ae78cac
LC
2045 "Currently this procedure is only defined on GNU variants\n"
2046 "(@pxref{CPU Affinity, @code{sched_setaffinity},, libc, The\n"
2047 "GNU C Library Reference Manual}).\n")
fe613fe2
LC
2048#define FUNC_NAME s_scm_setaffinity
2049{
2050 cpu_set_t cs;
2051 scm_t_array_handle handle;
2052 const scm_t_uint32 *c_mask;
2053 size_t len, off, cpu;
2054 ssize_t inc;
2055 int err;
2056
2057 c_mask = scm_bitvector_elements (mask, &handle, &off, &len, &inc);
2058
2059 CPU_ZERO (&cs);
2060 for (cpu = 0; cpu < len; cpu++)
2061 {
2062 size_t idx;
2063
2064 idx = cpu * inc + off;
2065 if (c_mask[idx / 32] & (1UL << (idx % 32)))
2066 CPU_SET (cpu, &cs);
2067 }
2068
2069 err = sched_setaffinity (scm_to_int (pid), sizeof (cs), &cs);
2070 if (err)
2071 SCM_SYSERROR;
2072
2073 return SCM_UNSPECIFIED;
2074}
2075#undef FUNC_NAME
2076
2077#endif /* HAVE_SCHED_SETAFFINITY */
2078
f0c0141f 2079\f
94e6d793
MG
2080#if HAVE_GETPASS
2081SCM_DEFINE (scm_getpass, "getpass", 1, 0, 0,
2082 (SCM prompt),
2083 "Display @var{prompt} to the standard error output and read\n"
2084 "a password from @file{/dev/tty}. If this file is not\n"
2085 "accessible, it reads from standard input. The password may be\n"
2086 "up to 127 characters in length. Additional characters and the\n"
2087 "terminating newline character are discarded. While reading\n"
2088 "the password, echoing and the generation of signals by special\n"
2089 "characters is disabled.")
2090#define FUNC_NAME s_scm_getpass
2091{
2092 char * p;
2093 SCM passwd;
2094
2095 SCM_VALIDATE_STRING (1, prompt);
94e6d793 2096
f015614a
MV
2097 WITH_STRING (prompt, c_prompt,
2098 p = getpass(c_prompt));
2099 passwd = scm_from_locale_string (p);
94e6d793
MG
2100
2101 /* Clear out the password in the static buffer. */
2102 memset (p, 0, strlen (p));
2103
2104 return passwd;
2105}
2106#undef FUNC_NAME
2107#endif /* HAVE_GETPASS */
2108
94e6d793
MG
2109SCM_DEFINE (scm_flock, "flock", 2, 0, 0,
2110 (SCM file, SCM operation),
2111 "Apply or remove an advisory lock on an open file.\n"
2112 "@var{operation} specifies the action to be done:\n"
0b91f1db
KR
2113 "\n"
2114 "@defvar LOCK_SH\n"
94e6d793
MG
2115 "Shared lock. More than one process may hold a shared lock\n"
2116 "for a given file at a given time.\n"
0b91f1db
KR
2117 "@end defvar\n"
2118 "@defvar LOCK_EX\n"
94e6d793
MG
2119 "Exclusive lock. Only one process may hold an exclusive lock\n"
2120 "for a given file at a given time.\n"
0b91f1db
KR
2121 "@end defvar\n"
2122 "@defvar LOCK_UN\n"
94e6d793 2123 "Unlock the file.\n"
0b91f1db
KR
2124 "@end defvar\n"
2125 "@defvar LOCK_NB\n"
2126 "Don't block when locking. This is combined with one of the\n"
2127 "other operations using @code{logior}. If @code{flock} would\n"
2128 "block an @code{EWOULDBLOCK} error is thrown.\n"
2129 "@end defvar\n"
2130 "\n"
94e6d793 2131 "The return value is not specified. @var{file} may be an open\n"
0b91f1db
KR
2132 "file descriptor or an open file descriptor port.\n"
2133 "\n"
2134 "Note that @code{flock} does not lock files across NFS.")
94e6d793
MG
2135#define FUNC_NAME s_scm_flock
2136{
a55c2b68 2137 int fdes;
94e6d793 2138
a55c2b68
MV
2139 if (scm_is_integer (file))
2140 fdes = scm_to_int (file);
94e6d793
MG
2141 else
2142 {
2143 SCM_VALIDATE_OPFPORT (2, file);
2144
2145 fdes = SCM_FPORT_FDES (file);
2146 }
a55c2b68 2147 if (flock (fdes, scm_to_int (operation)) == -1)
94e6d793
MG
2148 SCM_SYSERROR;
2149 return SCM_UNSPECIFIED;
2150}
2151#undef FUNC_NAME
94e6d793
MG
2152
2153#if HAVE_SETHOSTNAME
2154SCM_DEFINE (scm_sethostname, "sethostname", 1, 0, 0,
2155 (SCM name),
2156 "Set the host name of the current processor to @var{name}. May\n"
2157 "only be used by the superuser. The return value is not\n"
2158 "specified.")
2159#define FUNC_NAME s_scm_sethostname
2160{
f015614a 2161 int rv;
94e6d793 2162
f015614a
MV
2163 WITH_STRING (name, c_name,
2164 rv = sethostname (c_name, strlen(c_name)));
2165 if (rv == -1)
94e6d793
MG
2166 SCM_SYSERROR;
2167 return SCM_UNSPECIFIED;
2168}
2169#undef FUNC_NAME
2170#endif /* HAVE_SETHOSTNAME */
2171
b28f5b3c 2172
94e6d793
MG
2173#if HAVE_GETHOSTNAME
2174SCM_DEFINE (scm_gethostname, "gethostname", 0, 0, 0,
2175 (void),
2176 "Return the host name of the current processor.")
2177#define FUNC_NAME s_scm_gethostname
2178{
b28f5b3c
DH
2179#ifdef MAXHOSTNAMELEN
2180
2181 /* Various systems define MAXHOSTNAMELEN (including Solaris in fact).
2182 * On GNU/Linux this doesn't include the terminating '\0', hence "+ 1". */
2183 const int len = MAXHOSTNAMELEN + 1;
2184 char *const p = scm_malloc (len);
2185 const int res = gethostname (p, len);
2186
661ae7ab
MV
2187 scm_dynwind_begin (0);
2188 scm_dynwind_unwind_handler (free, p, 0);
b28f5b3c
DH
2189
2190#else
94e6d793 2191
0eaf1055 2192 /* Default 256 is for Solaris, under Linux ENAMETOOLONG is returned if not
b28f5b3c
DH
2193 * large enough. SUSv2 specifies 255 maximum too, apparently. */
2194 int len = 256;
2195 int res;
2196 char *p;
0eaf1055 2197
b28f5b3c 2198# if HAVE_SYSCONF && defined (_SC_HOST_NAME_MAX)
0eaf1055
KR
2199
2200 /* POSIX specifies the HOST_NAME_MAX system parameter for the max size,
b28f5b3c
DH
2201 * which may reflect a particular kernel configuration.
2202 * Must watch out for this existing but giving -1, as happens for instance
2203 * in gnu/linux glibc 2.3.2. */
0eaf1055 2204 {
b28f5b3c 2205 const long int n = sysconf (_SC_HOST_NAME_MAX);
0eaf1055
KR
2206 if (n != -1L)
2207 len = n;
2208 }
b28f5b3c
DH
2209
2210# endif
2211
2212 p = scm_malloc (len);
2213
661ae7ab
MV
2214 scm_dynwind_begin (0);
2215 scm_dynwind_unwind_handler (free, p, 0);
0eaf1055 2216
94e6d793
MG
2217 res = gethostname (p, len);
2218 while (res == -1 && errno == ENAMETOOLONG)
2219 {
94e6d793 2220 len *= 2;
b28f5b3c
DH
2221
2222 /* scm_realloc may throw an exception. */
2223 p = scm_realloc (p, len);
94e6d793
MG
2224 res = gethostname (p, len);
2225 }
b28f5b3c
DH
2226
2227#endif
2228
94e6d793
MG
2229 if (res == -1)
2230 {
b28f5b3c
DH
2231 const int save_errno = errno;
2232
2b829bbb 2233 /* No guile exceptions can occur before we have freed p's memory. */
661ae7ab 2234 scm_dynwind_end ();
4c9419ac 2235 free (p);
b28f5b3c 2236
22865124 2237 errno = save_errno;
94e6d793
MG
2238 SCM_SYSERROR;
2239 }
b28f5b3c
DH
2240 else
2241 {
cc95e00a
MV
2242 /* scm_from_locale_string may throw an exception. */
2243 const SCM name = scm_from_locale_string (p);
b28f5b3c 2244
2b829bbb 2245 /* No guile exceptions can occur before we have freed p's memory. */
661ae7ab 2246 scm_dynwind_end ();
b28f5b3c
DH
2247 free (p);
2248
2249 return name;
2250 }
94e6d793
MG
2251}
2252#undef FUNC_NAME
2253#endif /* HAVE_GETHOSTNAME */
2254
fe613fe2 2255\f
a2e946f1
AW
2256#ifdef HAVE_FORK
2257static void
2258scm_init_popen (void)
2259{
2260 scm_c_define_gsubr ("open-process", 2, 0, 1, scm_open_process);
2261}
2262#endif
2263
b89c4943 2264void
0f2d19dd 2265scm_init_posix ()
0f2d19dd
JB
2266{
2267 scm_add_feature ("posix");
2268#ifdef HAVE_GETEUID
2269 scm_add_feature ("EIDs");
2270#endif
2271#ifdef WAIT_ANY
e11e83f3 2272 scm_c_define ("WAIT_ANY", scm_from_int (WAIT_ANY));
0f2d19dd
JB
2273#endif
2274#ifdef WAIT_MYPGRP
e11e83f3 2275 scm_c_define ("WAIT_MYPGRP", scm_from_int (WAIT_MYPGRP));
0f2d19dd
JB
2276#endif
2277#ifdef WNOHANG
e11e83f3 2278 scm_c_define ("WNOHANG", scm_from_int (WNOHANG));
0f2d19dd
JB
2279#endif
2280#ifdef WUNTRACED
e11e83f3 2281 scm_c_define ("WUNTRACED", scm_from_int (WUNTRACED));
0f2d19dd
JB
2282#endif
2283
0f2d19dd 2284#ifdef LC_COLLATE
e11e83f3 2285 scm_c_define ("LC_COLLATE", scm_from_int (LC_COLLATE));
0f2d19dd
JB
2286#endif
2287#ifdef LC_CTYPE
e11e83f3 2288 scm_c_define ("LC_CTYPE", scm_from_int (LC_CTYPE));
0f2d19dd
JB
2289#endif
2290#ifdef LC_MONETARY
e11e83f3 2291 scm_c_define ("LC_MONETARY", scm_from_int (LC_MONETARY));
0f2d19dd
JB
2292#endif
2293#ifdef LC_NUMERIC
e11e83f3 2294 scm_c_define ("LC_NUMERIC", scm_from_int (LC_NUMERIC));
0f2d19dd
JB
2295#endif
2296#ifdef LC_TIME
e11e83f3 2297 scm_c_define ("LC_TIME", scm_from_int (LC_TIME));
0f2d19dd
JB
2298#endif
2299#ifdef LC_MESSAGES
e11e83f3 2300 scm_c_define ("LC_MESSAGES", scm_from_int (LC_MESSAGES));
0f2d19dd
JB
2301#endif
2302#ifdef LC_ALL
e11e83f3 2303 scm_c_define ("LC_ALL", scm_from_int (LC_ALL));
0f2d19dd 2304#endif
9361f762
MV
2305#ifdef LC_PAPER
2306 scm_c_define ("LC_PAPER", scm_from_int (LC_PAPER));
2307#endif
2308#ifdef LC_NAME
2309 scm_c_define ("LC_NAME", scm_from_int (LC_NAME));
2310#endif
2311#ifdef LC_ADDRESS
2312 scm_c_define ("LC_ADDRESS", scm_from_int (LC_ADDRESS));
2313#endif
2314#ifdef LC_TELEPHONE
2315 scm_c_define ("LC_TELEPHONE", scm_from_int (LC_TELEPHONE));
2316#endif
2317#ifdef LC_MEASUREMENT
2318 scm_c_define ("LC_MEASUREMENT", scm_from_int (LC_MEASUREMENT));
2319#endif
2320#ifdef LC_IDENTIFICATION
2321 scm_c_define ("LC_IDENTIFICATION", scm_from_int (LC_IDENTIFICATION));
2322#endif
bd9e24b3 2323#ifdef PIPE_BUF
b9bd8526 2324 scm_c_define ("PIPE_BUF", scm_from_long (PIPE_BUF));
bd9e24b3
GH
2325#endif
2326
94e6d793 2327#ifdef PRIO_PROCESS
e11e83f3 2328 scm_c_define ("PRIO_PROCESS", scm_from_int (PRIO_PROCESS));
94e6d793
MG
2329#endif
2330#ifdef PRIO_PGRP
e11e83f3 2331 scm_c_define ("PRIO_PGRP", scm_from_int (PRIO_PGRP));
94e6d793
MG
2332#endif
2333#ifdef PRIO_USER
e11e83f3 2334 scm_c_define ("PRIO_USER", scm_from_int (PRIO_USER));
94e6d793
MG
2335#endif
2336
2337#ifdef LOCK_SH
e11e83f3 2338 scm_c_define ("LOCK_SH", scm_from_int (LOCK_SH));
94e6d793
MG
2339#endif
2340#ifdef LOCK_EX
e11e83f3 2341 scm_c_define ("LOCK_EX", scm_from_int (LOCK_EX));
94e6d793
MG
2342#endif
2343#ifdef LOCK_UN
e11e83f3 2344 scm_c_define ("LOCK_UN", scm_from_int (LOCK_UN));
94e6d793
MG
2345#endif
2346#ifdef LOCK_NB
e11e83f3 2347 scm_c_define ("LOCK_NB", scm_from_int (LOCK_NB));
94e6d793
MG
2348#endif
2349
648da032 2350#include "libguile/cpp-SIG.c"
a0599745 2351#include "libguile/posix.x"
a2e946f1 2352
712ca51f 2353#ifdef HAVE_FORK
a2e946f1
AW
2354 scm_c_register_extension ("libguile-" SCM_EFFECTIVE_VERSION,
2355 "scm_init_popen",
2356 (scm_t_extension_init_func) scm_init_popen,
2357 NULL);
712ca51f 2358#endif /* HAVE_FORK */
0f2d19dd 2359}
89e00824
ML
2360
2361/*
2362 Local Variables:
2363 c-file-style: "gnu"
2364 End:
2365*/