fports.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741
  1. /* Copyright (C) 1995,1996,1997,1998,1999, 2000, 2002 Free Software Foundation, Inc.
  2. *
  3. * This program is free software; you can redistribute it and/or modify
  4. * it under the terms of the GNU General Public License as published by
  5. * the Free Software Foundation; either version 2, or (at your option)
  6. * any later version.
  7. *
  8. * This program 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
  11. * GNU General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU General Public License
  14. * along with this software; see the file COPYING. If not, write to
  15. * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
  16. * Boston, MA 02111-1307 USA
  17. *
  18. * As a special exception, the Free Software Foundation gives permission
  19. * for additional uses of the text contained in its release of GUILE.
  20. *
  21. * The exception is that, if you link the GUILE library with other files
  22. * to produce an executable, this does not by itself cause the
  23. * resulting executable to be covered by the GNU General Public License.
  24. * Your use of that executable is in no way restricted on account of
  25. * linking the GUILE library code into it.
  26. *
  27. * This exception does not however invalidate any other reasons why
  28. * the executable file might be covered by the GNU General Public License.
  29. *
  30. * This exception applies only to the code released by the
  31. * Free Software Foundation under the name GUILE. If you copy
  32. * code from other Free Software Foundation releases into a copy of
  33. * GUILE, as the General Public License permits, the exception does
  34. * not apply to the code that you add in this way. To avoid misleading
  35. * anyone as to the status of such modified files, you must delete
  36. * this exception notice from them.
  37. *
  38. * If you write modifications of your own for GUILE, it is your choice
  39. * whether to permit this exception to apply to your modifications.
  40. * If you do not wish that, delete this exception notice. */
  41. #include <stdio.h>
  42. #include <fcntl.h>
  43. #include "libguile/_scm.h"
  44. #include "libguile/strings.h"
  45. #include "libguile/validate.h"
  46. #include "libguile/fports.h"
  47. #ifdef HAVE_STRING_H
  48. #include <string.h>
  49. #endif
  50. #ifdef HAVE_UNISTD_H
  51. #include <unistd.h>
  52. #else
  53. scm_sizet fwrite ();
  54. #endif
  55. #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
  56. #include <sys/stat.h>
  57. #endif
  58. #include <errno.h>
  59. #include "libguile/iselect.h"
  60. /* default buffer size, used if the O/S won't supply a value. */
  61. static const int default_buffer_size = 1024;
  62. /* create FPORT buffer with specified sizes (or -1 to use default size or
  63. 0 for no buffer. */
  64. static void
  65. scm_fport_buffer_add (SCM port, int read_size, int write_size)
  66. {
  67. struct scm_fport *fp = SCM_FSTREAM (port);
  68. scm_port *pt = SCM_PTAB_ENTRY (port);
  69. char *s_scm_fport_buffer_add = "scm_fport_buffer_add";
  70. if (read_size == -1 || write_size == -1)
  71. {
  72. int default_size;
  73. #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
  74. struct stat st;
  75. default_size = (fstat (fp->fdes, &st) == -1) ? default_buffer_size
  76. : st.st_blksize;
  77. #else
  78. default_size = default_buffer_size;
  79. #endif
  80. if (read_size == -1)
  81. read_size = default_size;
  82. if (write_size == -1)
  83. write_size = default_size;
  84. }
  85. if (SCM_INPUT_PORT_P (port) && read_size > 0)
  86. {
  87. pt->read_buf = malloc (read_size);
  88. if (pt->read_buf == NULL)
  89. scm_memory_error (s_scm_fport_buffer_add);
  90. pt->read_pos = pt->read_end = pt->read_buf;
  91. pt->read_buf_size = read_size;
  92. }
  93. else
  94. {
  95. pt->read_pos = pt->read_buf = pt->read_end = &pt->shortbuf;
  96. pt->read_buf_size = 1;
  97. }
  98. if (SCM_OUTPUT_PORT_P (port) && write_size > 0)
  99. {
  100. pt->write_buf = malloc (write_size);
  101. if (pt->write_buf == NULL)
  102. scm_memory_error (s_scm_fport_buffer_add);
  103. pt->write_pos = pt->write_buf;
  104. pt->write_buf_size = write_size;
  105. }
  106. else
  107. {
  108. pt->write_buf = pt->write_pos = &pt->shortbuf;
  109. pt->write_buf_size = 1;
  110. }
  111. pt->write_end = pt->write_buf + pt->write_buf_size;
  112. if (read_size > 0 || write_size > 0)
  113. SCM_SET_CELL_WORD_0 (port, SCM_CELL_WORD_0 (port) & ~SCM_BUF0);
  114. else
  115. SCM_SET_CELL_WORD_0 (port, SCM_CELL_WORD_0 (port) | SCM_BUF0);
  116. }
  117. SCM_DEFINE (scm_setvbuf, "setvbuf", 2, 1, 0,
  118. (SCM port, SCM mode, SCM size),
  119. "Set the buffering mode for @var{port}. @var{mode} can be:\n"
  120. "@table @code\n"
  121. "@item _IONBF\n"
  122. "non-buffered\n"
  123. "@item _IOLBF\n"
  124. "line buffered\n"
  125. "@item _IOFBF\n"
  126. "block buffered, using a newly allocated buffer of @var{size} bytes.\n"
  127. "If @var{size} is omitted, a default size will be used.\n"
  128. "@end table")
  129. #define FUNC_NAME s_scm_setvbuf
  130. {
  131. int cmode, csize;
  132. scm_port *pt;
  133. port = SCM_COERCE_OUTPORT (port);
  134. SCM_VALIDATE_OPFPORT (1,port);
  135. SCM_VALIDATE_INUM_COPY (2,mode,cmode);
  136. if (cmode != _IONBF && cmode != _IOFBF && cmode != _IOLBF)
  137. scm_out_of_range (FUNC_NAME, mode);
  138. if (cmode == _IOLBF)
  139. {
  140. SCM_SET_CELL_WORD_0 (port, SCM_CELL_WORD_0 (port) | SCM_BUFLINE);
  141. cmode = _IOFBF;
  142. }
  143. else
  144. {
  145. SCM_SET_CELL_WORD_0 (port, SCM_CELL_WORD_0 (port) ^ SCM_BUFLINE);
  146. }
  147. if (SCM_UNBNDP (size))
  148. {
  149. if (cmode == _IOFBF)
  150. csize = -1;
  151. else
  152. csize = 0;
  153. }
  154. else
  155. {
  156. SCM_VALIDATE_INUM_COPY (3,size,csize);
  157. if (csize < 0 || (cmode == _IONBF && csize > 0))
  158. scm_out_of_range (FUNC_NAME, size);
  159. }
  160. pt = SCM_PTAB_ENTRY (port);
  161. /* silently discards buffered chars. */
  162. if (pt->read_buf != &pt->shortbuf)
  163. free (pt->read_buf);
  164. if (pt->write_buf != &pt->shortbuf)
  165. free (pt->write_buf);
  166. scm_fport_buffer_add (port, csize, csize);
  167. return SCM_UNSPECIFIED;
  168. }
  169. #undef FUNC_NAME
  170. /* Move ports with the specified file descriptor to new descriptors,
  171. * reseting the revealed count to 0.
  172. */
  173. void
  174. scm_evict_ports (int fd)
  175. {
  176. int i;
  177. for (i = 0; i < scm_port_table_size; i++)
  178. {
  179. SCM port = scm_port_table[i]->port;
  180. if (SCM_FPORTP (port))
  181. {
  182. struct scm_fport *fp = SCM_FSTREAM (port);
  183. if (fp->fdes == fd)
  184. {
  185. fp->fdes = dup (fd);
  186. if (fp->fdes == -1)
  187. scm_syserror ("scm_evict_ports");
  188. scm_set_port_revealed_x (port, SCM_MAKINUM (0));
  189. }
  190. }
  191. }
  192. }
  193. /* scm_open_file
  194. * Return a new port open on a given file.
  195. *
  196. * The mode string must match the pattern: [rwa+]** which
  197. * is interpreted in the usual unix way.
  198. *
  199. * Return the new port.
  200. */
  201. SCM_DEFINE (scm_open_file, "open-file", 2, 0, 0,
  202. (SCM filename, SCM modes),
  203. "Open the file whose name is @var{string}, and return a port\n"
  204. "representing that file. The attributes of the port are\n"
  205. "determined by the @var{mode} string. The way in \n"
  206. "which this is interpreted is similar to C stdio:\n\n"
  207. "The first character must be one of the following:\n\n"
  208. "@table @samp\n"
  209. "@item r\n"
  210. "Open an existing file for input.\n"
  211. "@item w\n"
  212. "Open a file for output, creating it if it doesn't already exist\n"
  213. "or removing its contents if it does.\n"
  214. "@item a\n"
  215. "Open a file for output, creating it if it doesn't already exist.\n"
  216. "All writes to the port will go to the end of the file.\n"
  217. "The \"append mode\" can be turned off while the port is in use\n"
  218. "@pxref{Ports and File Descriptors, fcntl}\n"
  219. "@end table\n\n"
  220. "The following additional characters can be appended:\n\n"
  221. "@table @samp\n"
  222. "@item +\n"
  223. "Open the port for both input and output. E.g., @code{r+}: open\n"
  224. "an existing file for both input and output.\n"
  225. "@item 0\n"
  226. "Create an \"unbuffered\" port. In this case input and output operations\n"
  227. "are passed directly to the underlying port implementation without\n"
  228. "additional buffering. This is likely to slow down I/O operations.\n"
  229. "The buffering mode can be changed while a port is in use\n"
  230. "@pxref{Ports and File Descriptors, setvbuf}\n"
  231. "@item l\n"
  232. "Add line-buffering to the port. The port output buffer will be\n"
  233. "automatically flushed whenever a newline character is written.\n"
  234. "@end table\n\n"
  235. "In theory we could create read/write ports which were buffered in one\n"
  236. "direction only. However this isn't included in the current interfaces.\n\n"
  237. "If a file cannot be opened with the access requested,\n"
  238. "@code{open-file} throws an exception.")
  239. #define FUNC_NAME s_scm_open_file
  240. {
  241. SCM port;
  242. int fdes;
  243. int flags = 0;
  244. char *file;
  245. char *mode;
  246. char *ptr;
  247. SCM_VALIDATE_ROSTRING (1,filename);
  248. SCM_VALIDATE_ROSTRING (2,modes);
  249. if (SCM_SUBSTRP (filename))
  250. filename = scm_makfromstr (SCM_ROCHARS (filename), SCM_ROLENGTH (filename), 0);
  251. if (SCM_SUBSTRP (modes))
  252. modes = scm_makfromstr (SCM_ROCHARS (modes), SCM_ROLENGTH (modes), 0);
  253. file = SCM_ROCHARS (filename);
  254. mode = SCM_ROCHARS (modes);
  255. switch (*mode)
  256. {
  257. case 'r':
  258. flags |= O_RDONLY;
  259. break;
  260. case 'w':
  261. flags |= O_WRONLY | O_CREAT | O_TRUNC;
  262. break;
  263. case 'a':
  264. flags |= O_WRONLY | O_CREAT | O_APPEND;
  265. break;
  266. default:
  267. scm_out_of_range (FUNC_NAME, modes);
  268. }
  269. ptr = mode + 1;
  270. while (*ptr != '\0')
  271. {
  272. switch (*ptr)
  273. {
  274. case '+':
  275. flags = (flags & ~(O_RDONLY | O_WRONLY)) | O_RDWR;
  276. break;
  277. case '0': /* unbuffered: handled later. */
  278. case 'b': /* 'binary' mode: ignored. */
  279. case 'l': /* line buffered: handled during output. */
  280. break;
  281. default:
  282. scm_out_of_range (FUNC_NAME, modes);
  283. }
  284. ptr++;
  285. }
  286. SCM_SYSCALL (fdes = open (file, flags, 0666));
  287. if (fdes == -1)
  288. {
  289. int en = errno;
  290. SCM_SYSERROR_MSG ("~A: ~S",
  291. scm_cons (scm_makfrom0str (strerror (en)),
  292. scm_cons (filename, SCM_EOL)), en);
  293. }
  294. port = scm_fdes_to_port (fdes, mode, filename);
  295. return port;
  296. }
  297. #undef FUNC_NAME
  298. /* Building Guile ports from a file descriptor. */
  299. /* Build a Scheme port from an open file descriptor `fdes'.
  300. MODE indicates whether FILE is open for reading or writing; it uses
  301. the same notation as open-file's second argument.
  302. NAME is a string to be used as the port's filename.
  303. */
  304. SCM
  305. scm_fdes_to_port (int fdes, char *mode, SCM name)
  306. #define FUNC_NAME "scm_fdes_to_port"
  307. {
  308. long mode_bits = scm_mode_bits (mode);
  309. SCM port;
  310. scm_port *pt;
  311. int flags;
  312. /* test that fdes is valid. */
  313. flags = fcntl (fdes, F_GETFL, 0);
  314. if (flags == -1)
  315. SCM_SYSERROR;
  316. flags &= O_ACCMODE;
  317. if (flags != O_RDWR
  318. && ((flags != O_WRONLY && (mode_bits & SCM_WRTNG))
  319. || (flags != O_RDONLY && (mode_bits & SCM_RDNG))))
  320. {
  321. SCM_MISC_ERROR ("requested file mode not available on fdes", SCM_EOL);
  322. }
  323. SCM_NEWCELL (port);
  324. SCM_DEFER_INTS;
  325. pt = scm_add_to_port_table (port);
  326. SCM_SETPTAB_ENTRY (port, pt);
  327. SCM_SET_CELL_TYPE (port, (scm_tc16_fport | mode_bits));
  328. {
  329. struct scm_fport *fp
  330. = (struct scm_fport *) malloc (sizeof (struct scm_fport));
  331. if (fp == NULL)
  332. SCM_MEMORY_ERROR;
  333. fp->fdes = fdes;
  334. pt->rw_random = SCM_FDES_RANDOM_P (fdes);
  335. SCM_SETSTREAM (port, fp);
  336. if (mode_bits & SCM_BUF0)
  337. scm_fport_buffer_add (port, 0, 0);
  338. else
  339. scm_fport_buffer_add (port, -1, -1);
  340. }
  341. SCM_PTAB_ENTRY (port)->file_name = name;
  342. SCM_ALLOW_INTS;
  343. return port;
  344. }
  345. #undef FUNC_NAME
  346. /* Return a lower bound on the number of bytes available for input. */
  347. static int
  348. fport_input_waiting (SCM port)
  349. {
  350. int fdes = SCM_FSTREAM (port)->fdes;
  351. #ifdef HAVE_SELECT
  352. struct timeval timeout;
  353. SELECT_TYPE read_set;
  354. SELECT_TYPE write_set;
  355. SELECT_TYPE except_set;
  356. FD_ZERO (&read_set);
  357. FD_ZERO (&write_set);
  358. FD_ZERO (&except_set);
  359. FD_SET (fdes, &read_set);
  360. timeout.tv_sec = 0;
  361. timeout.tv_usec = 0;
  362. if (select (SELECT_SET_SIZE,
  363. &read_set, &write_set, &except_set, &timeout)
  364. < 0)
  365. scm_syserror ("fport_input_waiting");
  366. return FD_ISSET (fdes, &read_set) ? 1 : 0;
  367. #elif defined (FIONREAD)
  368. int remir;
  369. ioctl(fdes, FIONREAD, &remir);
  370. return remir;
  371. #else
  372. scm_misc_error ("fport_input_waiting",
  373. "Not fully implemented on this platform",
  374. SCM_EOL);
  375. #endif
  376. }
  377. static int
  378. prinfport (SCM exp,SCM port,scm_print_state *pstate)
  379. {
  380. scm_puts ("#<", port);
  381. scm_print_port_mode (exp, port);
  382. if (SCM_OPFPORTP (exp))
  383. {
  384. int fdes;
  385. SCM name = SCM_PTAB_ENTRY (exp)->file_name;
  386. scm_puts (SCM_ROSTRINGP (name)
  387. ? SCM_ROCHARS (name)
  388. : SCM_PTOBNAME (SCM_PTOBNUM (exp)),
  389. port);
  390. scm_putc (' ', port);
  391. fdes = (SCM_FSTREAM (exp))->fdes;
  392. if (isatty (fdes))
  393. scm_puts (ttyname (fdes), port);
  394. else
  395. scm_intprint (fdes, 10, port);
  396. }
  397. else
  398. {
  399. scm_puts (SCM_PTOBNAME (SCM_PTOBNUM (exp)), port);
  400. scm_putc (' ', port);
  401. scm_intprint (SCM_UNPACK (SCM_CDR (exp)), 16, port);
  402. }
  403. scm_putc ('>', port);
  404. return 1;
  405. }
  406. #ifdef GUILE_ISELECT
  407. /* thread-local block for input on fport's fdes. */
  408. static void
  409. fport_wait_for_input (SCM port)
  410. {
  411. int fdes = SCM_FSTREAM (port)->fdes;
  412. if (!fport_input_waiting (port))
  413. {
  414. int n;
  415. SELECT_TYPE readfds;
  416. int flags = fcntl (fdes, F_GETFL);
  417. if (flags == -1)
  418. scm_syserror ("scm_fdes_wait_for_input");
  419. if (!(flags & O_NONBLOCK))
  420. do
  421. {
  422. FD_ZERO (&readfds);
  423. FD_SET (fdes, &readfds);
  424. n = scm_internal_select (fdes + 1, &readfds, NULL, NULL, NULL);
  425. }
  426. while (n == -1 && errno == EINTR);
  427. }
  428. }
  429. #endif
  430. static void fport_flush (SCM port);
  431. /* fill a port's read-buffer with a single read.
  432. returns the first char and moves the read_pos pointer past it.
  433. or returns EOF if end of file. */
  434. static int
  435. fport_fill_input (SCM port)
  436. {
  437. int count;
  438. scm_port *pt = SCM_PTAB_ENTRY (port);
  439. struct scm_fport *fp = SCM_FSTREAM (port);
  440. #ifdef GUILE_ISELECT
  441. fport_wait_for_input (port);
  442. #endif
  443. SCM_SYSCALL (count = read (fp->fdes, pt->read_buf, pt->read_buf_size));
  444. if (count == -1)
  445. scm_syserror ("fport_fill_input");
  446. if (count == 0)
  447. return EOF;
  448. else
  449. {
  450. pt->read_pos = pt->read_buf;
  451. pt->read_end = pt->read_buf + count;
  452. return *pt->read_buf;
  453. }
  454. }
  455. static off_t
  456. fport_seek (SCM port, off_t offset, int whence)
  457. {
  458. scm_port *pt = SCM_PTAB_ENTRY (port);
  459. struct scm_fport *fp = SCM_FSTREAM (port);
  460. off_t rv;
  461. off_t result;
  462. if (pt->rw_active == SCM_PORT_WRITE)
  463. {
  464. if (offset != 0 || whence != SEEK_CUR)
  465. {
  466. fport_flush (port);
  467. result = rv = lseek (fp->fdes, offset, whence);
  468. }
  469. else
  470. {
  471. /* read current position without disturbing the buffer. */
  472. rv = lseek (fp->fdes, offset, whence);
  473. result = rv + (pt->write_pos - pt->write_buf);
  474. }
  475. }
  476. else if (pt->rw_active == SCM_PORT_READ)
  477. {
  478. if (offset != 0 || whence != SEEK_CUR)
  479. {
  480. /* could expand to avoid a second seek. */
  481. scm_end_input (port);
  482. result = rv = lseek (fp->fdes, offset, whence);
  483. }
  484. else
  485. {
  486. /* read current position without disturbing the buffer
  487. (particularly the unread-char buffer). */
  488. rv = lseek (fp->fdes, offset, whence);
  489. result = rv - (pt->read_end - pt->read_pos);
  490. if (pt->read_buf == pt->putback_buf)
  491. result -= pt->saved_read_end - pt->saved_read_pos;
  492. }
  493. }
  494. else /* SCM_PORT_NEITHER */
  495. {
  496. result = rv = lseek (fp->fdes, offset, whence);
  497. }
  498. if (rv == -1)
  499. scm_syserror ("fport_seek");
  500. return result;
  501. }
  502. static void
  503. fport_truncate (SCM port, off_t length)
  504. {
  505. struct scm_fport *fp = SCM_FSTREAM (port);
  506. if (ftruncate (fp->fdes, length) == -1)
  507. scm_syserror ("ftruncate");
  508. }
  509. static void
  510. fport_write (SCM port, const void *data, size_t size)
  511. {
  512. scm_port *pt = SCM_PTAB_ENTRY (port);
  513. if (pt->write_buf == &pt->shortbuf)
  514. {
  515. /* "unbuffered" port. */
  516. int fdes = SCM_FSTREAM (port)->fdes;
  517. if (write (fdes, data, size) == -1)
  518. scm_syserror ("fport_write");
  519. }
  520. else
  521. {
  522. const char *input = (char *) data;
  523. size_t remaining = size;
  524. while (remaining > 0)
  525. {
  526. int space = pt->write_end - pt->write_pos;
  527. int write_len = (remaining > space) ? space : remaining;
  528. memcpy (pt->write_pos, input, write_len);
  529. pt->write_pos += write_len;
  530. remaining -= write_len;
  531. input += write_len;
  532. if (write_len == space)
  533. fport_flush (port);
  534. }
  535. /* handle line buffering. */
  536. if ((SCM_CELL_WORD_0 (port) & SCM_BUFLINE) && memchr (data, '\n', size))
  537. fport_flush (port);
  538. }
  539. }
  540. /* becomes 1 when process is exiting: normal exception handling won't
  541. work by this time. */
  542. extern int terminating;
  543. static void
  544. fport_flush (SCM port)
  545. {
  546. scm_port *pt = SCM_PTAB_ENTRY (port);
  547. struct scm_fport *fp = SCM_FSTREAM (port);
  548. unsigned char *ptr = pt->write_buf;
  549. int init_size = pt->write_pos - pt->write_buf;
  550. int remaining = init_size;
  551. while (remaining > 0)
  552. {
  553. int count;
  554. SCM_SYSCALL (count = write (fp->fdes, ptr, remaining));
  555. if (count < 0)
  556. {
  557. /* error. assume nothing was written this call, but
  558. fix up the buffer for any previous successful writes. */
  559. int done = init_size - remaining;
  560. if (done > 0)
  561. {
  562. int i;
  563. for (i = 0; i < remaining; i++)
  564. {
  565. *(pt->write_buf + i) = *(pt->write_buf + done + i);
  566. }
  567. pt->write_pos = pt->write_buf + remaining;
  568. }
  569. if (!terminating)
  570. scm_syserror ("fport_flush");
  571. else
  572. {
  573. const char *msg = "Error: could not flush file-descriptor ";
  574. char buf[11];
  575. write (2, msg, strlen (msg));
  576. sprintf (buf, "%d\n", fp->fdes);
  577. write (2, buf, strlen (buf));
  578. count = remaining;
  579. }
  580. }
  581. ptr += count;
  582. remaining -= count;
  583. }
  584. pt->write_pos = pt->write_buf;
  585. pt->rw_active = SCM_PORT_NEITHER;
  586. }
  587. /* clear the read buffer and adjust the file position for unread bytes. */
  588. static void
  589. fport_end_input (SCM port, int offset)
  590. {
  591. struct scm_fport *fp = SCM_FSTREAM (port);
  592. scm_port *pt = SCM_PTAB_ENTRY (port);
  593. offset += pt->read_end - pt->read_pos;
  594. if (offset > 0)
  595. {
  596. pt->read_pos = pt->read_end;
  597. /* will throw error if unread-char used at beginning of file
  598. then attempting to write. seems correct. */
  599. if (lseek (fp->fdes, -offset, SEEK_CUR) == -1)
  600. scm_syserror ("fport_end_input");
  601. }
  602. pt->rw_active = SCM_PORT_NEITHER;
  603. }
  604. static int
  605. fport_close (SCM port)
  606. {
  607. struct scm_fport *fp = SCM_FSTREAM (port);
  608. scm_port *pt = SCM_PTAB_ENTRY (port);
  609. int rv;
  610. fport_flush (port);
  611. SCM_SYSCALL (rv = close (fp->fdes));
  612. if (rv == -1 && errno != EBADF)
  613. scm_syserror ("fport_close");
  614. if (pt->read_buf == pt->putback_buf)
  615. pt->read_buf = pt->saved_read_buf;
  616. if (pt->read_buf != &pt->shortbuf)
  617. free (pt->read_buf);
  618. if (pt->write_buf != &pt->shortbuf)
  619. free (pt->write_buf);
  620. free ((char *) fp);
  621. return rv;
  622. }
  623. static scm_sizet
  624. fport_free (SCM port)
  625. {
  626. fport_close (port);
  627. return 0;
  628. }
  629. void scm_make_fptob (void); /* Called from ports.c */
  630. void
  631. scm_make_fptob ()
  632. {
  633. long tc = scm_make_port_type ("file", fport_fill_input, fport_write);
  634. scm_set_port_free (tc, fport_free);
  635. scm_set_port_print (tc, prinfport);
  636. scm_set_port_flush (tc, fport_flush);
  637. scm_set_port_end_input (tc, fport_end_input);
  638. scm_set_port_close (tc, fport_close);
  639. scm_set_port_seek (tc, fport_seek);
  640. scm_set_port_truncate (tc, fport_truncate);
  641. scm_set_port_input_waiting (tc, fport_input_waiting);
  642. }
  643. void
  644. scm_init_fports ()
  645. {
  646. #include "libguile/fports.x"
  647. scm_sysintern ("_IOFBF", SCM_MAKINUM (_IOFBF));
  648. scm_sysintern ("_IOLBF", SCM_MAKINUM (_IOLBF));
  649. scm_sysintern ("_IONBF", SCM_MAKINUM (_IONBF));
  650. }
  651. /*
  652. Local Variables:
  653. c-file-style: "gnu"
  654. End:
  655. */