GNU Octave  3.8.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
syscalls.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 1996-2013 John W. Eaton
4 Copyright (C) 2010 VZLU Prague
5 
6 This file is part of Octave.
7 
8 Octave is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 3 of the License, or (at your
11 option) any later version.
12 
13 Octave is distributed in the hope that it will be useful, but WITHOUT
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 for more details.
17 
18 You should have received a copy of the GNU General Public License
19 along with Octave; see the file COPYING. If not, see
20 <http://www.gnu.org/licenses/>.
21 
22 */
23 
24 // Thomas Baier <[email protected]> added the original versions of
25 // the following functions:
26 //
27 // mkfifo unlink waitpid
28 
29 #ifdef HAVE_CONFIG_H
30 #include <config.h>
31 #endif
32 
33 #include <cstdio>
34 #include <cstring>
35 
36 #include <sys/types.h>
37 #include <unistd.h>
38 
39 #include <fcntl.h>
40 
41 #include "cmd-hist.h"
42 #include "file-ops.h"
43 #include "file-stat.h"
44 #include "oct-env.h"
45 #include "oct-syscalls.h"
46 #include "oct-uname.h"
47 
48 #include "defun.h"
49 #include "error.h"
50 #include "gripes.h"
51 #include "lo-utils.h"
52 #include "oct-hist.h"
53 #include "oct-map.h"
54 #include "oct-obj.h"
55 #include "oct-stdstrm.h"
56 #include "oct-stream.h"
57 #include "sysdep.h"
58 #include "utils.h"
59 #include "variables.h"
60 #include "input.h"
61 
62 static octave_scalar_map
64 {
66 
67  m.assign ("dev", static_cast<double> (fs.dev ()));
68  m.assign ("ino", fs.ino ());
69  m.assign ("mode", fs.mode ());
70  m.assign ("modestr", fs.mode_as_string ());
71  m.assign ("nlink", fs.nlink ());
72  m.assign ("uid", fs.uid ());
73  m.assign ("gid", fs.gid ());
74 #if defined (HAVE_STRUCT_STAT_ST_RDEV)
75  m.assign ("rdev", static_cast<double> (fs.rdev ()));
76 #endif
77  m.assign ("size", fs.size ());
78  m.assign ("atime", fs.atime ());
79  m.assign ("mtime", fs.mtime ());
80  m.assign ("ctime", fs.ctime ());
81 #if defined (HAVE_STRUCT_STAT_ST_BLKSIZE)
82  m.assign ("blksize", fs.blksize ());
83 #endif
84 #if defined (HAVE_STRUCT_STAT_ST_BLOCKS)
85  m.assign ("blocks", fs.blocks ());
86 #endif
87 
88  return m;
89 }
90 
91 static octave_value_list
93 {
94  octave_value_list retval;
95 
96  if (fs)
97  {
98  retval(2) = std::string ();
99  retval(1) = 0;
100  retval(0) = octave_value (mk_stat_map (fs));
101  }
102  else
103  {
104  retval(2) = fs.error ();
105  retval(1) = -1;
106  retval(0) = Matrix ();
107  }
108 
109  return retval;
110 }
111 
112 DEFUNX ("dup2", Fdup2, args, ,
113  "-*- texinfo -*-\n\
114 @deftypefn {Built-in Function} {[@var{fid}, @var{msg}] =} dup2 (@var{old}, @var{new})\n\
115 Duplicate a file descriptor.\n\
116 \n\
117 If successful, @var{fid} is greater than zero and contains the new file\n\
118 ID@. Otherwise, @var{fid} is negative and @var{msg} contains a\n\
119 system-dependent error message.\n\
120 @end deftypefn")
121 {
122  octave_value_list retval;
123 
124  retval(1) = std::string ();
125  retval(0) = -1;
126 
127  int nargin = args.length ();
128 
129  if (nargin == 2)
130  {
131  octave_stream old_stream
132  = octave_stream_list::lookup (args(0), "dup2");
133 
134  if (! error_state)
135  {
136  octave_stream new_stream
137  = octave_stream_list::lookup (args(1), "dup2");
138 
139  if (! error_state)
140  {
141  int i_old = old_stream.file_number ();
142  int i_new = new_stream.file_number ();
143 
144  if (i_old >= 0 && i_new >= 0)
145  {
146  std::string msg;
147 
148  int status = octave_syscalls::dup2 (i_old, i_new, msg);
149 
150  retval(1) = msg;
151  retval(0) = status;
152  }
153  }
154  }
155  else
156  error ("dup2: invalid stream");
157  }
158  else
159  print_usage ();
160 
161  return retval;
162 }
163 
164 DEFUNX ("exec", Fexec, args, ,
165  "-*- texinfo -*-\n\
166 @deftypefn {Built-in Function} {[@var{err}, @var{msg}] =} exec (@var{file}, @var{args})\n\
167 Replace current process with a new process. Calling @code{exec} without\n\
168 first calling @code{fork} will terminate your current Octave process and\n\
169 replace it with the program named by @var{file}. For example,\n\
170 \n\
171 @example\n\
172 exec (\"ls\" \"-l\")\n\
173 @end example\n\
174 \n\
175 @noindent\n\
176 will run @code{ls} and return you to your shell prompt.\n\
177 \n\
178 If successful, @code{exec} does not return. If @code{exec} does return,\n\
179 @var{err} will be nonzero, and @var{msg} will contain a system-dependent\n\
180 error message.\n\
181 @end deftypefn")
182 {
183  octave_value_list retval;
184 
185  retval(1) = std::string ();
186  retval(0) = -1;
187 
188  int nargin = args.length ();
189 
190  if (nargin == 1 || nargin == 2)
191  {
192  std::string exec_file = args(0).string_value ();
193 
194  if (! error_state)
195  {
196  string_vector exec_args;
197 
198  if (nargin == 2)
199  {
200  string_vector tmp = args(1).all_strings ();
201 
202  if (! error_state)
203  {
204  int len = tmp.length ();
205 
206  exec_args.resize (len + 1);
207 
208  exec_args[0] = exec_file;
209 
210  for (int i = 0; i < len; i++)
211  exec_args[i+1] = tmp[i];
212  }
213  else
214  error ("exec: arguments must be character strings");
215  }
216  else
217  {
218  exec_args.resize (1);
219 
220  exec_args[0] = exec_file;
221  }
222 
223  if (! error_state)
224  {
226 
229 
230  std::string msg;
231 
232  int status = octave_syscalls::execvp (exec_file, exec_args, msg);
233 
234  retval(1) = msg;
235  retval(0) = status;
236  }
237  }
238  else
239  error ("exec: FILE must be a string");
240  }
241  else
242  print_usage ();
243 
244  return retval;
245 }
246 
247 DEFUNX ("popen2", Fpopen2, args, ,
248  "-*- texinfo -*-\n\
249 @deftypefn {Built-in Function} {[@var{in}, @var{out}, @var{pid}] =} popen2 (@var{command}, @var{args})\n\
250 Start a subprocess with two-way communication. The name of the process\n\
251 is given by @var{command}, and @var{args} is an array of strings\n\
252 containing options for the command. The file identifiers for the input\n\
253 and output streams of the subprocess are returned in @var{in} and\n\
254 @var{out}. If execution of the command is successful, @var{pid}\n\
255 contains the process ID of the subprocess. Otherwise, @var{pid} is\n\
256 @minus{}1.\n\
257 \n\
258 For example:\n\
259 \n\
260 @example\n\
261 [in, out, pid] = popen2 (\"sort\", \"-r\");\n\
262 fputs (in, \"these\\nare\\nsome\\nstrings\\n\");\n\
263 fclose (in);\n\
264 EAGAIN = errno (\"EAGAIN\");\n\
265 done = false;\n\
266 do\n\
267  s = fgets (out);\n\
268  if (ischar (s))\n\
269  fputs (stdout, s);\n\
270  elseif (errno () == EAGAIN)\n\
271  sleep (0.1);\n\
272  fclear (out);\n\
273  else\n\
274  done = true;\n\
275  endif\n\
276 until (done)\n\
277 fclose (out);\n\
278 waitpid (pid);\n\
279 \n\
280  @print{} these\n\
281  @print{} strings\n\
282  @print{} some\n\
283  @print{} are\n\
284 @end example\n\
285 \n\
286 Note that @code{popen2}, unlike @code{popen}, will not @nospell{\"reap\"} the\n\
287 child process. If you don't use @code{waitpid} to check the child's\n\
288 exit status, it will linger until Octave exits.\n\
289 @seealso{popen, waitpid}\n\
290 @end deftypefn")
291 {
292  octave_value_list retval;
293 
294  retval(2) = -1;
295  retval(1) = Matrix ();
296  retval(0) = Matrix ();
297 
298  int nargin = args.length ();
299 
300  if (nargin >= 1 && nargin <= 3)
301  {
302  std::string exec_file = args(0).string_value ();
303 
304  if (! error_state)
305  {
306  string_vector arg_list;
307 
308  if (nargin >= 2)
309  {
310  string_vector tmp = args(1).all_strings ();
311 
312  if (! error_state)
313  {
314  int len = tmp.length ();
315 
316  arg_list.resize (len + 1);
317 
318  arg_list[0] = exec_file;
319 
320  for (int i = 0; i < len; i++)
321  arg_list[i+1] = tmp[i];
322  }
323  else
324  error ("popen2: arguments must be character strings");
325  }
326  else
327  {
328  arg_list.resize (1);
329 
330  arg_list[0] = exec_file;
331  }
332 
333  if (! error_state)
334  {
335  bool sync_mode = (nargin == 3 ? args(2).bool_value () : false);
336 
337  if (! error_state)
338  {
339  int fildes[2];
340  std::string msg;
341  pid_t pid;
342 
343  pid = octave_syscalls::popen2 (exec_file, arg_list, sync_mode,
344  fildes, msg, interactive);
345  if (pid >= 0)
346  {
347  FILE *ifile = fdopen (fildes[1], "r");
348  FILE *ofile = fdopen (fildes[0], "w");
349 
350  std::string nm;
351 
353  std::ios::in);
354 
356  std::ios::out);
357 
358  Cell file_ids (1, 2);
359 
360  retval(2) = pid;
361  retval(1) = octave_stream_list::insert (is);
362  retval(0) = octave_stream_list::insert (os);
363  }
364  else
365  error (msg.c_str ());
366  }
367  }
368  else
369  error ("popen2: arguments must be character strings");
370  }
371  else
372  error ("popen2: COMMAND argument must be a string");
373  }
374  else
375  print_usage ();
376 
377  return retval;
378 }
379 
380 /*
381 
382 %!test # UNIX-style test
383 %! if (isunix () || ismac ())
384 %! [in, out, pid] = popen2 ("sort", "-r");
385 %! EAGAIN = errno ("EAGAIN");
386 %! fputs (in, "these\nare\nsome\nstrings\n");
387 %! fclose (in);
388 %! done = false;
389 %! str = {};
390 %! idx = 0;
391 %! errs = 0;
392 %! do
393 %! if (ismac ()) # FIXME: Is this necessary?
394 %! errno (0);
395 %! endif
396 %! s = fgets (out);
397 %! if (ischar (s))
398 %! idx++;
399 %! str{idx} = s;
400 %! elseif (errno () == EAGAIN)
401 %! fclear (out);
402 %! sleep (0.1);
403 %! if (++errs == 100)
404 %! done = true;
405 %! endif
406 %! else
407 %! done = true;
408 %! endif
409 %! until (done)
410 %! fclose (out);
411 %! waitpid (pid);
412 %! assert (str, {"these\n","strings\n","some\n","are\n"});
413 %! endif
414 
415 %!test # Windows-style test
416 %! if (ispc () && ! isunix ())
417 %! [in, out, pid] = popen2 ('C:\Windows\system32\sort.exe', "/R");
418 %! EAGAIN = errno ("EINVAL");
419 %! fputs (in, "these\r\nare\r\nsome\r\nstrings\r\n");
420 %! fclose (in);
421 %! done = false;
422 %! str = {};
423 %! idx = 0;
424 %! errs = 0;
425 %! do
426 %! errno (0);
427 %! s = fgets (out);
428 %! if (ischar (s))
429 %! idx++;
430 %! str{idx} = s;
431 %! elseif (errno () == EAGAIN)
432 %! fclear (out);
433 %! sleep (0.1);
434 %! if (++errs == 100)
435 %! done = true;
436 %! endif
437 %! else
438 %! done = true;
439 %! endif
440 %! until (done)
441 %! fclose (out);
442 %! waitpid (pid);
443 %! assert (str, {"these\r\n","strings\r\n","some\r\n","are\r\n"});
444 %! endif
445 
446 */
447 
448 DEFUNX ("fcntl", Ffcntl, args, ,
449  "-*- texinfo -*-\n\
450 @deftypefn {Built-in Function} {[@var{err}, @var{msg}] =} fcntl (@var{fid}, @var{request}, @var{arg})\n\
451 Change the properties of the open file @var{fid}. The following values\n\
452 may be passed as @var{request}:\n\
453 \n\
454 @vtable @code\n\
455 @item F_DUPFD\n\
456 Return a duplicate file descriptor.\n\
457 \n\
458 @item F_GETFD\n\
459 Return the file descriptor flags for @var{fid}.\n\
460 \n\
461 @item F_SETFD\n\
462 Set the file descriptor flags for @var{fid}.\n\
463 \n\
464 @item F_GETFL\n\
465 Return the file status flags for @var{fid}. The following codes may be\n\
466 returned (some of the flags may be undefined on some systems).\n\
467 \n\
468 @vtable @code\n\
469 @item O_RDONLY\n\
470 Open for reading only.\n\
471 \n\
472 @item O_WRONLY\n\
473 Open for writing only.\n\
474 \n\
475 @item O_RDWR\n\
476 Open for reading and writing.\n\
477 \n\
478 @item O_APPEND\n\
479 Append on each write.\n\
480 \n\
481 @item O_CREAT\n\
482 Create the file if it does not exist.\n\
483 \n\
484 @item O_NONBLOCK\n\
485 Non-blocking mode.\n\
486 \n\
487 @item O_SYNC\n\
488 Wait for writes to complete.\n\
489 \n\
490 @item O_ASYNC\n\
491 Asynchronous I/O.\n\
492 @end vtable\n\
493 \n\
494 @item F_SETFL\n\
495 Set the file status flags for @var{fid} to the value specified by\n\
496 @var{arg}. The only flags that can be changed are @w{@code{O_APPEND}} and\n\
497 @w{@code{O_NONBLOCK}}.\n\
498 @end vtable\n\
499 \n\
500 If successful, @var{err} is 0 and @var{msg} is an empty string.\n\
501 Otherwise, @var{err} is nonzero and @var{msg} contains a\n\
502 system-dependent error message.\n\
503 @end deftypefn")
504 {
505  octave_value_list retval;
506 
507  retval(1) = std::string ();
508  retval(0) = -1;
509 
510  int nargin = args.length ();
511 
512  if (nargin == 3)
513  {
514  octave_stream strm = octave_stream_list::lookup (args (0), "fcntl");
515 
516  if (! error_state)
517  {
518  int fid = strm.file_number ();
519 
520  int req = args(1).int_value (true);
521  int arg = args(2).int_value (true);
522 
523  if (! error_state)
524  {
525  // FIXME: Need better checking here?
526  if (fid < 0)
527  error ("fcntl: invalid file id");
528  else
529  {
530  std::string msg;
531 
532  int status = octave_fcntl (fid, req, arg, msg);
533 
534  retval(1) = msg;
535  retval(0) = status;
536  }
537  }
538  }
539  else
540  error ("fcntl: FID, REQUEST, and ARG must be integers");
541  }
542  else
543  print_usage ();
544 
545  return retval;
546 }
547 
548 DEFUNX ("fork", Ffork, args, ,
549  "-*- texinfo -*-\n\
550 @deftypefn {Built-in Function} {[@var{pid}, @var{msg}] =} fork ()\n\
551 Create a copy of the current process.\n\
552 \n\
553 Fork can return one of the following values:\n\
554 \n\
555 @table @asis\n\
556 @item > 0\n\
557 You are in the parent process. The value returned from @code{fork} is\n\
558 the process id of the child process. You should probably arrange to\n\
559 wait for any child processes to exit.\n\
560 \n\
561 @item 0\n\
562 You are in the child process. You can call @code{exec} to start another\n\
563 process. If that fails, you should probably call @code{exit}.\n\
564 \n\
565 @item < 0\n\
566 The call to @code{fork} failed for some reason. You must take evasive\n\
567 action. A system dependent error message will be waiting in @var{msg}.\n\
568 @end table\n\
569 @end deftypefn")
570 {
571  octave_value_list retval;
572 
573  retval(1) = std::string ();
574  retval(0) = -1;
575 
576  int nargin = args.length ();
577 
578  if (nargin == 0)
579  {
580  std::string msg;
581 
582  pid_t pid = octave_syscalls::fork (msg);
583 
584  retval(1) = msg;
585  retval(0) = pid;
586  }
587  else
588  print_usage ();
589 
590  return retval;
591 }
592 
593 DEFUNX ("getpgrp", Fgetpgrp, args, ,
594  "-*- texinfo -*-\n\
595 @deftypefn {Built-in Function} {pgid =} getpgrp ()\n\
596 Return the process group id of the current process.\n\
597 @end deftypefn")
598 {
599  octave_value_list retval;
600 
601  retval(1) = std::string ();
602  retval(0) = -1;
603 
604  int nargin = args.length ();
605 
606  if (nargin == 0)
607  {
608  std::string msg;
609 
610  retval(1) = msg;
611  retval(0) = octave_syscalls::getpgrp (msg);
612  }
613  else
614  print_usage ();
615 
616  return retval;
617 }
618 
619 DEFUNX ("getpid", Fgetpid, args, ,
620  "-*- texinfo -*-\n\
621 @deftypefn {Built-in Function} {pid =} getpid ()\n\
622 Return the process id of the current process.\n\
623 @end deftypefn")
624 {
625  octave_value retval = -1;
626 
627  int nargin = args.length ();
628 
629  if (nargin == 0)
630  retval = octave_syscalls::getpid ();
631  else
632  print_usage ();
633 
634  return retval;
635 }
636 
637 DEFUNX ("getppid", Fgetppid, args, ,
638  "-*- texinfo -*-\n\
639 @deftypefn {Built-in Function} {pid =} getppid ()\n\
640 Return the process id of the parent process.\n\
641 @end deftypefn")
642 {
643  octave_value retval = -1;
644 
645  int nargin = args.length ();
646 
647  if (nargin == 0)
648  retval = octave_syscalls::getppid ();
649  else
650  print_usage ();
651 
652  return retval;
653 }
654 
655 DEFUNX ("getegid", Fgetegid, args, ,
656  "-*- texinfo -*-\n\
657 @deftypefn {Built-in Function} {egid =} getegid ()\n\
658 Return the effective group id of the current process.\n\
659 @end deftypefn")
660 {
661  octave_value retval = -1;
662 
663  int nargin = args.length ();
664 
665  if (nargin == 0)
666  retval = octave_syscalls::getegid ();
667  else
668  print_usage ();
669 
670  return retval;
671 }
672 
673 DEFUNX ("getgid", Fgetgid, args, ,
674  "-*- texinfo -*-\n\
675 @deftypefn {Built-in Function} {gid =} getgid ()\n\
676 Return the real group id of the current process.\n\
677 @end deftypefn")
678 {
679  octave_value retval = -1;
680 
681  int nargin = args.length ();
682 
683  if (nargin == 0)
684  retval = octave_syscalls::getgid ();
685  else
686  print_usage ();
687 
688  return retval;
689 }
690 
691 DEFUNX ("geteuid", Fgeteuid, args, ,
692  "-*- texinfo -*-\n\
693 @deftypefn {Built-in Function} {euid =} geteuid ()\n\
694 Return the effective user id of the current process.\n\
695 @end deftypefn")
696 {
697  octave_value retval = -1;
698 
699  int nargin = args.length ();
700 
701  if (nargin == 0)
702  retval = octave_syscalls::geteuid ();
703  else
704  print_usage ();
705 
706  return retval;
707 }
708 
709 DEFUNX ("getuid", Fgetuid, args, ,
710  "-*- texinfo -*-\n\
711 @deftypefn {Built-in Function} {uid =} getuid ()\n\
712 Return the real user id of the current process.\n\
713 @end deftypefn")
714 {
715  octave_value retval = -1;
716 
717  int nargin = args.length ();
718 
719  if (nargin == 0)
720  retval = octave_syscalls::getuid ();
721  else
722  print_usage ();
723 
724  return retval;
725 }
726 
727 DEFUNX ("kill", Fkill, args, ,
728  "-*- texinfo -*-\n\
729 @deftypefn {Built-in Function} {[@var{err}, @var{msg}] =} kill (@var{pid}, @var{sig})\n\
730 Send signal @var{sig} to process @var{pid}.\n\
731 \n\
732 If @var{pid} is positive, then signal @var{sig} is sent to @var{pid}.\n\
733 \n\
734 If @var{pid} is 0, then signal @var{sig} is sent to every process\n\
735 in the process group of the current process.\n\
736 \n\
737 If @var{pid} is -1, then signal @var{sig} is sent to every process\n\
738 except process 1.\n\
739 \n\
740 If @var{pid} is less than -1, then signal @var{sig} is sent to every\n\
741 process in the process group @var{-pid}.\n\
742 \n\
743 If @var{sig} is 0, then no signal is sent, but error checking is still\n\
744 performed.\n\
745 \n\
746 Return 0 if successful, otherwise return -1.\n\
747 @end deftypefn")
748 {
749  octave_value_list retval;
750 
751  retval(1) = std::string ();
752  retval(0) = -1;
753 
754  if (args.length () == 2)
755  {
756  pid_t pid = args(0).int_value (true);
757 
758  if (! error_state)
759  {
760  int sig = args(1).int_value (true);
761 
762  if (! error_state)
763  {
764  std::string msg;
765 
766  int status = octave_syscalls::kill (pid, sig, msg);
767 
768  retval(1) = msg;
769  retval(0) = status;
770  }
771  }
772  }
773  else
774  print_usage ();
775 
776  return retval;
777 }
778 
779 DEFUNX ("lstat", Flstat, args, ,
780  "-*- texinfo -*-\n\
781 @deftypefn {Built-in Function} {@var{info} =} lstat (@var{symlink})\n\
782 @deftypefnx {Built-in Function} {[@var{info}, @var{err}, @var{msg}] =} lstat (@var{symlink})\n\
783 Return a structure @var{info} containing information about the symbolic link\n\
784 @var{symlink}.\n\
785 \n\
786 The function outputs are described in the documentation for @code{stat}.\n\
787 @seealso{stat, symlink}\n\
788 @end deftypefn")
789 {
790  octave_value_list retval;
791 
792  if (args.length () == 1)
793  {
794  std::string fname = args(0).string_value ();
795 
796  if (! error_state)
797  {
798  file_stat fs (fname, false);
799 
800  retval = mk_stat_result (fs);
801  }
802  }
803  else
804  print_usage ();
805 
806  return retval;
807 }
808 
809 DEFUNX ("mkfifo", Fmkfifo, args, ,
810  "-*- texinfo -*-\n\
811 @deftypefn {Built-in Function} {} mkfifo (@var{name}, @var{mode})\n\
812 @deftypefnx {Built-in Function} {[@var{err}, @var{msg}] =} mkfifo (@var{name}, @var{mode})\n\
813 Create a FIFO special file named @var{name} with file mode @var{mode}\n\
814 \n\
815 If successful, @var{err} is 0 and @var{msg} is an empty string.\n\
816 Otherwise, @var{err} is nonzero and @var{msg} contains a\n\
817 system-dependent error message.\n\
818 @seealso{pipe}\n\
819 @end deftypefn")
820 {
821  octave_value_list retval;
822 
823  retval(1) = std::string ();
824  retval(0) = -1;
825 
826  int nargin = args.length ();
827 
828  if (nargin == 2)
829  {
830  if (args(0).is_string ())
831  {
832  std::string name = args(0).string_value ();
833 
834  if (args(1).is_scalar_type ())
835  {
836  long mode = args(1).long_value ();
837 
838  if (! error_state)
839  {
840  std::string msg;
841 
842  int status = octave_mkfifo (name, mode, msg);
843 
844  retval(0) = status;
845 
846  if (status < 0)
847  retval(1) = msg;
848  }
849  else
850  error ("mkfifo: invalid MODE");
851  }
852  else
853  error ("mkfifo: MODE must be an integer");
854  }
855  else
856  error ("mkfifo: FILE must be a string");
857  }
858  else
859  print_usage ();
860 
861  return retval;
862 }
863 
864 DEFUNX ("pipe", Fpipe, args, ,
865  "-*- texinfo -*-\n\
866 @deftypefn {Built-in Function} {[@var{read_fd}, @var{write_fd}, @var{err}, @var{msg}] =} pipe ()\n\
867 Create a pipe and return the reading and writing ends of the pipe\n\
868 into @var{read_fd} and @var{write_fd} respectively.\n\
869 \n\
870 If successful, @var{err} is 0 and @var{msg} is an empty string.\n\
871 Otherwise, @var{err} is nonzero and @var{msg} contains a\n\
872 system-dependent error message.\n\
873 @seealso{mkfifo}\n\
874 @end deftypefn")
875 {
876  octave_value_list retval;
877 
878  retval(3) = std::string ();
879  retval(2) = -1;
880  retval(1) = -1;
881  retval(0) = -1;
882 
883  int nargin = args.length ();
884 
885  if (nargin == 0)
886  {
887  int fid[2];
888 
889  std::string msg;
890 
891  int status = octave_syscalls::pipe (fid, msg);
892 
893  if (status < 0)
894  retval(3) = msg;
895  else
896  {
897  FILE *ifile = fdopen (fid[0], "r");
898  FILE *ofile = fdopen (fid[1], "w");
899 
900  std::string nm;
901 
903  std::ios::in);
904 
906  std::ios::out);
907 
908  retval(2) = status;
909  retval(1) = octave_stream_list::insert (os);
910  retval(0) = octave_stream_list::insert (is);
911  }
912  }
913  else
914  print_usage ();
915 
916  return retval;
917 }
918 
919 DEFUNX ("stat", Fstat, args, ,
920  "-*- texinfo -*-\n\
921 @deftypefn {Built-in Function} {[@var{info}, @var{err}, @var{msg}] =} stat (@var{file})\n\
922 @deftypefnx {Built-in Function} {[@var{info}, @var{err}, @var{msg}] =} stat (@var{fid})\n\
923 @deftypefnx {Built-in Function} {[@var{info}, @var{err}, @var{msg}] =} lstat (@var{file})\n\
924 @deftypefnx {Built-in Function} {[@var{info}, @var{err}, @var{msg}] =} lstat (@var{fid})\n\
925 Return a structure @var{info} containing the following information about\n\
926 @var{file} or file identifier @var{fid}.\n\
927 \n\
928 @table @code\n\
929 @item dev\n\
930 ID of device containing a directory entry for this file.\n\
931 \n\
932 @item ino\n\
933 File number of the file.\n\
934 \n\
935 @item mode\n\
936 File mode, as an integer. Use the functions @w{@code{S_ISREG}},\n\
937 @w{@code{S_ISDIR}}, @w{@code{S_ISCHR}}, @w{@code{S_ISBLK}},\n\
938 @w{@code{S_ISFIFO}}, @w{@code{S_ISLNK}}, or @w{@code{S_ISSOCK}} to extract\n\
939 information from this value.\n\
940 \n\
941 @item modestr\n\
942 File mode, as a string of ten letters or dashes as would be returned by\n\
943 @kbd{ls -l}.\n\
944 \n\
945 @item nlink\n\
946 Number of links.\n\
947 \n\
948 @item uid\n\
949 User ID of file's owner.\n\
950 \n\
951 @item gid\n\
952 Group ID of file's group.\n\
953 \n\
954 @item rdev\n\
955 ID of device for block or character special files.\n\
956 \n\
957 @item size\n\
958 Size in bytes.\n\
959 \n\
960 @item atime\n\
961 Time of last access in the same form as time values returned from\n\
962 @code{time}. @xref{Timing Utilities}.\n\
963 \n\
964 @item mtime\n\
965 Time of last modification in the same form as time values returned from\n\
966 @code{time}. @xref{Timing Utilities}.\n\
967 \n\
968 @item ctime\n\
969 Time of last file status change in the same form as time values\n\
970 returned from @code{time}. @xref{Timing Utilities}.\n\
971 \n\
972 @item blksize\n\
973 Size of blocks in the file.\n\
974 \n\
975 @item blocks\n\
976 Number of blocks allocated for file.\n\
977 @end table\n\
978 \n\
979 If the call is successful @var{err} is 0 and @var{msg} is an empty\n\
980 string. If the file does not exist, or some other error occurs, @var{info}\n\
981 is an empty matrix, @var{err} is @minus{}1, and @var{msg} contains the\n\
982 corresponding system error message.\n\
983 \n\
984 If @var{file} is a symbolic link, @code{stat} will return information\n\
985 about the actual file that is referenced by the link. Use @code{lstat}\n\
986 if you want information about the symbolic link itself.\n\
987 \n\
988 For example:\n\
989 \n\
990 @example\n\
991 [info, err, msg] = stat (\"/vmlinuz\")\n\
992  @result{} info =\n\
993  @{\n\
994  atime = 855399756\n\
995  rdev = 0\n\
996  ctime = 847219094\n\
997  uid = 0\n\
998  size = 389218\n\
999  blksize = 4096\n\
1000  mtime = 847219094\n\
1001  gid = 6\n\
1002  nlink = 1\n\
1003  blocks = 768\n\
1004  mode = -rw-r--r--\n\
1005  modestr = -rw-r--r--\n\
1006  ino = 9316\n\
1007  dev = 2049\n\
1008  @}\n\
1009  @result{} err = 0\n\
1010  @result{} msg =\n\
1011 @end example\n\
1012 @seealso{lstat, ls, dir}\n\
1013 @end deftypefn")
1014 {
1015  octave_value_list retval;
1016 
1017  if (args.length () == 1)
1018  {
1019  if (args(0).is_scalar_type ())
1020  {
1021  int fid = octave_stream_list::get_file_number (args(0));
1022 
1023  if (! error_state)
1024  {
1025  file_fstat fs (fid);
1026 
1027  retval = mk_stat_result (fs);
1028  }
1029  }
1030  else
1031  {
1032  std::string fname = args(0).string_value ();
1033 
1034  if (! error_state)
1035  {
1036  file_stat fs (fname);
1037 
1038  retval = mk_stat_result (fs);
1039  }
1040  }
1041  }
1042  else
1043  print_usage ();
1044 
1045  return retval;
1046 }
1047 
1048 DEFUNX ("S_ISREG", FS_ISREG, args, ,
1049  "-*- texinfo -*-\n\
1050 @deftypefn {Built-in Function} {} S_ISREG (@var{mode})\n\
1051 Return true if @var{mode} corresponds to a regular file.\n\
1052 \n\
1053 The value of @var{mode} is assumed to be returned from a call to @code{stat}.\n\
1054 @seealso{stat, lstat}\n\
1055 @end deftypefn")
1056 {
1057  octave_value retval = false;
1058 
1059  if (args.length () == 1)
1060  {
1061  double mode = args(0).double_value ();
1062 
1063  if (! error_state)
1064  retval = file_stat::is_reg (static_cast<mode_t> (mode));
1065  else
1066  error ("S_ISREG: invalid MODE value");
1067  }
1068  else
1069  print_usage ();
1070 
1071  return retval;
1072 }
1073 
1074 DEFUNX ("S_ISDIR", FS_ISDIR, args, ,
1075  "-*- texinfo -*-\n\
1076 @deftypefn {Built-in Function} {} S_ISDIR (@var{mode})\n\
1077 Return true if @var{mode} corresponds to a directory.\n\
1078 \n\
1079 The value of @var{mode} is assumed to be returned from a call to @code{stat}.\n\
1080 @seealso{stat, lstat}\n\
1081 @end deftypefn")
1082 {
1083  octave_value retval = false;
1084 
1085  if (args.length () == 1)
1086  {
1087  double mode = args(0).double_value ();
1088 
1089  if (! error_state)
1090  retval = file_stat::is_dir (static_cast<mode_t> (mode));
1091  else
1092  error ("S_ISDIR: invalid MODE value");
1093  }
1094  else
1095  print_usage ();
1096 
1097  return retval;
1098 }
1099 
1100 DEFUNX ("S_ISCHR", FS_ISCHR, args, ,
1101  "-*- texinfo -*-\n\
1102 @deftypefn {Built-in Function} {} S_ISCHR (@var{mode})\n\
1103 Return true if @var{mode} corresponds to a character device.\n\
1104 \n\
1105 The value of @var{mode} is assumed to be returned from a call to @code{stat}.\n\
1106 @seealso{stat, lstat}\n\
1107 @end deftypefn")
1108 {
1109  octave_value retval = false;
1110 
1111  if (args.length () == 1)
1112  {
1113  double mode = args(0).double_value ();
1114 
1115  if (! error_state)
1116  retval = file_stat::is_chr (static_cast<mode_t> (mode));
1117  else
1118  error ("S_ISCHR: invalid MODE value");
1119  }
1120  else
1121  print_usage ();
1122 
1123  return retval;
1124 }
1125 
1126 DEFUNX ("S_ISBLK", FS_ISBLK, args, ,
1127  "-*- texinfo -*-\n\
1128 @deftypefn {Built-in Function} {} S_ISBLK (@var{mode})\n\
1129 Return true if @var{mode} corresponds to a block device.\n\
1130 \n\
1131 The value of @var{mode} is assumed to be returned from a call to @code{stat}.\n\
1132 @seealso{stat, lstat}\n\
1133 @end deftypefn")
1134 {
1135  octave_value retval = false;
1136 
1137  if (args.length () == 1)
1138  {
1139  double mode = args(0).double_value ();
1140 
1141  if (! error_state)
1142  retval = file_stat::is_blk (static_cast<mode_t> (mode));
1143  else
1144  error ("S_ISBLK: invalid MODE value");
1145  }
1146  else
1147  print_usage ();
1148 
1149  return retval;
1150 }
1151 
1152 DEFUNX ("S_ISFIFO", FS_ISFIFO, args, ,
1153  "-*- texinfo -*-\n\
1154 @deftypefn {Built-in Function} {} S_ISFIFO (@var{mode})\n\
1155 Return true if @var{mode} corresponds to a fifo.\n\
1156 \n\
1157 The value of @var{mode} is assumed to be returned from a call to @code{stat}.\n\
1158 @seealso{stat, lstat}\n\
1159 @end deftypefn")
1160 {
1161  octave_value retval = false;
1162 
1163  if (args.length () == 1)
1164  {
1165  double mode = args(0).double_value ();
1166 
1167  if (! error_state)
1168  retval = file_stat::is_fifo (static_cast<mode_t> (mode));
1169  else
1170  error ("S_ISFIFO: invalid MODE value");
1171  }
1172  else
1173  print_usage ();
1174 
1175  return retval;
1176 }
1177 
1178 DEFUNX ("S_ISLNK", FS_ISLNK, args, ,
1179  "-*- texinfo -*-\n\
1180 @deftypefn {Built-in Function} {} S_ISLNK (@var{mode})\n\
1181 Return true if @var{mode} corresponds to a symbolic link.\n\
1182 \n\
1183 The value of @var{mode} is assumed to be returned from a call to @code{stat}.\n\
1184 @seealso{stat, lstat}\n\
1185 @end deftypefn")
1186 {
1187  octave_value retval = false;
1188 
1189  if (args.length () == 1)
1190  {
1191  double mode = args(0).double_value ();
1192 
1193  if (! error_state)
1194  retval = file_stat::is_lnk (static_cast<mode_t> (mode));
1195  else
1196  error ("S_ISLNK: invalid MODE value");
1197  }
1198  else
1199  print_usage ();
1200 
1201  return retval;
1202 }
1203 
1204 DEFUNX ("S_ISSOCK", FS_ISSOCK, args, ,
1205  "-*- texinfo -*-\n\
1206 @deftypefn {Built-in Function} {} S_ISSOCK (@var{mode})\n\
1207 Return true if @var{mode} corresponds to a socket.\n\
1208 \n\
1209 The value of @var{mode} is assumed to be returned from a call to @code{stat}.\n\
1210 @seealso{stat, lstat}\n\
1211 @end deftypefn")
1212 {
1213  octave_value retval = false;
1214 
1215  if (args.length () == 1)
1216  {
1217  double mode = args(0).double_value ();
1218 
1219  if (! error_state)
1220  retval = file_stat::is_sock (static_cast<mode_t> (mode));
1221  else
1222  error ("S_ISSOCK: invalid MODE value");
1223  }
1224  else
1225  print_usage ();
1226 
1227  return retval;
1228 }
1229 
1230 DEFUN (gethostname, args, ,
1231  "-*- texinfo -*-\n\
1232 @deftypefn {Built-in Function} {} gethostname ()\n\
1233 Return the hostname of the system where Octave is running.\n\
1234 @end deftypefn")
1235 {
1236  octave_value retval;
1237 
1238  if (args.length () == 0)
1239  retval = octave_env::get_host_name ();
1240  else
1241  print_usage ();
1242 
1243  return retval;
1244 }
1245 
1246 DEFUN (uname, args, ,
1247  "-*- texinfo -*-\n\
1248 @deftypefn {Built-in Function} {[@var{uts}, @var{err}, @var{msg}] =} uname ()\n\
1249 Return system information in the structure. For example:\n\
1250 \n\
1251 @example\n\
1252 @group\n\
1253 uname ()\n\
1254  @result{} @{\n\
1255  sysname = x86_64\n\
1256  nodename = segfault\n\
1257  release = 2.6.15-1-amd64-k8-smp\n\
1258  version = Linux\n\
1259  machine = #2 SMP Thu Feb 23 04:57:49 UTC 2006\n\
1260  @}\n\
1261 @end group\n\
1262 @end example\n\
1263 \n\
1264 If successful, @var{err} is 0 and @var{msg} is an empty string.\n\
1265 Otherwise, @var{err} is nonzero and @var{msg} contains a\n\
1266 system-dependent error message.\n\
1267 @end deftypefn")
1268 {
1269  octave_value_list retval;
1270 
1271  if (args.length () == 0)
1272  {
1273  octave_uname sysinfo;
1274 
1276 
1277  m.assign ("sysname", sysinfo.sysname ());
1278  m.assign ("nodename", sysinfo.nodename ());
1279  m.assign ("release", sysinfo.release ());
1280  m.assign ("version", sysinfo.version ());
1281  m.assign ("machine", sysinfo.machine ());
1282 
1283  retval(2) = sysinfo.message ();
1284  retval(1) = sysinfo.error ();
1285  retval(0) = m;
1286  }
1287  else
1288  print_usage ();
1289 
1290  return retval;
1291 }
1292 
1293 DEFUNX ("unlink", Funlink, args, ,
1294  "-*- texinfo -*-\n\
1295 @deftypefn {Built-in Function} {[@var{err}, @var{msg}] =} unlink (@var{file})\n\
1296 Delete the file named @var{file}.\n\
1297 \n\
1298 If successful, @var{err} is 0 and @var{msg} is an empty string.\n\
1299 Otherwise, @var{err} is nonzero and @var{msg} contains a\n\
1300 system-dependent error message.\n\
1301 @end deftypefn")
1302 {
1303  octave_value_list retval;
1304 
1305  retval(1) = std::string ();
1306  retval(0) = -1;
1307 
1308  int nargin = args.length ();
1309 
1310  if (nargin == 1)
1311  {
1312  if (args(0).is_string ())
1313  {
1314  std::string name = args(0).string_value ();
1315 
1316  std::string msg;
1317 
1318  int status = octave_unlink (name, msg);
1319 
1320  retval(1) = msg;
1321  retval(0) = status;
1322  }
1323  else
1324  error ("unlink: FILE must be a string");
1325  }
1326  else
1327  print_usage ();
1328 
1329  return retval;
1330 }
1331 
1332 DEFUNX ("waitpid", Fwaitpid, args, ,
1333  "-*- texinfo -*-\n\
1334 @deftypefn {Built-in Function} {[@var{pid}, @var{status}, @var{msg}] =} waitpid (@var{pid}, @var{options})\n\
1335 Wait for process @var{pid} to terminate. The @var{pid} argument can be:\n\
1336 \n\
1337 @table @asis\n\
1338 @item @minus{}1\n\
1339 Wait for any child process.\n\
1340 \n\
1341 @item 0\n\
1342 Wait for any child process whose process group ID is equal to that of\n\
1343 the Octave interpreter process.\n\
1344 \n\
1345 @item > 0\n\
1346 Wait for termination of the child process with ID @var{pid}.\n\
1347 @end table\n\
1348 \n\
1349 The @var{options} argument can be a bitwise OR of zero or more of\n\
1350 the following constants:\n\
1351 \n\
1352 @table @code\n\
1353 @item 0\n\
1354 Wait until signal is received or a child process exits (this is the\n\
1355 default if the @var{options} argument is missing).\n\
1356 \n\
1357 @item WNOHANG\n\
1358 Do not hang if status is not immediately available.\n\
1359 \n\
1360 @item WUNTRACED\n\
1361 Report the status of any child processes that are stopped, and whose\n\
1362 status has not yet been reported since they stopped.\n\
1363 \n\
1364 @item WCONTINUE\n\
1365 Return if a stopped child has been resumed by delivery of @code{SIGCONT}.\n\
1366 This value may not be meaningful on all systems.\n\
1367 @end table\n\
1368 \n\
1369 If the returned value of @var{pid} is greater than 0, it is the process\n\
1370 ID of the child process that exited. If an error occurs, @var{pid} will\n\
1371 be less than zero and @var{msg} will contain a system-dependent error\n\
1372 message. The value of @var{status} contains additional system-dependent\n\
1373 information about the subprocess that exited.\n\
1374 @seealso{WCONTINUE, WCOREDUMP, WEXITSTATUS, WIFCONTINUED, WIFSIGNALED, WIFSTOPPED, WNOHANG, WSTOPSIG, WTERMSIG, WUNTRACED}\n\
1375 @end deftypefn")
1376 {
1377  octave_value_list retval;
1378 
1379  retval(2) = std::string ();
1380  retval(1) = 0;
1381  retval(0) = -1;
1382 
1383  int nargin = args.length ();
1384 
1385  if (nargin == 1 || nargin == 2)
1386  {
1387  pid_t pid = args(0).int_value (true);
1388 
1389  if (! error_state)
1390  {
1391  int options = 0;
1392 
1393  if (args.length () == 2)
1394  options = args(1).int_value (true);
1395 
1396  if (! error_state)
1397  {
1398  std::string msg;
1399 
1400  int status = 0;
1401 
1402  pid_t result = octave_syscalls::waitpid (pid, &status,
1403  options, msg);
1404 
1405  retval(2) = msg;
1406  retval(1) = status;
1407  retval(0) = result;
1408  }
1409  else
1410  error ("waitpid: OPTIONS must be an integer");
1411  }
1412  else
1413  error ("waitpid: PID must be an integer value");
1414  }
1415  else
1416  print_usage ();
1417 
1418  return retval;
1419 }
1420 
1421 DEFUNX ("WIFEXITED", FWIFEXITED, args, ,
1422  "-*- texinfo -*-\n\
1423 @deftypefn {Built-in Function} {} WIFEXITED (@var{status})\n\
1424 Given @var{status} from a call to @code{waitpid}, return true if the\n\
1425 child terminated normally.\n\
1426 @seealso{waitpid, WEXITSTATUS, WIFSIGNALED, WTERMSIG, WCOREDUMP, WIFSTOPPED, WSTOPSIG, WIFCONTINUED}\n\
1427 @end deftypefn")
1428 {
1429  octave_value retval = false;
1430 
1431  if (args.length () == 1)
1432  {
1433  int status = args(0).int_value ();
1434 
1435  if (! error_state)
1436  retval = octave_wait::ifexited (status);
1437  else
1438  error ("WIFEXITED: STATUS must be an integer");
1439  }
1440 
1441  return retval;
1442 }
1443 
1444 DEFUNX ("WEXITSTATUS", FWEXITSTATUS, args, ,
1445  "-*- texinfo -*-\n\
1446 @deftypefn {Built-in Function} {} WEXITSTATUS (@var{status})\n\
1447 Given @var{status} from a call to @code{waitpid}, return the exit\n\
1448 status of the child. This function should only be employed if\n\
1449 @code{WIFEXITED} returned true.\n\
1450 @seealso{waitpid, WIFEXITED, WIFSIGNALED, WTERMSIG, WCOREDUMP, WIFSTOPPED, WSTOPSIG, WIFCONTINUED}\n\
1451 @end deftypefn")
1452 {
1453  octave_value retval = 0;
1454 
1455  if (args.length () == 1)
1456  {
1457  int status = args(0).int_value ();
1458 
1459  if (! error_state)
1460  retval = octave_wait::exitstatus (status);
1461  else
1462  error ("WEXITSTATUS: STATUS must be an integer");
1463  }
1464 
1465  return retval;
1466 }
1467 
1468 DEFUNX ("WIFSIGNALED", FWIFSIGNALED, args, ,
1469  "-*- texinfo -*-\n\
1470 @deftypefn {Built-in Function} {} WIFSIGNALED (@var{status})\n\
1471 Given @var{status} from a call to @code{waitpid}, return true if the\n\
1472 child process was terminated by a signal.\n\
1473 @seealso{waitpid, WIFEXITED, WEXITSTATUS, WTERMSIG, WCOREDUMP, WIFSTOPPED, WSTOPSIG, WIFCONTINUED}\n\
1474 @end deftypefn")
1475 {
1476  octave_value retval = false;
1477 
1478  if (args.length () == 1)
1479  {
1480  int status = args(0).int_value ();
1481 
1482  if (! error_state)
1483  retval = octave_wait::ifsignaled (status);
1484  else
1485  error ("WIFSIGNALED: STATUS must be an integer");
1486  }
1487 
1488  return retval;
1489 }
1490 
1491 DEFUNX ("WTERMSIG", FWTERMSIG, args, ,
1492  "-*- texinfo -*-\n\
1493 @deftypefn {Built-in Function} {} WTERMSIG (@var{status})\n\
1494 Given @var{status} from a call to @code{waitpid}, return the number of\n\
1495 the signal that caused the child process to terminate. This function\n\
1496 should only be employed if @code{WIFSIGNALED} returned true.\n\
1497 @seealso{waitpid, WIFEXITED, WEXITSTATUS, WIFSIGNALED, WCOREDUMP, WIFSTOPPED, WSTOPSIG, WIFCONTINUED}\n\
1498 @end deftypefn")
1499 {
1500  octave_value retval = 0;
1501 
1502  if (args.length () == 1)
1503  {
1504  int status = args(0).int_value ();
1505 
1506  if (! error_state)
1507  retval = octave_wait::termsig (status);
1508  else
1509  error ("WTERMSIG: STATUS must be an integer");
1510  }
1511 
1512  return retval;
1513 }
1514 
1515 DEFUNX ("WCOREDUMP", FWCOREDUMP, args, ,
1516  "-*- texinfo -*-\n\
1517 @deftypefn {Built-in Function} {} WCOREDUMP (@var{status})\n\
1518 Given @var{status} from a call to @code{waitpid}, return true if the\n\
1519 child produced a core dump. This function should only be employed if\n\
1520 @code{WIFSIGNALED} returned true. The macro used to implement this\n\
1521 function is not specified in POSIX.1-2001 and is not available on some\n\
1522 Unix implementations (e.g., AIX, SunOS).\n\
1523 @seealso{waitpid, WIFEXITED, WEXITSTATUS, WIFSIGNALED, WTERMSIG, WIFSTOPPED, WSTOPSIG, WIFCONTINUED}\n\
1524 @end deftypefn")
1525 {
1526  octave_value retval = false;
1527 
1528  if (args.length () == 1)
1529  {
1530  int status = args(0).int_value ();
1531 
1532  if (! error_state)
1533  retval = octave_wait::coredump (status);
1534  else
1535  error ("WCOREDUMP: STATUS must be an integer");
1536  }
1537 
1538  return retval;
1539 }
1540 
1541 DEFUNX ("WIFSTOPPED", FWIFSTOPPED, args, ,
1542  "-*- texinfo -*-\n\
1543 @deftypefn {Built-in Function} {} WIFSTOPPED (@var{status})\n\
1544 Given @var{status} from a call to @code{waitpid}, return true if the\n\
1545 child process was stopped by delivery of a signal; this is only\n\
1546 possible if the call was done using @code{WUNTRACED} or when the child\n\
1547 is being traced (see ptrace(2)).\n\
1548 @seealso{waitpid, WIFEXITED, WEXITSTATUS, WIFSIGNALED, WTERMSIG, WCOREDUMP, WSTOPSIG, WIFCONTINUED}\n\
1549 @end deftypefn")
1550 {
1551  octave_value retval = false;
1552 
1553  if (args.length () == 1)
1554  {
1555  int status = args(0).int_value ();
1556 
1557  if (! error_state)
1558  retval = octave_wait::ifstopped (status);
1559  else
1560  error ("WIFSTOPPED: STATUS must be an integer");
1561  }
1562 
1563  return retval;
1564 }
1565 
1566 DEFUNX ("WSTOPSIG", FWSTOPSIG, args, ,
1567  "-*- texinfo -*-\n\
1568 @deftypefn {Built-in Function} {} WSTOPSIG (@var{status})\n\
1569 Given @var{status} from a call to @code{waitpid}, return the number of\n\
1570 the signal which caused the child to stop. This function should only\n\
1571 be employed if @code{WIFSTOPPED} returned true.\n\
1572 @seealso{waitpid, WIFEXITED, WEXITSTATUS, WIFSIGNALED, WTERMSIG, WCOREDUMP, WIFSTOPPED, WIFCONTINUED}\n\
1573 @end deftypefn")
1574 {
1575  octave_value retval = 0;
1576 
1577  if (args.length () == 1)
1578  {
1579  int status = args(0).int_value ();
1580 
1581  if (! error_state)
1582  retval = octave_wait::stopsig (status);
1583  else
1584  error ("WSTOPSIG: STATUS must be an integer");
1585  }
1586 
1587  return retval;
1588 }
1589 
1590 DEFUNX ("WIFCONTINUED", FWIFCONTINUED, args, ,
1591  "-*- texinfo -*-\n\
1592 @deftypefn {Built-in Function} {} WIFCONTINUED (@var{status})\n\
1593 Given @var{status} from a call to @code{waitpid}, return true if the\n\
1594 child process was resumed by delivery of @code{SIGCONT}.\n\
1595 @seealso{waitpid, WIFEXITED, WEXITSTATUS, WIFSIGNALED, WTERMSIG, WCOREDUMP, WIFSTOPPED, WSTOPSIG}\n\
1596 @end deftypefn")
1597 {
1598  octave_value retval = false;
1599 
1600  if (args.length () == 1)
1601  {
1602  int status = args(0).int_value ();
1603 
1604  if (! error_state)
1605  retval = octave_wait::ifcontinued (status);
1606  else
1607  error ("WIFCONTINUED: STATUS must be an integer");
1608  }
1609 
1610  return retval;
1611 }
1612 
1613 DEFUNX ("canonicalize_file_name", Fcanonicalize_file_name, args, ,
1614  "-*- texinfo -*-\n\
1615 @deftypefn {Built-in Function} {[@var{cname}, @var{status}, @var{msg}] =} canonicalize_file_name (@var{fname})\n\
1616 Return the canonical name of file @var{fname}. If the file does not exist\n\
1617 the empty string (\"\") is returned.\n\
1618 @seealso{make_absolute_filename, is_absolute_filename, is_rooted_relative_filename}\n\
1619 @end deftypefn")
1620 {
1621  octave_value_list retval;
1622 
1623  if (args.length () == 1)
1624  {
1625  std::string name = args(0).string_value ();
1626 
1627  if (! error_state)
1628  {
1629  std::string msg;
1630 
1631  std::string result = octave_canonicalize_file_name (name, msg);
1632 
1633  retval(2) = msg;
1634  retval(1) = msg.empty () ? 0 : -1;
1635  retval(0) = result;
1636  }
1637  else
1638  error ("canonicalize_file_name: NAME must be a character string");
1639  }
1640  else
1641  print_usage ();
1642 
1643  return retval;
1644 }
1645 
1646 static octave_value
1647 const_value (const octave_value_list& args, int val)
1648 {
1649  octave_value retval;
1650 
1651  int nargin = args.length ();
1652 
1653  if (nargin == 0)
1654  retval = val;
1655  else
1656  print_usage ();
1657 
1658  return retval;
1659 }
1660 
1661 #if !defined (O_NONBLOCK) && defined (O_NDELAY)
1662 #define O_NONBLOCK O_NDELAY
1663 #endif
1664 
1665 DEFUNX ("F_DUPFD", FF_DUPFD, args, ,
1666  "-*- texinfo -*-\n\
1667 @deftypefn {Built-in Function} {} F_DUPFD ()\n\
1668 Return the numerical value to pass to @code{fcntl} to return a\n\
1669 duplicate file descriptor.\n\
1670 @seealso{fcntl, F_GETFD, F_GETFL, F_SETFD, F_SETFL}\n\
1671 @end deftypefn")
1672 {
1673 #if defined (F_DUPFD)
1674  return const_value (args, F_DUPFD);
1675 #else
1676  error ("F_DUPFD: not available on this system");
1677  return octave_value ();
1678 #endif
1679 }
1680 
1681 DEFUNX ("F_GETFD", FF_GETFD, args, ,
1682  "-*- texinfo -*-\n\
1683 @deftypefn {Built-in Function} {} F_GETFD ()\n\
1684 Return the numerical value to pass to @code{fcntl} to return the\n\
1685 file descriptor flags.\n\
1686 @seealso{fcntl, F_DUPFD, F_GETFL, F_SETFD, F_SETFL}\n\
1687 @end deftypefn")
1688 {
1689 #if defined (F_GETFD)
1690  return const_value (args, F_GETFD);
1691 #else
1692  error ("F_GETFD: not available on this system");
1693  return octave_value ();
1694 #endif
1695 }
1696 
1697 DEFUNX ("F_GETFL", FF_GETFL, args, ,
1698  "-*- texinfo -*-\n\
1699 @deftypefn {Built-in Function} {} F_GETFL ()\n\
1700 Return the numerical value to pass to @code{fcntl} to return the\n\
1701 file status flags.\n\
1702 @seealso{fcntl, F_DUPFD, F_GETFD, F_SETFD, F_SETFL}\n\
1703 @end deftypefn")
1704 {
1705 #if defined (F_GETFL)
1706  return const_value (args, F_GETFL);
1707 #else
1708  error ("F_GETFL: not available on this system");
1709  return octave_value ();
1710 #endif
1711 }
1712 
1713 DEFUNX ("F_SETFD", FF_SETFD, args, ,
1714  "-*- texinfo -*-\n\
1715 @deftypefn {Built-in Function} {} F_SETFD ()\n\
1716 Return the numerical value to pass to @code{fcntl} to set the file\n\
1717 descriptor flags.\n\
1718 @seealso{fcntl, F_DUPFD, F_GETFD, F_GETFL, F_SETFL}\n\
1719 @end deftypefn")
1720 {
1721 #if defined (F_SETFD)
1722  return const_value (args, F_SETFD);
1723 #else
1724  error ("F_SETFD: not available on this system");
1725  return octave_value ();
1726 #endif
1727 }
1728 
1729 DEFUNX ("F_SETFL", FF_SETFL, args, ,
1730  "-*- texinfo -*-\n\
1731 @deftypefn {Built-in Function} {} F_SETFL ()\n\
1732 Return the numerical value to pass to @code{fcntl} to set the file\n\
1733 status flags.\n\
1734 @seealso{fcntl, F_DUPFD, F_GETFD, F_GETFL, F_SETFD}\n\
1735 @end deftypefn")
1736 {
1737 #if defined (F_SETFL)
1738  return const_value (args, F_SETFL);
1739 #else
1740  error ("F_SETFL: not available on this system");
1741  return octave_value ();
1742 #endif
1743 }
1744 
1745 DEFUNX ("O_APPEND", FO_APPEND, args, ,
1746  "-*- texinfo -*-\n\
1747 @deftypefn {Built-in Function} {} O_APPEND ()\n\
1748 Return the numerical value of the file status flag that may be\n\
1749 returned by @code{fcntl} to indicate each write operation appends,\n\
1750 or that may be passed to @code{fcntl} to set the write mode to append.\n\
1751 @seealso{fcntl, O_ASYNC, O_CREAT, O_EXCL, O_NONBLOCK, O_RDONLY, O_RDWR, O_SYNC, O_TRUNC, O_WRONLY}\n\
1752 @end deftypefn")
1753 {
1754 #if defined (O_APPEND)
1755  return const_value (args, O_APPEND);
1756 #else
1757  error ("O_APPEND: not available on this system");
1758  return octave_value ();
1759 #endif
1760 }
1761 
1762 DEFUNX ("O_ASYNC", FO_ASYNC, args, ,
1763  "-*- texinfo -*-\n\
1764 @deftypefn {Built-in Function} {} O_ASYNC ()\n\
1765 Return the numerical value of the file status flag that may be\n\
1766 returned by @code{fcntl} to indicate asynchronous I/O.\n\
1767 @seealso{fcntl, O_APPEND, O_CREAT, O_EXCL, O_NONBLOCK, O_RDONLY, O_RDWR, O_SYNC, O_TRUNC, O_WRONLY}\n\
1768 @end deftypefn")
1769 {
1770 #if defined (O_ASYNC)
1771  return const_value (args, O_ASYNC);
1772 #else
1773  error ("O_ASYNC: not available on this system");
1774  return octave_value ();
1775 #endif
1776 }
1777 
1778 DEFUNX ("O_CREAT", FO_CREAT, args, ,
1779  "-*- texinfo -*-\n\
1780 @deftypefn {Built-in Function} {} O_CREAT ()\n\
1781 Return the numerical value of the file status flag that may be\n\
1782 returned by @code{fcntl} to indicate that a file should be\n\
1783 created if it does not exist.\n\
1784 @seealso{fcntl, O_APPEND, O_ASYNC, O_EXCL, O_NONBLOCK, O_RDONLY, O_RDWR, O_SYNC, O_TRUNC, O_WRONLY}\n\
1785 @end deftypefn")
1786 {
1787 #if defined (O_CREAT)
1788  return const_value (args, O_CREAT);
1789 #else
1790  error ("O_CREAT: not available on this system");
1791  return octave_value ();
1792 #endif
1793 }
1794 
1795 DEFUNX ("O_EXCL", FO_EXCL, args, ,
1796  "-*- texinfo -*-\n\
1797 @deftypefn {Built-in Function} {} O_EXCL ()\n\
1798 Return the numerical value of the file status flag that may be\n\
1799 returned by @code{fcntl} to indicate that file locking is used.\n\
1800 @seealso{fcntl, O_APPEND, O_ASYNC, O_CREAT, O_NONBLOCK, O_RDONLY, O_RDWR, O_SYNC, O_TRUNC, O_WRONLY}\n\
1801 @end deftypefn")
1802 {
1803 #if defined (O_EXCL)
1804  return const_value (args, O_EXCL);
1805 #else
1806  error ("O_EXCL: not available on this system");
1807  return octave_value ();
1808 #endif
1809 }
1810 
1811 DEFUNX ("O_NONBLOCK", FO_NONBLOCK, args, ,
1812  "-*- texinfo -*-\n\
1813 @deftypefn {Built-in Function} {} O_NONBLOCK ()\n\
1814 Return the numerical value of the file status flag that may be\n\
1815 returned by @code{fcntl} to indicate that non-blocking I/O is in use,\n\
1816 or that may be passsed to @code{fcntl} to set non-blocking I/O.\n\
1817 @seealso{fcntl, O_APPEND, O_ASYNC, O_CREAT, O_EXCL, O_RDONLY, O_RDWR, O_SYNC, O_TRUNC, O_WRONLY}\n\
1818 @end deftypefn")
1819 {
1820 #if defined (O_NONBLOCK)
1821  return const_value (args, O_NONBLOCK);
1822 #else
1823  error ("O_NONBLOCK: not available on this system");
1824  return octave_value ();
1825 #endif
1826 }
1827 
1828 DEFUNX ("O_RDONLY", FO_RDONLY, args, ,
1829  "-*- texinfo -*-\n\
1830 @deftypefn {Built-in Function} {} O_RDONLY ()\n\
1831 Return the numerical value of the file status flag that may be\n\
1832 returned by @code{fcntl} to indicate that a file is open for\n\
1833 reading only.\n\
1834 @seealso{fcntl, O_APPEND, O_ASYNC, O_CREAT, O_EXCL, O_NONBLOCK, O_RDWR, O_SYNC, O_TRUNC, O_WRONLY}\n\
1835 @end deftypefn")
1836 {
1837 #if defined (O_RDONLY)
1838  return const_value (args, O_RDONLY);
1839 #else
1840  error ("O_RDONLY: not available on this system");
1841  return octave_value ();
1842 #endif
1843 }
1844 
1845 DEFUNX ("O_RDWR", FO_RDWR, args, ,
1846  "-*- texinfo -*-\n\
1847 @deftypefn {Built-in Function} {} O_RDWR ()\n\
1848 Return the numerical value of the file status flag that may be\n\
1849 returned by @code{fcntl} to indicate that a file is open for both\n\
1850 reading and writing.\n\
1851 @seealso{fcntl, O_APPEND, O_ASYNC, O_CREAT, O_EXCL, O_NONBLOCK, O_RDONLY, O_SYNC, O_TRUNC, O_WRONLY}\n\
1852 @end deftypefn")
1853 {
1854 #if defined (O_RDWR)
1855  return const_value (args, O_RDWR);
1856 #else
1857  error ("O_RDWR: not available on this system");
1858  return octave_value ();
1859 #endif
1860 }
1861 
1862 DEFUNX ("O_SYNC", FO_SYNC, args, ,
1863  "-*- texinfo -*-\n\
1864 @deftypefn {Built-in Function} {} O_SYNC ()\n\
1865 Return the numerical value of the file status flag that may be\n\
1866 returned by @code{fcntl} to indicate that a file is open for\n\
1867 synchronous I/O.\n\
1868 @seealso{fcntl, O_APPEND, O_ASYNC, O_CREAT, O_EXCL, O_NONBLOCK, O_RDONLY, O_RDWR, O_TRUNC, O_WRONLY}\n\
1869 @end deftypefn")
1870 {
1871 #if defined (O_SYNC)
1872  return const_value (args, O_SYNC);
1873 #else
1874  error ("O_SYNC: not available on this system");
1875  return octave_value ();
1876 #endif
1877 }
1878 
1879 DEFUNX ("O_TRUNC", FO_TRUNC, args, ,
1880  "-*- texinfo -*-\n\
1881 @deftypefn {Built-in Function} O_TRUNC ()\n\
1882 Return the numerical value of the file status flag that may be\n\
1883 returned by @code{fcntl} to indicate that if file exists, it should\n\
1884 be truncated when writing.\n\
1885 @seealso{fcntl, O_APPEND, O_ASYNC, O_CREAT, O_EXCL, O_NONBLOCK, O_RDONLY, O_RDWR, O_SYNC, O_WRONLY}\n\
1886 @end deftypefn")
1887 {
1888 #if defined (O_TRUNC)
1889  return const_value (args, O_TRUNC);
1890 #else
1891  error ("O_TRUNC: not available on this system");
1892  return octave_value ();
1893 #endif
1894 }
1895 
1896 DEFUNX ("O_WRONLY", FO_WRONLY, args, ,
1897  "-*- texinfo -*-\n\
1898 @deftypefn {Built-in Function} {} O_WRONLY ()\n\
1899 Return the numerical value of the file status flag that may be\n\
1900 returned by @code{fcntl} to indicate that a file is open for\n\
1901 writing only.\n\
1902 @seealso{fcntl, O_APPEND, O_ASYNC, O_CREAT, O_EXCL, O_NONBLOCK, O_RDONLY, O_RDWR, O_SYNC, O_TRUNC}\n\
1903 @end deftypefn")
1904 {
1905 #if defined (O_WRONLY)
1906  return const_value (args, O_WRONLY);
1907 #else
1908  error ("O_WRONLY: not available on this system");
1909  return octave_value ();
1910 #endif
1911 }
1912 
1913 #if !defined (WNOHANG)
1914 #define WNOHANG 0
1915 #endif
1916 
1917 DEFUNX ("WNOHANG", FWNOHANG, args, ,
1918  "-*- texinfo -*-\n\
1919 @deftypefn {Built-in Function} {} WNOHANG ()\n\
1920 Return the numerical value of the option argument that may be\n\
1921 passed to @code{waitpid} to indicate that it should return its\n\
1922 status immediately instead of waiting for a process to exit.\n\
1923 @seealso{waitpid, WUNTRACED, WCONTINUE}\n\
1924 @end deftypefn")
1925 {
1926  return const_value (args, WNOHANG);
1927 }
1928 
1929 #if !defined (WUNTRACED)
1930 #define WUNTRACED 0
1931 #endif
1932 
1933 DEFUNX ("WUNTRACED", FWUNTRACED, args, ,
1934  "-*- texinfo -*-\n\
1935 @deftypefn {Built-in Function} {} WUNTRACED ()\n\
1936 Return the numerical value of the option argument that may be\n\
1937 passed to @code{waitpid} to indicate that it should also return\n\
1938 if the child process has stopped but is not traced via the\n\
1939 @code{ptrace} system call\n\
1940 @seealso{waitpid, WNOHANG, WCONTINUE}\n\
1941 @end deftypefn")
1942 {
1943  return const_value (args, WUNTRACED);
1944 }
1945 
1946 #if !defined (WCONTINUE)
1947 #define WCONTINUE 0
1948 #endif
1949 
1950 DEFUNX ("WCONTINUE", FWCONTINUE, args, ,
1951  "-*- texinfo -*-\n\
1952 @deftypefn {Built-in Function} {} WCONTINUE ()\n\
1953 Return the numerical value of the option argument that may be\n\
1954 passed to @code{waitpid} to indicate that it should also return\n\
1955 if a stopped child has been resumed by delivery of a @code{SIGCONT}\n\
1956 signal.\n\
1957 @seealso{waitpid, WNOHANG, WUNTRACED}\n\
1958 @end deftypefn")
1959 {
1960  return const_value (args, WCONTINUE);
1961 }