~peter-pearse/ubuntu/natty/guile-1.8/prop001

« back to all changes in this revision

Viewing changes to libguile/posix.c

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Schepler
  • Date: 2006-11-09 03:11:16 UTC
  • Revision ID: james.westby@ubuntu.com-20061109031116-hu0q1jxqg12y6yeg
Tags: upstream-1.8.1+1
ImportĀ upstreamĀ versionĀ 1.8.1+1

Show diffs side-by-side

added added

removed removed

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