comparison src/file-io.cc @ 1230:92609e161b29

[project @ 1995-04-10 01:08:57 by jwe]
author jwe
date Mon, 10 Apr 1995 01:14:34 +0000
parents b2b7c5264ac2
children 611d403c7f3d
comparison
equal deleted inserted replaced
1229:7d7c3eaa1d3b 1230:92609e161b29
20 Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 20 Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
21 21
22 */ 22 */
23 23
24 // Written by John C. Campbell <jcc@che.utexas.edu>. 24 // Written by John C. Campbell <jcc@che.utexas.edu>.
25 //
26 // Thomas Baier <baier@ci.tuwien.ac.at> added the following functions:
27 //
28 // popen pclose execute sync_system async_system
29 // waitpid mkfifo unlink
30
25 31
26 #ifdef HAVE_CONFIG_H 32 #ifdef HAVE_CONFIG_H
27 #include "config.h" 33 #include <config.h>
28 #endif 34 #endif
29 35
30 #include <DLList.h> 36 #include <sys/types.h>
31 #include <unistd.h> 37 #include <unistd.h>
32 #include <string.h> 38 #include <string.h>
33 #include <stdio.h> 39 #include <stdio.h>
34 #include <errno.h> 40 #include <errno.h>
35 #include <stdlib.h> 41 #include <stdlib.h>
36 #include <strstream.h> 42 #include <strstream.h>
43 #include <sys/wait.h>
44 #include <fcntl.h>
37 #include <ctype.h> 45 #include <ctype.h>
46
47 #include <DLList.h>
38 48
39 #include "dMatrix.h" 49 #include "dMatrix.h"
40 50
41 #include "statdefs.h" 51 #include "statdefs.h"
42 #include "file-io.h" 52 #include "file-io.h"
283 293
284 return retval; 294 return retval;
285 } 295 }
286 296
287 DEFUN ("fclose", Ffclose, Sfclose, 1, 1, 297 DEFUN ("fclose", Ffclose, Sfclose, 1, 1,
288 "fclose (FILENAME or FILENUM): close a file") 298 "fclose (FILENAME or FILENUM): close a file")
289 { 299 {
290 Octave_object retval; 300 Octave_object retval;
291 301
292 int nargin = args.length (); 302 int nargin = args.length ();
293 303
1691 \n\ 1701 \n\
1692 FILENUM : file number from fopen\n\ 1702 FILENUM : file number from fopen\n\
1693 SIZE : size specification for the Data matrix\n\ 1703 SIZE : size specification for the Data matrix\n\
1694 PRECISION : type of data to read, valid types are\n\ 1704 PRECISION : type of data to read, valid types are\n\
1695 \n\ 1705 \n\
1696 'char', 'schar', 'short', 'int', 'long', 'float'\n\ 1706 \"char\" \"schar\" \"short\" \"int\" \"long\" \"float\"\n\
1697 'double', 'uchar', 'ushort', 'uint', 'ulong'\n\ 1707 \"double\" \"uchar\" \"ushort\" \"uint\" \"ulong\"\n\
1698 \n\ 1708 \n\
1699 DATA : matrix in which the data is stored\n\ 1709 DATA : matrix in which the data is stored\n\
1700 COUNT : number of elements read") 1710 COUNT : number of elements read")
1701 { 1711 {
1702 Octave_object retval; 1712 Octave_object retval;
1772 \n\ 1782 \n\
1773 FILENUM : file number from fopen\n\ 1783 FILENUM : file number from fopen\n\
1774 DATA : matrix of elements to be written\n\ 1784 DATA : matrix of elements to be written\n\
1775 PRECISION : type of data to read, valid types are\n\ 1785 PRECISION : type of data to read, valid types are\n\
1776 \n\ 1786 \n\
1777 'char', 'schar', 'short', 'int', 'long', 'float'\n\ 1787 \"char\" \"schar\" \"short\" \"int\" \"long\" \"float\"\n\
1778 'double', 'uchar', 'ushort', 'uint', 'ulong'\n\ 1788 \"double\" \"uchar\" \"ushort\" \"uint\" \"ulong\"\n\
1779 \n\ 1789 \n\
1780 COUNT : number of elements written") 1790 COUNT : number of elements written")
1781 { 1791 {
1782 Octave_object retval; 1792 Octave_object retval;
1783 1793
1881 retval = ferror_internal (args, nargout); 1891 retval = ferror_internal (args, nargout);
1882 1892
1883 return retval; 1893 return retval;
1884 } 1894 }
1885 1895
1896 static Octave_object
1897 popen_internal (const Octave_object& args)
1898 {
1899 Octave_object retval;
1900
1901 if (! args(0).is_string ())
1902 {
1903 error ("popen: file name must be a string");
1904 return retval;
1905 }
1906
1907 char *name = args(0).string_value ();
1908
1909 Pix p = return_valid_file (name);
1910
1911 if (p)
1912 {
1913 file_info file = file_list (p);
1914
1915 retval(0) = (double) file.number ();
1916
1917 return retval;
1918 }
1919
1920 if (! args(1).is_string ())
1921 {
1922 error ("popen: file mode must be a string");
1923 return retval;
1924 }
1925
1926 char *mode = args(1).string_value ();
1927
1928 if (mode[1] || (mode[0] != 'w' && mode[0] != 'r'))
1929 {
1930 error ("popen: invalid mode, must be either \"r\" or \"w\".");
1931 return retval;
1932 }
1933
1934 struct stat buffer;
1935 if (stat (name, &buffer) == 0 && (buffer.st_mode & S_IFDIR) == S_IFDIR)
1936 {
1937 error ("popen: can't open directory");
1938 return retval;
1939 }
1940
1941 FILE *file_ptr = popen (name, mode);
1942
1943 if (! file_ptr)
1944 {
1945 error ("popen: unable to start process `%s'", name);
1946 return retval;
1947 }
1948
1949 int number = file_list.length () + 1;
1950
1951 file_info file (number, name, file_ptr, mode);
1952 file_list.append (file);
1953
1954 retval(0) = (double) number;
1955
1956 return retval;
1957 }
1958
1959 DEFUN ("popen", Fpopen, Spopen, 2, 1,
1960 "FILENUM = popen (FILENAME, MODE)\n\
1961 \n\
1962 start a process and create a pipe. Valid values for mode are:\n\
1963 \n\
1964 \"r\" : connect stdout of process to pipe\n\
1965 \"w\" : connect stdin of process to pipe")
1966 {
1967 Octave_object retval;
1968
1969 int nargin = args.length ();
1970
1971 if (nargin != 2)
1972 print_usage ("popen");
1973 else
1974 retval = popen_internal (args);
1975
1976 return retval;
1977 }
1978
1979 static Octave_object
1980 pclose_internal (const Octave_object& args)
1981 {
1982 Octave_object retval;
1983
1984 Pix p = return_valid_file (args(0));
1985
1986 if (! p)
1987 return retval;
1988
1989 file_info file = file_list (p);
1990
1991 if (file.number () < 3)
1992 {
1993 warning ("pclose: can't close stdin, stdout, or stderr!");
1994 return retval;
1995 }
1996
1997 int success = pclose (file.fptr ());
1998 file_list.del (p);
1999
2000 if (success == 0)
2001 retval(0) = 1.0; // succeeded
2002 else
2003 {
2004 error ("pclose: error on closing file");
2005 retval(0) = 0.0; // failed
2006 }
2007
2008 return retval;
2009 }
2010
2011 DEFUN ("pclose", Fpclose, Spclose, 1, 1,
2012 "pclose (FILENAME or FILENUM)\n\
2013 \n\
2014 Close a pipe and terminate the associated process")
2015 {
2016 Octave_object retval;
2017
2018 int nargin = args.length ();
2019
2020 if (nargin != 1)
2021 print_usage ("pclose");
2022 else
2023 retval = pclose_internal (args);
2024
2025 return retval;
2026 }
2027
2028 static Octave_object
2029 execute_internal (const Octave_object& args, int nargout)
2030 {
2031 Octave_object retval (3, tree_constant (-1.0));
2032
2033 pid_t pid = 0;
2034 int stdin_pipe[2];
2035 int stdout_pipe[2];
2036 FILE *stdin_file;
2037 FILE *stdout_file;
2038 int new_stdin;
2039 int new_stdout;
2040
2041 if (! args(0).is_string ())
2042 {
2043 error ("execute: file name must be a string");
2044 return retval;
2045 }
2046
2047 char *name = args(0).string_value ();
2048
2049 if (pipe (stdin_pipe) || pipe (stdout_pipe))
2050 {
2051 error ("execute: pipe creation failed");
2052 return retval;
2053 }
2054
2055 pid = fork ();
2056
2057 if (pid < (pid_t) 0)
2058 {
2059 error ("execute: fork failed - can't create child process");
2060 return retval;
2061 }
2062
2063 if (pid == (pid_t) 0)
2064 {
2065 close (stdin_pipe[1]);
2066 close (stdout_pipe[0]);
2067
2068 dup2 (stdin_pipe[0], STDIN_FILENO);
2069 close (stdin_pipe[0]);
2070
2071 dup2 (stdout_pipe[1], STDOUT_FILENO);
2072 close (stdout_pipe[1]);
2073
2074 if (execlp (name, name, 0) == -1)
2075 error ("execute: unable to start process `%s'", name);
2076
2077 exit (0);
2078 return 0.0;
2079 }
2080 else
2081 {
2082 close (stdin_pipe[0]);
2083 close (stdout_pipe[1]);
2084
2085 stdout_file = fdopen (stdout_pipe[0], "r");
2086 stdin_file = fdopen (stdin_pipe[1], "w");
2087
2088 if (fcntl (fileno (stdout_file), F_SETFL, O_NONBLOCK) < 0)
2089 {
2090 error ("execute: error setting file mode");
2091 return retval;
2092 }
2093
2094 new_stdin = file_list.length () + 1;
2095 new_stdout = new_stdin + 1;
2096
2097 file_info new_stdin_file_ptr (new_stdin, name, stdin_file, "w");
2098 file_info new_stdout_file_ptr (new_stdout, name, stdout_file, "r");
2099
2100 file_list.append (new_stdin_file_ptr);
2101 file_list.append (new_stdout_file_ptr);
2102 }
2103
2104 retval(2) = (double) pid;
2105 retval(1) = (double) new_stdout;
2106 retval(0) = (double) new_stdin;
2107
2108 return retval;
2109 }
2110
2111 DEFUN ("execute", Fexecute, Sexecute, 1, 3,
2112 "[STDIN, STDOUT, PID] = execute (COMMAND)\n\
2113 \n\
2114 Start a program and redirect its stdin to STDIN and its stdout to STDOUT")
2115 {
2116 Octave_object retval;
2117
2118 int nargin = args.length ();
2119
2120 if (nargin != 1)
2121 print_usage ("execute");
2122 else
2123 retval = execute_internal (args, nargout);
2124
2125 return retval;
2126 }
2127
2128 static Octave_object
2129 sync_system_internal (const Octave_object& args)
2130 {
2131 Octave_object retval (1, tree_constant (-1.0));
2132
2133 if (! args(0).is_string ())
2134 {
2135 error ("sync_system: file name must be a string");
2136 return retval;
2137 }
2138
2139 char *name = args(0).string_value ();
2140
2141 retval (0) = (double) system (name);
2142 return retval;
2143 }
2144
2145 DEFUN ("sync_system", Fsync_system, Ssync_system, 1, 1,
2146 "RETCODE = sync_system (FILENAME)\n\
2147 \n\
2148 Start a program and wait until it terminates")
2149 {
2150 Octave_object retval;
2151
2152 int nargin = args.length ();
2153
2154 if (nargin != 1)
2155 print_usage ("sync_system");
2156 else
2157 retval = sync_system_internal (args);
2158
2159 return retval;
2160 }
2161
2162 static Octave_object
2163 async_system_internal (const Octave_object& args)
2164 {
2165 Octave_object retval (1, tree_constant (-1.0));
2166 pid_t pid;
2167
2168 if (! args(0).is_string ())
2169 {
2170 error ("async_system: file name must be a string");
2171 return retval;
2172 }
2173
2174 char *name = args(0).string_value ();
2175
2176 pid = fork ();
2177
2178 if (pid < 0)
2179 {
2180 error ("async_system: fork failed -- can't create child process");
2181 return retval;
2182 }
2183
2184 if (pid == 0)
2185 {
2186 system (name);
2187 exit (0);
2188 retval (0) = 0.0;
2189 return retval;
2190 }
2191 else
2192 {
2193 retval (0) = (double) pid;
2194 return retval;
2195 }
2196 }
2197
2198 DEFUN ("async_system", Fasync_system, Sasync_system, 1, 1,
2199 "PID = async_system (FILENAME)\n\
2200 \n\
2201 Create a new process and start FILENAME")
2202 {
2203 Octave_object retval;
2204
2205 int nargin = args.length ();
2206
2207 if (nargin != 1)
2208 print_usage ("async_system");
2209 else
2210 retval = async_system_internal (args);
2211
2212 return retval;
2213 }
2214
2215 static Octave_object
2216 waitpid_internal (const Octave_object& args)
2217 {
2218 Octave_object retval (1, tree_constant (-1.0));
2219
2220 double pid_num = args(0).double_value ();
2221
2222 if (! error_state)
2223 {
2224 if (D_NINT (pid_num) != pid_num)
2225 error ("waitpid: PID must be an integer value");
2226 else
2227 {
2228 pid_t pid = (pid_t) pid_num;
2229
2230 int options = 0;
2231
2232 if (args.length () == 2)
2233 {
2234 double options_num = args(1).double_value ();
2235
2236 if (! error_state)
2237 {
2238 if (D_NINT (options_num) != options_num)
2239 error ("waitpid: PID must be an integer value");
2240 else
2241 {
2242 options = NINT (options_num);
2243 if (options < 0 || options > 3)
2244 error ("waitpid: invalid OPTIONS value specified");
2245 }
2246 }
2247 }
2248
2249 if (! error_state)
2250 retval (0) = (double) waitpid (pid, 0, options);
2251 }
2252 }
2253
2254 return retval;
2255 }
2256
2257 DEFUN ("waitpid", Fwaitpid, Swaitpid, 1, 1,
2258 "STATUS = waitpid (PID, OPTIONS)\n\
2259 \n\
2260 wait for process PID to terminate\n\
2261 \n\
2262 PID can be:\n\
2263 \n\
2264 -1 : wait for any child process\n\
2265 0 : wait for any child process whose process group ID is equal to\n\
2266 that of the Octave interpreter process.\n\
2267 > 0 : wait for termination of the child process with ID PID.\n\
2268 \n\
2269 OPTIONS is:\n\
2270 \n\
2271 0 : wait until signal is received or a child process exits (this\n\
2272 is the default if the OPTIONS argument is missing) \n\
2273 1 : do not hang if status is not immediately available\n\
2274 2 : report the status of any child processes that are\n\
2275 stopped, and whose status has not yet been reported\n\
2276 since they stopped\n\
2277 3 : implies both 1 and 2\n\
2278 \n\
2279 STATUS is:\n\
2280 \n\
2281 -1 : if an error occured\n\
2282 > 0 : the process ID of the child process that exited")
2283 {
2284 Octave_object retval;
2285
2286 int nargin = args.length ();
2287
2288 if (nargin == 1 || nargin == 2)
2289 retval = waitpid_internal (args);
2290 else
2291 print_usage ("waitpid");
2292
2293 return retval;
2294 }
2295
2296 static Octave_object
2297 mkfifo_internal (const Octave_object& args)
2298 {
2299 Octave_object retval (1, tree_constant (-1.0));
2300
2301 if (! args(0).is_string ())
2302 {
2303 error ("mkfifo: file name must be a string");
2304 return retval;
2305 }
2306
2307 char *name = args(0).string_value ();
2308
2309 if (! args(1).is_scalar_type ())
2310 {
2311 error ("mkfifo: MODE must be an integer");
2312 return retval;
2313 }
2314
2315 long mode = (long) args(1).double_value ();
2316
2317 retval (0) = (double) mkfifo (name, mode);
2318
2319 return retval;
2320 }
2321
2322 DEFUN ("mkfifo", Fmkfifo, Smkfifo, 2, 1,
2323 "STATUS = mkfifo (NAME, MODE)\n\
2324 \n\
2325 Create a FIFO special file named NAME with file mode MODE\n\
2326 \n\
2327 STATUS is:\n\
2328 \n\
2329 != 0 : if mkfifo failed\n\
2330 0 : if the FIFO special file could be created")
2331 {
2332 Octave_object retval;
2333
2334 int nargin = args.length ();
2335
2336 if (nargin != 2)
2337 print_usage ("mkfifo");
2338 else
2339 retval = mkfifo_internal (args);
2340
2341 return retval;
2342 }
2343
2344 static Octave_object
2345 unlink_internal (const Octave_object& args)
2346 {
2347 Octave_object retval;
2348
2349 if (! args(0).is_string ())
2350 {
2351 error ("unlink: file name must be a string");
2352 retval (0) = -1.0;
2353 return retval;
2354 }
2355
2356 char *name = args(0).string_value ();
2357
2358 retval (0) = (double) unlink (name);
2359
2360 return retval;
2361 }
2362
2363 DEFUN ("unlink", Funlink, Sunlink, 1, 1,
2364 "STATUS = unlink (NAME)\n\
2365 \n\
2366 Delete the file NAME\n\
2367 \n\
2368 STATUS is:\n\
2369 \n\
2370 != 0 : if unlink failed\n\
2371 0 : if the file could be successfully deleted")
2372 {
2373 Octave_object retval;
2374
2375 int nargin = args.length ();
2376
2377 if (nargin != 1)
2378 print_usage ("unlink");
2379 else
2380 retval = unlink_internal (args);
2381
2382 return retval;
2383 }
2384
1886 /* 2385 /*
1887 ;;; Local Variables: *** 2386 ;;; Local Variables: ***
1888 ;;; mode: C++ *** 2387 ;;; mode: C++ ***
1889 ;;; page-delimiter: "^/\\*" *** 2388 ;;; page-delimiter: "^/\\*" ***
1890 ;;; End: *** 2389 ;;; End: ***