Mercurial > octave
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: *** |