Advertisement
Guest User

Untitled

a guest
Sep 14th, 2011
103
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 160.93 KB | None | 0 0
  1. clients/Instantbird/giochannel.c | 2316 ++++++++++++++++++++++++++++++++
  2. clients/Instantbird/giounix.c | 598 ++++++++
  3. clients/Instantbird/giowin32.c | 2129 +++++++++++++++++++++++++++++
  4. clients/Instantbird/gstrcmp0.c | 22 +
  5. clients/Instantbird/linux/Makefile.in | 62 +
  6. clients/Instantbird/macosx/Makefile.in | 63 +
  7. clients/Instantbird/win32/Makefile.in | 63 +
  8. msn.c | 4 +
  9. 8 files changed, 5257 insertions(+), 0 deletions(-)
  10. create mode 100755 clients/Instantbird/giochannel.c
  11. create mode 100755 clients/Instantbird/giounix.c
  12. create mode 100755 clients/Instantbird/giowin32.c
  13. create mode 100755 clients/Instantbird/gstrcmp0.c
  14. create mode 100755 clients/Instantbird/linux/Makefile.in
  15. create mode 100755 clients/Instantbird/macosx/Makefile.in
  16. create mode 100755 clients/Instantbird/win32/Makefile.in
  17.  
  18. diff --git a/clients/Instantbird/giochannel.c b/clients/Instantbird/giochannel.c
  19. new file mode 100755
  20. index 0000000..b067736
  21. --- /dev/null
  22. +++ b/clients/Instantbird/giochannel.c
  23. @@ -0,0 +1,2316 @@
  24. +/* GLIB - Library of useful routines for C programming
  25. + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
  26. + *
  27. + * giochannel.c: IO Channel abstraction
  28. + * Copyright 1998 Owen Taylor
  29. + *
  30. + * This library is free software; you can redistribute it and/or
  31. + * modify it under the terms of the GNU Lesser General Public
  32. + * License as published by the Free Software Foundation; either
  33. + * version 2 of the License, or (at your option) any later version.
  34. + *
  35. + * This library is distributed in the hope that it will be useful,
  36. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  37. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  38. + * Lesser General Public License for more details.
  39. + *
  40. + * You should have received a copy of the GNU Lesser General Public
  41. + * License along with this library; if not, write to the
  42. + * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  43. + * Boston, MA 02111-1307, USA.
  44. + */
  45. +
  46. +/*
  47. + * Modified by the GLib Team and others 1997-2000. See the AUTHORS
  48. + * file for a list of people on the GLib Team. See the ChangeLog
  49. + * files for a list of changes. These files are distributed with
  50. + * GLib at ftp://ftp.gtk.org/pub/gtk/.
  51. + */
  52. +
  53. +/*
  54. + * MT safe
  55. + */
  56. +
  57. +#include "config.h"
  58. +
  59. +#include <string.h>
  60. +#include <errno.h>
  61. +#ifndef EILSEQ
  62. +# define EILSEQ 42
  63. +#endif
  64. +
  65. +#ifdef HAVE_UNISTD_H
  66. +#include <unistd.h>
  67. +#endif
  68. +
  69. +#undef G_DISABLE_DEPRECATED
  70. +
  71. +#include "glib.h"
  72. +
  73. +#include "giochannel.h"
  74. +
  75. +#include "glibintl.h"
  76. +
  77. +#include "galias.h"
  78. +
  79. +#define G_IO_NICE_BUF_SIZE 1024
  80. +
  81. +/* This needs to be as wide as the largest character in any possible encoding */
  82. +#define MAX_CHAR_SIZE 10
  83. +
  84. +/* Some simplifying macros, which reduce the need to worry whether the
  85. + * buffers have been allocated. These also make USE_BUF () an lvalue,
  86. + * which is used in g_io_channel_read_to_end ().
  87. + */
  88. +#define USE_BUF(channel) ((channel)->encoding ? (channel)->encoded_read_buf \
  89. + : (channel)->read_buf)
  90. +#define BUF_LEN(string) ((string) ? (string)->len : 0)
  91. +
  92. +static GIOError g_io_error_get_from_g_error (GIOStatus status,
  93. + GError *err);
  94. +static void g_io_channel_purge (GIOChannel *channel);
  95. +static GIOStatus g_io_channel_fill_buffer (GIOChannel *channel,
  96. + GError **err);
  97. +static GIOStatus g_io_channel_read_line_backend (GIOChannel *channel,
  98. + gsize *length,
  99. + gsize *terminator_pos,
  100. + GError **error);
  101. +
  102. +void
  103. +g_io_channel_init (GIOChannel *channel)
  104. +{
  105. + channel->ref_count = 1;
  106. + channel->encoding = g_strdup ("UTF-8");
  107. + channel->line_term = NULL;
  108. + channel->line_term_len = 0;
  109. + channel->buf_size = G_IO_NICE_BUF_SIZE;
  110. + channel->read_cd = (GIConv) -1;
  111. + channel->write_cd = (GIConv) -1;
  112. + channel->read_buf = NULL; /* Lazy allocate buffers */
  113. + channel->encoded_read_buf = NULL;
  114. + channel->write_buf = NULL;
  115. + channel->partial_write_buf[0] = '\0';
  116. + channel->use_buffer = TRUE;
  117. + channel->do_encode = FALSE;
  118. + channel->close_on_unref = FALSE;
  119. +}
  120. +
  121. +GIOChannel *
  122. +g_io_channel_ref (GIOChannel *channel)
  123. +{
  124. + g_return_val_if_fail (channel != NULL, NULL);
  125. +
  126. + g_atomic_int_inc (&channel->ref_count);
  127. +
  128. + return channel;
  129. +}
  130. +
  131. +void
  132. +g_io_channel_unref (GIOChannel *channel)
  133. +{
  134. + gboolean is_zero;
  135. +
  136. + g_return_if_fail (channel != NULL);
  137. +
  138. + is_zero = g_atomic_int_dec_and_test (&channel->ref_count);
  139. +
  140. + if (G_UNLIKELY (is_zero))
  141. + {
  142. + if (channel->close_on_unref)
  143. + g_io_channel_shutdown (channel, TRUE, NULL);
  144. + else
  145. + g_io_channel_purge (channel);
  146. + g_free (channel->encoding);
  147. + if (channel->read_cd != (GIConv) -1)
  148. + g_iconv_close (channel->read_cd);
  149. + if (channel->write_cd != (GIConv) -1)
  150. + g_iconv_close (channel->write_cd);
  151. + g_free (channel->line_term);
  152. + if (channel->read_buf)
  153. + g_string_free (channel->read_buf, TRUE);
  154. + if (channel->write_buf)
  155. + g_string_free (channel->write_buf, TRUE);
  156. + if (channel->encoded_read_buf)
  157. + g_string_free (channel->encoded_read_buf, TRUE);
  158. + channel->funcs->io_free (channel);
  159. + }
  160. +}
  161. +
  162. +static GIOError
  163. +g_io_error_get_from_g_error (GIOStatus status,
  164. + GError *err)
  165. +{
  166. + switch (status)
  167. + {
  168. + case G_IO_STATUS_NORMAL:
  169. + case G_IO_STATUS_EOF:
  170. + return G_IO_ERROR_NONE;
  171. + case G_IO_STATUS_AGAIN:
  172. + return G_IO_ERROR_AGAIN;
  173. + case G_IO_STATUS_ERROR:
  174. + g_return_val_if_fail (err != NULL, G_IO_ERROR_UNKNOWN);
  175. +
  176. + if (err->domain != G_IO_CHANNEL_ERROR)
  177. + return G_IO_ERROR_UNKNOWN;
  178. + switch (err->code)
  179. + {
  180. + case G_IO_CHANNEL_ERROR_INVAL:
  181. + return G_IO_ERROR_INVAL;
  182. + default:
  183. + return G_IO_ERROR_UNKNOWN;
  184. + }
  185. + default:
  186. + g_assert_not_reached ();
  187. + return G_IO_ERROR_UNKNOWN; /* Keep the compiler happy */
  188. + }
  189. +}
  190. +
  191. +/**
  192. + * g_io_channel_read:
  193. + * @channel: a #GIOChannel
  194. + * @buf: a buffer to read the data into (which should be at least
  195. + * count bytes long)
  196. + * @count: the number of bytes to read from the #GIOChannel
  197. + * @bytes_read: returns the number of bytes actually read
  198. + *
  199. + * Reads data from a #GIOChannel.
  200. + *
  201. + * Return value: %G_IO_ERROR_NONE if the operation was successful.
  202. + *
  203. + * Deprecated:2.2: Use g_io_channel_read_chars() instead.
  204. + **/
  205. +GIOError
  206. +g_io_channel_read (GIOChannel *channel,
  207. + gchar *buf,
  208. + gsize count,
  209. + gsize *bytes_read)
  210. +{
  211. + GError *err = NULL;
  212. + GIOError error;
  213. + GIOStatus status;
  214. +
  215. + g_return_val_if_fail (channel != NULL, G_IO_ERROR_UNKNOWN);
  216. + g_return_val_if_fail (bytes_read != NULL, G_IO_ERROR_UNKNOWN);
  217. +
  218. + if (count == 0)
  219. + {
  220. + if (bytes_read)
  221. + *bytes_read = 0;
  222. + return G_IO_ERROR_NONE;
  223. + }
  224. +
  225. + g_return_val_if_fail (buf != NULL, G_IO_ERROR_UNKNOWN);
  226. +
  227. + status = channel->funcs->io_read (channel, buf, count, bytes_read, &err);
  228. +
  229. + error = g_io_error_get_from_g_error (status, err);
  230. +
  231. + if (err)
  232. + g_error_free (err);
  233. +
  234. + return error;
  235. +}
  236. +
  237. +/**
  238. + * g_io_channel_write:
  239. + * @channel: a #GIOChannel
  240. + * @buf: the buffer containing the data to write
  241. + * @count: the number of bytes to write
  242. + * @bytes_written: the number of bytes actually written
  243. + *
  244. + * Writes data to a #GIOChannel.
  245. + *
  246. + * Return value: %G_IO_ERROR_NONE if the operation was successful.
  247. + *
  248. + * Deprecated:2.2: Use g_io_channel_write_chars() instead.
  249. + **/
  250. +GIOError
  251. +g_io_channel_write (GIOChannel *channel,
  252. + const gchar *buf,
  253. + gsize count,
  254. + gsize *bytes_written)
  255. +{
  256. + GError *err = NULL;
  257. + GIOError error;
  258. + GIOStatus status;
  259. +
  260. + g_return_val_if_fail (channel != NULL, G_IO_ERROR_UNKNOWN);
  261. + g_return_val_if_fail (bytes_written != NULL, G_IO_ERROR_UNKNOWN);
  262. +
  263. + status = channel->funcs->io_write (channel, buf, count, bytes_written, &err);
  264. +
  265. + error = g_io_error_get_from_g_error (status, err);
  266. +
  267. + if (err)
  268. + g_error_free (err);
  269. +
  270. + return error;
  271. +}
  272. +
  273. +/**
  274. + * g_io_channel_seek:
  275. + * @channel: a #GIOChannel
  276. + * @offset: an offset, in bytes, which is added to the position specified
  277. + * by @type
  278. + * @type: the position in the file, which can be %G_SEEK_CUR (the current
  279. + * position), %G_SEEK_SET (the start of the file), or %G_SEEK_END
  280. + * (the end of the file)
  281. + *
  282. + * Sets the current position in the #GIOChannel, similar to the standard
  283. + * library function fseek().
  284. + *
  285. + * Return value: %G_IO_ERROR_NONE if the operation was successful.
  286. + *
  287. + * Deprecated:2.2: Use g_io_channel_seek_position() instead.
  288. + **/
  289. +GIOError
  290. +g_io_channel_seek (GIOChannel *channel,
  291. + gint64 offset,
  292. + GSeekType type)
  293. +{
  294. + GError *err = NULL;
  295. + GIOError error;
  296. + GIOStatus status;
  297. +
  298. + g_return_val_if_fail (channel != NULL, G_IO_ERROR_UNKNOWN);
  299. + g_return_val_if_fail (channel->is_seekable, G_IO_ERROR_UNKNOWN);
  300. +
  301. + switch (type)
  302. + {
  303. + case G_SEEK_CUR:
  304. + case G_SEEK_SET:
  305. + case G_SEEK_END:
  306. + break;
  307. + default:
  308. + g_warning ("g_io_channel_seek: unknown seek type");
  309. + return G_IO_ERROR_UNKNOWN;
  310. + }
  311. +
  312. + status = channel->funcs->io_seek (channel, offset, type, &err);
  313. +
  314. + error = g_io_error_get_from_g_error (status, err);
  315. +
  316. + if (err)
  317. + g_error_free (err);
  318. +
  319. + return error;
  320. +}
  321. +
  322. +/* The function g_io_channel_new_file() is prototyped in both
  323. + * giounix.c and giowin32.c, so we stick its documentation here.
  324. + */
  325. +
  326. +/**
  327. + * g_io_channel_new_file:
  328. + * @filename: A string containing the name of a file
  329. + * @mode: One of "r", "w", "a", "r+", "w+", "a+". These have
  330. + * the same meaning as in fopen()
  331. + * @error: A location to return an error of type %G_FILE_ERROR
  332. + *
  333. + * Open a file @filename as a #GIOChannel using mode @mode. This
  334. + * channel will be closed when the last reference to it is dropped,
  335. + * so there is no need to call g_io_channel_close() (though doing
  336. + * so will not cause problems, as long as no attempt is made to
  337. + * access the channel after it is closed).
  338. + *
  339. + * Return value: A #GIOChannel on success, %NULL on failure.
  340. + **/
  341. +
  342. +/**
  343. + * g_io_channel_close:
  344. + * @channel: A #GIOChannel
  345. + *
  346. + * Close an IO channel. Any pending data to be written will be
  347. + * flushed, ignoring errors. The channel will not be freed until the
  348. + * last reference is dropped using g_io_channel_unref().
  349. + *
  350. + * Deprecated:2.2: Use g_io_channel_shutdown() instead.
  351. + **/
  352. +void
  353. +g_io_channel_close (GIOChannel *channel)
  354. +{
  355. + GError *err = NULL;
  356. +
  357. + g_return_if_fail (channel != NULL);
  358. +
  359. + g_io_channel_purge (channel);
  360. +
  361. + channel->funcs->io_close (channel, &err);
  362. +
  363. + if (err)
  364. + { /* No way to return the error */
  365. + g_warning ("Error closing channel: %s", err->message);
  366. + g_error_free (err);
  367. + }
  368. +
  369. + channel->close_on_unref = FALSE; /* Because we already did */
  370. + channel->is_readable = FALSE;
  371. + channel->is_writeable = FALSE;
  372. + channel->is_seekable = FALSE;
  373. +}
  374. +
  375. +/**
  376. + * g_io_channel_shutdown:
  377. + * @channel: a #GIOChannel
  378. + * @flush: if %TRUE, flush pending
  379. + * @err: location to store a #GIOChannelError
  380. + *
  381. + * Close an IO channel. Any pending data to be written will be
  382. + * flushed if @flush is %TRUE. The channel will not be freed until the
  383. + * last reference is dropped using g_io_channel_unref().
  384. + *
  385. + * Return value: the status of the operation.
  386. + **/
  387. +GIOStatus
  388. +g_io_channel_shutdown (GIOChannel *channel,
  389. + gboolean flush,
  390. + GError **err)
  391. +{
  392. + GIOStatus status, result;
  393. + GError *tmperr = NULL;
  394. +
  395. + g_return_val_if_fail (channel != NULL, G_IO_STATUS_ERROR);
  396. + g_return_val_if_fail (err == NULL || *err == NULL, G_IO_STATUS_ERROR);
  397. +
  398. + if (channel->write_buf && channel->write_buf->len > 0)
  399. + {
  400. + if (flush)
  401. + {
  402. + GIOFlags flags;
  403. +
  404. + /* Set the channel to blocking, to avoid a busy loop
  405. + */
  406. + flags = g_io_channel_get_flags (channel);
  407. + /* Ignore any errors here, they're irrelevant */
  408. + g_io_channel_set_flags (channel, flags & ~G_IO_FLAG_NONBLOCK, NULL);
  409. +
  410. + result = g_io_channel_flush (channel, &tmperr);
  411. + }
  412. + else
  413. + result = G_IO_STATUS_NORMAL;
  414. +
  415. + g_string_truncate(channel->write_buf, 0);
  416. + }
  417. + else
  418. + result = G_IO_STATUS_NORMAL;
  419. +
  420. + if (channel->partial_write_buf[0] != '\0')
  421. + {
  422. + if (flush)
  423. + g_warning ("Partial character at end of write buffer not flushed.\n");
  424. + channel->partial_write_buf[0] = '\0';
  425. + }
  426. +
  427. + status = channel->funcs->io_close (channel, err);
  428. +
  429. + channel->close_on_unref = FALSE; /* Because we already did */
  430. + channel->is_readable = FALSE;
  431. + channel->is_writeable = FALSE;
  432. + channel->is_seekable = FALSE;
  433. +
  434. + if (status != G_IO_STATUS_NORMAL)
  435. + {
  436. + g_clear_error (&tmperr);
  437. + return status;
  438. + }
  439. + else if (result != G_IO_STATUS_NORMAL)
  440. + {
  441. + g_propagate_error (err, tmperr);
  442. + return result;
  443. + }
  444. + else
  445. + return G_IO_STATUS_NORMAL;
  446. +}
  447. +
  448. +/* This function is used for the final flush on close or unref */
  449. +static void
  450. +g_io_channel_purge (GIOChannel *channel)
  451. +{
  452. + GError *err = NULL;
  453. + GIOStatus status;
  454. +
  455. + g_return_if_fail (channel != NULL);
  456. +
  457. + if (channel->write_buf && channel->write_buf->len > 0)
  458. + {
  459. + GIOFlags flags;
  460. +
  461. + /* Set the channel to blocking, to avoid a busy loop
  462. + */
  463. + flags = g_io_channel_get_flags (channel);
  464. + g_io_channel_set_flags (channel, flags & ~G_IO_FLAG_NONBLOCK, NULL);
  465. +
  466. + status = g_io_channel_flush (channel, &err);
  467. +
  468. + if (err)
  469. + { /* No way to return the error */
  470. + g_warning ("Error flushing string: %s", err->message);
  471. + g_error_free (err);
  472. + }
  473. + }
  474. +
  475. + /* Flush these in case anyone tries to close without unrefing */
  476. +
  477. + if (channel->read_buf)
  478. + g_string_truncate (channel->read_buf, 0);
  479. + if (channel->write_buf)
  480. + g_string_truncate (channel->write_buf, 0);
  481. + if (channel->encoding)
  482. + {
  483. + if (channel->encoded_read_buf)
  484. + g_string_truncate (channel->encoded_read_buf, 0);
  485. +
  486. + if (channel->partial_write_buf[0] != '\0')
  487. + {
  488. + g_warning ("Partial character at end of write buffer not flushed.\n");
  489. + channel->partial_write_buf[0] = '\0';
  490. + }
  491. + }
  492. +}
  493. +
  494. +GSource *
  495. +g_io_create_watch (GIOChannel *channel,
  496. + GIOCondition condition)
  497. +{
  498. + g_return_val_if_fail (channel != NULL, NULL);
  499. +
  500. + return channel->funcs->io_create_watch (channel, condition);
  501. +}
  502. +
  503. +guint
  504. +g_io_add_watch_full (GIOChannel *channel,
  505. + gint priority,
  506. + GIOCondition condition,
  507. + GIOFunc func,
  508. + gpointer user_data,
  509. + GDestroyNotify notify)
  510. +{
  511. + GSource *source;
  512. + guint id;
  513. +
  514. + g_return_val_if_fail (channel != NULL, 0);
  515. +
  516. + source = g_io_create_watch (channel, condition);
  517. +
  518. + if (priority != G_PRIORITY_DEFAULT)
  519. + g_source_set_priority (source, priority);
  520. + g_source_set_callback (source, (GSourceFunc)func, user_data, notify);
  521. +
  522. + id = g_source_attach (source, NULL);
  523. + g_source_unref (source);
  524. +
  525. + return id;
  526. +}
  527. +
  528. +guint
  529. +g_io_add_watch (GIOChannel *channel,
  530. + GIOCondition condition,
  531. + GIOFunc func,
  532. + gpointer user_data)
  533. +{
  534. + return g_io_add_watch_full (channel, G_PRIORITY_DEFAULT, condition, func, user_data, NULL);
  535. +}
  536. +
  537. +/**
  538. + * g_io_channel_get_buffer_condition:
  539. + * @channel: A #GIOChannel
  540. + *
  541. + * This function returns a #GIOCondition depending on whether there
  542. + * is data to be read/space to write data in the internal buffers in
  543. + * the #GIOChannel. Only the flags %G_IO_IN and %G_IO_OUT may be set.
  544. + *
  545. + * Return value: A #GIOCondition
  546. + **/
  547. +GIOCondition
  548. +g_io_channel_get_buffer_condition (GIOChannel *channel)
  549. +{
  550. + GIOCondition condition = 0;
  551. +
  552. + if (channel->encoding)
  553. + {
  554. + if (channel->encoded_read_buf && (channel->encoded_read_buf->len > 0))
  555. + condition |= G_IO_IN; /* Only return if we have full characters */
  556. + }
  557. + else
  558. + {
  559. + if (channel->read_buf && (channel->read_buf->len > 0))
  560. + condition |= G_IO_IN;
  561. + }
  562. +
  563. + if (channel->write_buf && (channel->write_buf->len < channel->buf_size))
  564. + condition |= G_IO_OUT;
  565. +
  566. + return condition;
  567. +}
  568. +
  569. +/**
  570. + * g_io_channel_error_from_errno:
  571. + * @en: an <literal>errno</literal> error number, e.g. %EINVAL
  572. + *
  573. + * Converts an <literal>errno</literal> error number to a #GIOChannelError.
  574. + *
  575. + * Return value: a #GIOChannelError error number, e.g.
  576. + * %G_IO_CHANNEL_ERROR_INVAL.
  577. + **/
  578. +GIOChannelError
  579. +g_io_channel_error_from_errno (gint en)
  580. +{
  581. +#ifdef EAGAIN
  582. + g_return_val_if_fail (en != EAGAIN, G_IO_CHANNEL_ERROR_FAILED);
  583. +#endif
  584. +
  585. + switch (en)
  586. + {
  587. +#ifdef EBADF
  588. + case EBADF:
  589. + g_warning("Invalid file descriptor.\n");
  590. + return G_IO_CHANNEL_ERROR_FAILED;
  591. +#endif
  592. +
  593. +#ifdef EFAULT
  594. + case EFAULT:
  595. + g_warning("Buffer outside valid address space.\n");
  596. + return G_IO_CHANNEL_ERROR_FAILED;
  597. +#endif
  598. +
  599. +#ifdef EFBIG
  600. + case EFBIG:
  601. + return G_IO_CHANNEL_ERROR_FBIG;
  602. +#endif
  603. +
  604. +#ifdef EINTR
  605. + /* In general, we should catch EINTR before we get here,
  606. + * but close() is allowed to return EINTR by POSIX, so
  607. + * we need to catch it here; EINTR from close() is
  608. + * unrecoverable, because it's undefined whether
  609. + * the fd was actually closed or not, so we just return
  610. + * a generic error code.
  611. + */
  612. + case EINTR:
  613. + return G_IO_CHANNEL_ERROR_FAILED;
  614. +#endif
  615. +
  616. +#ifdef EINVAL
  617. + case EINVAL:
  618. + return G_IO_CHANNEL_ERROR_INVAL;
  619. +#endif
  620. +
  621. +#ifdef EIO
  622. + case EIO:
  623. + return G_IO_CHANNEL_ERROR_IO;
  624. +#endif
  625. +
  626. +#ifdef EISDIR
  627. + case EISDIR:
  628. + return G_IO_CHANNEL_ERROR_ISDIR;
  629. +#endif
  630. +
  631. +#ifdef ENOSPC
  632. + case ENOSPC:
  633. + return G_IO_CHANNEL_ERROR_NOSPC;
  634. +#endif
  635. +
  636. +#ifdef ENXIO
  637. + case ENXIO:
  638. + return G_IO_CHANNEL_ERROR_NXIO;
  639. +#endif
  640. +
  641. +#ifdef EOVERFLOW
  642. + case EOVERFLOW:
  643. + return G_IO_CHANNEL_ERROR_OVERFLOW;
  644. +#endif
  645. +
  646. +#ifdef EPIPE
  647. + case EPIPE:
  648. + return G_IO_CHANNEL_ERROR_PIPE;
  649. +#endif
  650. +
  651. + default:
  652. + return G_IO_CHANNEL_ERROR_FAILED;
  653. + }
  654. +}
  655. +
  656. +/**
  657. + * g_io_channel_set_buffer_size:
  658. + * @channel: a #GIOChannel
  659. + * @size: the size of the buffer, or 0 to let GLib pick a good size
  660. + *
  661. + * Sets the buffer size.
  662. + **/
  663. +void
  664. +g_io_channel_set_buffer_size (GIOChannel *channel,
  665. + gsize size)
  666. +{
  667. + g_return_if_fail (channel != NULL);
  668. +
  669. + if (size == 0)
  670. + size = G_IO_NICE_BUF_SIZE;
  671. +
  672. + if (size < MAX_CHAR_SIZE)
  673. + size = MAX_CHAR_SIZE;
  674. +
  675. + channel->buf_size = size;
  676. +}
  677. +
  678. +/**
  679. + * g_io_channel_get_buffer_size:
  680. + * @channel: a #GIOChannel
  681. + *
  682. + * Gets the buffer size.
  683. + *
  684. + * Return value: the size of the buffer.
  685. + **/
  686. +gsize
  687. +g_io_channel_get_buffer_size (GIOChannel *channel)
  688. +{
  689. + g_return_val_if_fail (channel != NULL, 0);
  690. +
  691. + return channel->buf_size;
  692. +}
  693. +
  694. +/**
  695. + * g_io_channel_set_line_term:
  696. + * @channel: a #GIOChannel
  697. + * @line_term: The line termination string. Use %NULL for autodetect.
  698. + * Autodetection breaks on "\n", "\r\n", "\r", "\0", and
  699. + * the Unicode paragraph separator. Autodetection should
  700. + * not be used for anything other than file-based channels.
  701. + * @length: The length of the termination string. If -1 is passed, the
  702. + * string is assumed to be nul-terminated. This option allows
  703. + * termination strings with embedded nuls.
  704. + *
  705. + * This sets the string that #GIOChannel uses to determine
  706. + * where in the file a line break occurs.
  707. + **/
  708. +void
  709. +g_io_channel_set_line_term (GIOChannel *channel,
  710. + const gchar *line_term,
  711. + gint length)
  712. +{
  713. + g_return_if_fail (channel != NULL);
  714. + g_return_if_fail (line_term == NULL || length != 0); /* Disallow "" */
  715. +
  716. + if (line_term == NULL)
  717. + length = 0;
  718. + else if (length < 0)
  719. + length = strlen (line_term);
  720. +
  721. + g_free (channel->line_term);
  722. + channel->line_term = line_term ? g_memdup (line_term, length) : NULL;
  723. + channel->line_term_len = length;
  724. +}
  725. +
  726. +/**
  727. + * g_io_channel_get_line_term:
  728. + * @channel: a #GIOChannel
  729. + * @length: a location to return the length of the line terminator
  730. + *
  731. + * This returns the string that #GIOChannel uses to determine
  732. + * where in the file a line break occurs. A value of %NULL
  733. + * indicates autodetection.
  734. + *
  735. + * Return value: The line termination string. This value
  736. + * is owned by GLib and must not be freed.
  737. + **/
  738. +G_CONST_RETURN gchar*
  739. +g_io_channel_get_line_term (GIOChannel *channel,
  740. + gint *length)
  741. +{
  742. + g_return_val_if_fail (channel != NULL, NULL);
  743. +
  744. + if (length)
  745. + *length = channel->line_term_len;
  746. +
  747. + return channel->line_term;
  748. +}
  749. +
  750. +/**
  751. + * g_io_channel_set_flags:
  752. + * @channel: a #GIOChannel
  753. + * @flags: the flags to set on the IO channel
  754. + * @error: A location to return an error of type #GIOChannelError
  755. + *
  756. + * Sets the (writeable) flags in @channel to (@flags & %G_IO_CHANNEL_SET_MASK).
  757. + *
  758. + * Return value: the status of the operation.
  759. + **/
  760. +GIOStatus
  761. +g_io_channel_set_flags (GIOChannel *channel,
  762. + GIOFlags flags,
  763. + GError **error)
  764. +{
  765. + g_return_val_if_fail (channel != NULL, G_IO_STATUS_ERROR);
  766. + g_return_val_if_fail ((error == NULL) || (*error == NULL),
  767. + G_IO_STATUS_ERROR);
  768. +
  769. + return (*channel->funcs->io_set_flags) (channel,
  770. + flags & G_IO_FLAG_SET_MASK,
  771. + error);
  772. +}
  773. +
  774. +/**
  775. + * g_io_channel_get_flags:
  776. + * @channel: a #GIOChannel
  777. + *
  778. + * Gets the current flags for a #GIOChannel, including read-only
  779. + * flags such as %G_IO_FLAG_IS_READABLE.
  780. + *
  781. + * The values of the flags %G_IO_FLAG_IS_READABLE and %G_IO_FLAG_IS_WRITEABLE
  782. + * are cached for internal use by the channel when it is created.
  783. + * If they should change at some later point (e.g. partial shutdown
  784. + * of a socket with the UNIX shutdown() function), the user
  785. + * should immediately call g_io_channel_get_flags() to update
  786. + * the internal values of these flags.
  787. + *
  788. + * Return value: the flags which are set on the channel
  789. + **/
  790. +GIOFlags
  791. +g_io_channel_get_flags (GIOChannel *channel)
  792. +{
  793. + GIOFlags flags;
  794. +
  795. + g_return_val_if_fail (channel != NULL, 0);
  796. +
  797. + flags = (* channel->funcs->io_get_flags) (channel);
  798. +
  799. + /* Cross implementation code */
  800. +
  801. + if (channel->is_seekable)
  802. + flags |= G_IO_FLAG_IS_SEEKABLE;
  803. + if (channel->is_readable)
  804. + flags |= G_IO_FLAG_IS_READABLE;
  805. + if (channel->is_writeable)
  806. + flags |= G_IO_FLAG_IS_WRITEABLE;
  807. +
  808. + return flags;
  809. +}
  810. +
  811. +/**
  812. + * g_io_channel_set_close_on_unref:
  813. + * @channel: a #GIOChannel
  814. + * @do_close: Whether to close the channel on the final unref of
  815. + * the GIOChannel data structure. The default value of
  816. + * this is %TRUE for channels created by g_io_channel_new_file (),
  817. + * and %FALSE for all other channels.
  818. + *
  819. + * Setting this flag to %TRUE for a channel you have already closed
  820. + * can cause problems.
  821. + **/
  822. +void
  823. +g_io_channel_set_close_on_unref (GIOChannel *channel,
  824. + gboolean do_close)
  825. +{
  826. + g_return_if_fail (channel != NULL);
  827. +
  828. + channel->close_on_unref = do_close;
  829. +}
  830. +
  831. +/**
  832. + * g_io_channel_get_close_on_unref:
  833. + * @channel: a #GIOChannel.
  834. + *
  835. + * Returns whether the file/socket/whatever associated with @channel
  836. + * will be closed when @channel receives its final unref and is
  837. + * destroyed. The default value of this is %TRUE for channels created
  838. + * by g_io_channel_new_file (), and %FALSE for all other channels.
  839. + *
  840. + * Return value: Whether the channel will be closed on the final unref of
  841. + * the GIOChannel data structure.
  842. + **/
  843. +gboolean
  844. +g_io_channel_get_close_on_unref (GIOChannel *channel)
  845. +{
  846. + g_return_val_if_fail (channel != NULL, FALSE);
  847. +
  848. + return channel->close_on_unref;
  849. +}
  850. +
  851. +/**
  852. + * g_io_channel_seek_position:
  853. + * @channel: a #GIOChannel
  854. + * @offset: The offset in bytes from the position specified by @type
  855. + * @type: a #GSeekType. The type %G_SEEK_CUR is only allowed in those
  856. + * cases where a call to g_io_channel_set_encoding ()
  857. + * is allowed. See the documentation for
  858. + * g_io_channel_set_encoding () for details.
  859. + * @error: A location to return an error of type #GIOChannelError
  860. + *
  861. + * Replacement for g_io_channel_seek() with the new API.
  862. + *
  863. + * Return value: the status of the operation.
  864. + **/
  865. +GIOStatus
  866. +g_io_channel_seek_position (GIOChannel *channel,
  867. + gint64 offset,
  868. + GSeekType type,
  869. + GError **error)
  870. +{
  871. + GIOStatus status;
  872. +
  873. + /* For files, only one of the read and write buffers can contain data.
  874. + * For sockets, both can contain data.
  875. + */
  876. +
  877. + g_return_val_if_fail (channel != NULL, G_IO_STATUS_ERROR);
  878. + g_return_val_if_fail ((error == NULL) || (*error == NULL),
  879. + G_IO_STATUS_ERROR);
  880. + g_return_val_if_fail (channel->is_seekable, G_IO_STATUS_ERROR);
  881. +
  882. + switch (type)
  883. + {
  884. + case G_SEEK_CUR: /* The user is seeking relative to the head of the buffer */
  885. + if (channel->use_buffer)
  886. + {
  887. + if (channel->do_encode && channel->encoded_read_buf
  888. + && channel->encoded_read_buf->len > 0)
  889. + {
  890. + g_warning ("Seek type G_SEEK_CUR not allowed for this"
  891. + " channel's encoding.\n");
  892. + return G_IO_STATUS_ERROR;
  893. + }
  894. + if (channel->read_buf)
  895. + offset -= channel->read_buf->len;
  896. + if (channel->encoded_read_buf)
  897. + {
  898. + g_assert (channel->encoded_read_buf->len == 0 || !channel->do_encode);
  899. +
  900. + /* If there's anything here, it's because the encoding is UTF-8,
  901. + * so we can just subtract the buffer length, the same as for
  902. + * the unencoded data.
  903. + */
  904. +
  905. + offset -= channel->encoded_read_buf->len;
  906. + }
  907. + }
  908. + break;
  909. + case G_SEEK_SET:
  910. + case G_SEEK_END:
  911. + break;
  912. + default:
  913. + g_warning ("g_io_channel_seek_position: unknown seek type");
  914. + return G_IO_STATUS_ERROR;
  915. + }
  916. +
  917. + if (channel->use_buffer)
  918. + {
  919. + status = g_io_channel_flush (channel, error);
  920. + if (status != G_IO_STATUS_NORMAL)
  921. + return status;
  922. + }
  923. +
  924. + status = channel->funcs->io_seek (channel, offset, type, error);
  925. +
  926. + if ((status == G_IO_STATUS_NORMAL) && (channel->use_buffer))
  927. + {
  928. + if (channel->read_buf)
  929. + g_string_truncate (channel->read_buf, 0);
  930. +
  931. + /* Conversion state no longer matches position in file */
  932. + if (channel->read_cd != (GIConv) -1)
  933. + g_iconv (channel->read_cd, NULL, NULL, NULL, NULL);
  934. + if (channel->write_cd != (GIConv) -1)
  935. + g_iconv (channel->write_cd, NULL, NULL, NULL, NULL);
  936. +
  937. + if (channel->encoded_read_buf)
  938. + {
  939. + g_assert (channel->encoded_read_buf->len == 0 || !channel->do_encode);
  940. + g_string_truncate (channel->encoded_read_buf, 0);
  941. + }
  942. +
  943. + if (channel->partial_write_buf[0] != '\0')
  944. + {
  945. + g_warning ("Partial character at end of write buffer not flushed.\n");
  946. + channel->partial_write_buf[0] = '\0';
  947. + }
  948. + }
  949. +
  950. + return status;
  951. +}
  952. +
  953. +/**
  954. + * g_io_channel_flush:
  955. + * @channel: a #GIOChannel
  956. + * @error: location to store an error of type #GIOChannelError
  957. + *
  958. + * Flushes the write buffer for the GIOChannel.
  959. + *
  960. + * Return value: the status of the operation: One of
  961. + * #G_IO_CHANNEL_NORMAL, #G_IO_CHANNEL_AGAIN, or
  962. + * #G_IO_CHANNEL_ERROR.
  963. + **/
  964. +GIOStatus
  965. +g_io_channel_flush (GIOChannel *channel,
  966. + GError **error)
  967. +{
  968. + GIOStatus status;
  969. + gsize this_time = 1, bytes_written = 0;
  970. +
  971. + g_return_val_if_fail (channel != NULL, G_IO_STATUS_ERROR);
  972. + g_return_val_if_fail ((error == NULL) || (*error == NULL), G_IO_STATUS_ERROR);
  973. +
  974. + if (channel->write_buf == NULL || channel->write_buf->len == 0)
  975. + return G_IO_STATUS_NORMAL;
  976. +
  977. + do
  978. + {
  979. + g_assert (this_time > 0);
  980. +
  981. + status = channel->funcs->io_write (channel,
  982. + channel->write_buf->str + bytes_written,
  983. + channel->write_buf->len - bytes_written,
  984. + &this_time, error);
  985. + bytes_written += this_time;
  986. + }
  987. + while ((bytes_written < channel->write_buf->len)
  988. + && (status == G_IO_STATUS_NORMAL));
  989. +
  990. + g_string_erase (channel->write_buf, 0, bytes_written);
  991. +
  992. + return status;
  993. +}
  994. +
  995. +/**
  996. + * g_io_channel_set_buffered:
  997. + * @channel: a #GIOChannel
  998. + * @buffered: whether to set the channel buffered or unbuffered
  999. + *
  1000. + * The buffering state can only be set if the channel's encoding
  1001. + * is %NULL. For any other encoding, the channel must be buffered.
  1002. + *
  1003. + * A buffered channel can only be set unbuffered if the channel's
  1004. + * internal buffers have been flushed. Newly created channels or
  1005. + * channels which have returned %G_IO_STATUS_EOF
  1006. + * not require such a flush. For write-only channels, a call to
  1007. + * g_io_channel_flush () is sufficient. For all other channels,
  1008. + * the buffers may be flushed by a call to g_io_channel_seek_position ().
  1009. + * This includes the possibility of seeking with seek type %G_SEEK_CUR
  1010. + * and an offset of zero. Note that this means that socket-based
  1011. + * channels cannot be set unbuffered once they have had data
  1012. + * read from them.
  1013. + *
  1014. + * On unbuffered channels, it is safe to mix read and write
  1015. + * calls from the new and old APIs, if this is necessary for
  1016. + * maintaining old code.
  1017. + *
  1018. + * The default state of the channel is buffered.
  1019. + **/
  1020. +void
  1021. +g_io_channel_set_buffered (GIOChannel *channel,
  1022. + gboolean buffered)
  1023. +{
  1024. + g_return_if_fail (channel != NULL);
  1025. +
  1026. + if (channel->encoding != NULL)
  1027. + {
  1028. + g_warning ("Need to have NULL encoding to set the buffering state of the "
  1029. + "channel.\n");
  1030. + return;
  1031. + }
  1032. +
  1033. + g_return_if_fail (!channel->read_buf || channel->read_buf->len == 0);
  1034. + g_return_if_fail (!channel->write_buf || channel->write_buf->len == 0);
  1035. +
  1036. + channel->use_buffer = buffered;
  1037. +}
  1038. +
  1039. +/**
  1040. + * g_io_channel_get_buffered:
  1041. + * @channel: a #GIOChannel
  1042. + *
  1043. + * Returns whether @channel is buffered.
  1044. + *
  1045. + * Return Value: %TRUE if the @channel is buffered.
  1046. + **/
  1047. +gboolean
  1048. +g_io_channel_get_buffered (GIOChannel *channel)
  1049. +{
  1050. + g_return_val_if_fail (channel != NULL, FALSE);
  1051. +
  1052. + return channel->use_buffer;
  1053. +}
  1054. +
  1055. +/**
  1056. + * g_io_channel_set_encoding:
  1057. + * @channel: a #GIOChannel
  1058. + * @encoding: the encoding type
  1059. + * @error: location to store an error of type #GConvertError
  1060. + *
  1061. + * Sets the encoding for the input/output of the channel.
  1062. + * The internal encoding is always UTF-8. The default encoding
  1063. + * for the external file is UTF-8.
  1064. + *
  1065. + * The encoding %NULL is safe to use with binary data.
  1066. + *
  1067. + * The encoding can only be set if one of the following conditions
  1068. + * is true:
  1069. + * <itemizedlist>
  1070. + * <listitem><para>
  1071. + * The channel was just created, and has not been written to or read
  1072. + * from yet.
  1073. + * </para></listitem>
  1074. + * <listitem><para>
  1075. + * The channel is write-only.
  1076. + * </para></listitem>
  1077. + * <listitem><para>
  1078. + * The channel is a file, and the file pointer was just
  1079. + * repositioned by a call to g_io_channel_seek_position().
  1080. + * (This flushes all the internal buffers.)
  1081. + * </para></listitem>
  1082. + * <listitem><para>
  1083. + * The current encoding is %NULL or UTF-8.
  1084. + * </para></listitem>
  1085. + * <listitem><para>
  1086. + * One of the (new API) read functions has just returned %G_IO_STATUS_EOF
  1087. + * (or, in the case of g_io_channel_read_to_end(), %G_IO_STATUS_NORMAL).
  1088. + * </para></listitem>
  1089. + * <listitem><para>
  1090. + * One of the functions g_io_channel_read_chars() or
  1091. + * g_io_channel_read_unichar() has returned %G_IO_STATUS_AGAIN or
  1092. + * %G_IO_STATUS_ERROR. This may be useful in the case of
  1093. + * %G_CONVERT_ERROR_ILLEGAL_SEQUENCE.
  1094. + * Returning one of these statuses from g_io_channel_read_line(),
  1095. + * g_io_channel_read_line_string(), or g_io_channel_read_to_end()
  1096. + * does <emphasis>not</emphasis> guarantee that the encoding can
  1097. + * be changed.
  1098. + * </para></listitem>
  1099. + * </itemizedlist>
  1100. + * Channels which do not meet one of the above conditions cannot call
  1101. + * g_io_channel_seek_position() with an offset of %G_SEEK_CUR, and, if
  1102. + * they are "seekable", cannot call g_io_channel_write_chars() after
  1103. + * calling one of the API "read" functions.
  1104. + *
  1105. + * Return Value: %G_IO_STATUS_NORMAL if the encoding was successfully set.
  1106. + **/
  1107. +GIOStatus
  1108. +g_io_channel_set_encoding (GIOChannel *channel,
  1109. + const gchar *encoding,
  1110. + GError **error)
  1111. +{
  1112. + GIConv read_cd, write_cd;
  1113. + gboolean did_encode;
  1114. +
  1115. + g_return_val_if_fail (channel != NULL, G_IO_STATUS_ERROR);
  1116. + g_return_val_if_fail ((error == NULL) || (*error == NULL), G_IO_STATUS_ERROR);
  1117. +
  1118. + /* Make sure the encoded buffers are empty */
  1119. +
  1120. + g_return_val_if_fail (!channel->do_encode || !channel->encoded_read_buf ||
  1121. + channel->encoded_read_buf->len == 0, G_IO_STATUS_ERROR);
  1122. +
  1123. + if (!channel->use_buffer)
  1124. + {
  1125. + g_warning ("Need to set the channel buffered before setting the encoding.\n");
  1126. + g_warning ("Assuming this is what you meant and acting accordingly.\n");
  1127. +
  1128. + channel->use_buffer = TRUE;
  1129. + }
  1130. +
  1131. + if (channel->partial_write_buf[0] != '\0')
  1132. + {
  1133. + g_warning ("Partial character at end of write buffer not flushed.\n");
  1134. + channel->partial_write_buf[0] = '\0';
  1135. + }
  1136. +
  1137. + did_encode = channel->do_encode;
  1138. +
  1139. + if (!encoding || strcmp (encoding, "UTF8") == 0 || strcmp (encoding, "UTF-8") == 0)
  1140. + {
  1141. + channel->do_encode = FALSE;
  1142. + read_cd = write_cd = (GIConv) -1;
  1143. + }
  1144. + else
  1145. + {
  1146. + gint err = 0;
  1147. + const gchar *from_enc = NULL, *to_enc = NULL;
  1148. +
  1149. + if (channel->is_readable)
  1150. + {
  1151. + read_cd = g_iconv_open ("UTF-8", encoding);
  1152. +
  1153. + if (read_cd == (GIConv) -1)
  1154. + {
  1155. + err = errno;
  1156. + from_enc = encoding;
  1157. + to_enc = "UTF-8";
  1158. + }
  1159. + }
  1160. + else
  1161. + read_cd = (GIConv) -1;
  1162. +
  1163. + if (channel->is_writeable && err == 0)
  1164. + {
  1165. + write_cd = g_iconv_open (encoding, "UTF-8");
  1166. +
  1167. + if (write_cd == (GIConv) -1)
  1168. + {
  1169. + err = errno;
  1170. + from_enc = "UTF-8";
  1171. + to_enc = encoding;
  1172. + }
  1173. + }
  1174. + else
  1175. + write_cd = (GIConv) -1;
  1176. +
  1177. + if (err != 0)
  1178. + {
  1179. + g_assert (from_enc);
  1180. + g_assert (to_enc);
  1181. +
  1182. + if (err == EINVAL)
  1183. + g_set_error (error, G_CONVERT_ERROR, G_CONVERT_ERROR_NO_CONVERSION,
  1184. + _("Conversion from character set '%s' to '%s' is not supported"),
  1185. + from_enc, to_enc);
  1186. + else
  1187. + g_set_error (error, G_CONVERT_ERROR, G_CONVERT_ERROR_FAILED,
  1188. + _("Could not open converter from '%s' to '%s': %s"),
  1189. + from_enc, to_enc, g_strerror (err));
  1190. +
  1191. + if (read_cd != (GIConv) -1)
  1192. + g_iconv_close (read_cd);
  1193. + if (write_cd != (GIConv) -1)
  1194. + g_iconv_close (write_cd);
  1195. +
  1196. + return G_IO_STATUS_ERROR;
  1197. + }
  1198. +
  1199. + channel->do_encode = TRUE;
  1200. + }
  1201. +
  1202. + /* The encoding is ok, so set the fields in channel */
  1203. +
  1204. + if (channel->read_cd != (GIConv) -1)
  1205. + g_iconv_close (channel->read_cd);
  1206. + if (channel->write_cd != (GIConv) -1)
  1207. + g_iconv_close (channel->write_cd);
  1208. +
  1209. + if (channel->encoded_read_buf && channel->encoded_read_buf->len > 0)
  1210. + {
  1211. + g_assert (!did_encode); /* Encoding UTF-8, NULL doesn't use encoded_read_buf */
  1212. +
  1213. + /* This is just validated UTF-8, so we can copy it back into read_buf
  1214. + * so it can be encoded in whatever the new encoding is.
  1215. + */
  1216. +
  1217. + g_string_prepend_len (channel->read_buf, channel->encoded_read_buf->str,
  1218. + channel->encoded_read_buf->len);
  1219. + g_string_truncate (channel->encoded_read_buf, 0);
  1220. + }
  1221. +
  1222. + channel->read_cd = read_cd;
  1223. + channel->write_cd = write_cd;
  1224. +
  1225. + g_free (channel->encoding);
  1226. + channel->encoding = g_strdup (encoding);
  1227. +
  1228. + return G_IO_STATUS_NORMAL;
  1229. +}
  1230. +
  1231. +/**
  1232. + * g_io_channel_get_encoding:
  1233. + * @channel: a #GIOChannel
  1234. + *
  1235. + * Gets the encoding for the input/output of the channel.
  1236. + * The internal encoding is always UTF-8. The encoding %NULL
  1237. + * makes the channel safe for binary data.
  1238. + *
  1239. + * Return value: A string containing the encoding, this string is
  1240. + * owned by GLib and must not be freed.
  1241. + **/
  1242. +G_CONST_RETURN gchar*
  1243. +g_io_channel_get_encoding (GIOChannel *channel)
  1244. +{
  1245. + g_return_val_if_fail (channel != NULL, NULL);
  1246. +
  1247. + return channel->encoding;
  1248. +}
  1249. +
  1250. +static GIOStatus
  1251. +g_io_channel_fill_buffer (GIOChannel *channel,
  1252. + GError **err)
  1253. +{
  1254. + gsize read_size, cur_len, oldlen;
  1255. + GIOStatus status;
  1256. +
  1257. + if (channel->is_seekable && channel->write_buf && channel->write_buf->len > 0)
  1258. + {
  1259. + status = g_io_channel_flush (channel, err);
  1260. + if (status != G_IO_STATUS_NORMAL)
  1261. + return status;
  1262. + }
  1263. + if (channel->is_seekable && channel->partial_write_buf[0] != '\0')
  1264. + {
  1265. + g_warning ("Partial character at end of write buffer not flushed.\n");
  1266. + channel->partial_write_buf[0] = '\0';
  1267. + }
  1268. +
  1269. + if (!channel->read_buf)
  1270. + channel->read_buf = g_string_sized_new (channel->buf_size);
  1271. +
  1272. + cur_len = channel->read_buf->len;
  1273. +
  1274. + g_string_set_size (channel->read_buf, channel->read_buf->len + channel->buf_size);
  1275. +
  1276. + status = channel->funcs->io_read (channel, channel->read_buf->str + cur_len,
  1277. + channel->buf_size, &read_size, err);
  1278. +
  1279. + g_assert ((status == G_IO_STATUS_NORMAL) || (read_size == 0));
  1280. +
  1281. + g_string_truncate (channel->read_buf, read_size + cur_len);
  1282. +
  1283. + if ((status != G_IO_STATUS_NORMAL) &&
  1284. + ((status != G_IO_STATUS_EOF) || (channel->read_buf->len == 0)))
  1285. + return status;
  1286. +
  1287. + g_assert (channel->read_buf->len > 0);
  1288. +
  1289. + if (channel->encoded_read_buf)
  1290. + oldlen = channel->encoded_read_buf->len;
  1291. + else
  1292. + {
  1293. + oldlen = 0;
  1294. + if (channel->encoding)
  1295. + channel->encoded_read_buf = g_string_sized_new (channel->buf_size);
  1296. + }
  1297. +
  1298. + if (channel->do_encode)
  1299. + {
  1300. + gsize errnum, inbytes_left, outbytes_left;
  1301. + gchar *inbuf, *outbuf;
  1302. + int errval;
  1303. +
  1304. + g_assert (channel->encoded_read_buf);
  1305. +
  1306. +reencode:
  1307. +
  1308. + inbytes_left = channel->read_buf->len;
  1309. + outbytes_left = MAX (channel->read_buf->len,
  1310. + channel->encoded_read_buf->allocated_len
  1311. + - channel->encoded_read_buf->len - 1); /* 1 for NULL */
  1312. + outbytes_left = MAX (outbytes_left, 6);
  1313. +
  1314. + inbuf = channel->read_buf->str;
  1315. + g_string_set_size (channel->encoded_read_buf,
  1316. + channel->encoded_read_buf->len + outbytes_left);
  1317. + outbuf = channel->encoded_read_buf->str + channel->encoded_read_buf->len
  1318. + - outbytes_left;
  1319. +
  1320. + errnum = g_iconv (channel->read_cd, &inbuf, &inbytes_left,
  1321. + &outbuf, &outbytes_left);
  1322. + errval = errno;
  1323. +
  1324. + g_assert (inbuf + inbytes_left == channel->read_buf->str
  1325. + + channel->read_buf->len);
  1326. + g_assert (outbuf + outbytes_left == channel->encoded_read_buf->str
  1327. + + channel->encoded_read_buf->len);
  1328. +
  1329. + g_string_erase (channel->read_buf, 0,
  1330. + channel->read_buf->len - inbytes_left);
  1331. + g_string_truncate (channel->encoded_read_buf,
  1332. + channel->encoded_read_buf->len - outbytes_left);
  1333. +
  1334. + if (errnum == (gsize) -1)
  1335. + {
  1336. + switch (errval)
  1337. + {
  1338. + case EINVAL:
  1339. + if ((oldlen == channel->encoded_read_buf->len)
  1340. + && (status == G_IO_STATUS_EOF))
  1341. + status = G_IO_STATUS_EOF;
  1342. + else
  1343. + status = G_IO_STATUS_NORMAL;
  1344. + break;
  1345. + case E2BIG:
  1346. + /* Buffer size at least 6, wrote at least on character */
  1347. + g_assert (inbuf != channel->read_buf->str);
  1348. + goto reencode;
  1349. + case EILSEQ:
  1350. + if (oldlen < channel->encoded_read_buf->len)
  1351. + status = G_IO_STATUS_NORMAL;
  1352. + else
  1353. + {
  1354. + g_set_error (err, G_CONVERT_ERROR,
  1355. + G_CONVERT_ERROR_ILLEGAL_SEQUENCE,
  1356. + _("Invalid byte sequence in conversion input"));
  1357. + return G_IO_STATUS_ERROR;
  1358. + }
  1359. + break;
  1360. + default:
  1361. + g_assert (errval != EBADF); /* The converter should be open */
  1362. + g_set_error (err, G_CONVERT_ERROR, G_CONVERT_ERROR_FAILED,
  1363. + _("Error during conversion: %s"), g_strerror (errval));
  1364. + return G_IO_STATUS_ERROR;
  1365. + }
  1366. + }
  1367. + g_assert ((status != G_IO_STATUS_NORMAL)
  1368. + || (channel->encoded_read_buf->len > 0));
  1369. + }
  1370. + else if (channel->encoding) /* UTF-8 */
  1371. + {
  1372. + gchar *nextchar, *lastchar;
  1373. +
  1374. + g_assert (channel->encoded_read_buf);
  1375. +
  1376. + nextchar = channel->read_buf->str;
  1377. + lastchar = channel->read_buf->str + channel->read_buf->len;
  1378. +
  1379. + while (nextchar < lastchar)
  1380. + {
  1381. + gunichar val_char;
  1382. +
  1383. + val_char = g_utf8_get_char_validated (nextchar, lastchar - nextchar);
  1384. +
  1385. + switch (val_char)
  1386. + {
  1387. + case -2:
  1388. + /* stop, leave partial character in buffer */
  1389. + lastchar = nextchar;
  1390. + break;
  1391. + case -1:
  1392. + if (oldlen < channel->encoded_read_buf->len)
  1393. + status = G_IO_STATUS_NORMAL;
  1394. + else
  1395. + {
  1396. + g_set_error (err, G_CONVERT_ERROR,
  1397. + G_CONVERT_ERROR_ILLEGAL_SEQUENCE,
  1398. + _("Invalid byte sequence in conversion input"));
  1399. + status = G_IO_STATUS_ERROR;
  1400. + }
  1401. + lastchar = nextchar;
  1402. + break;
  1403. + default:
  1404. + nextchar = g_utf8_next_char (nextchar);
  1405. + break;
  1406. + }
  1407. + }
  1408. +
  1409. + if (lastchar > channel->read_buf->str)
  1410. + {
  1411. + gint copy_len = lastchar - channel->read_buf->str;
  1412. +
  1413. + g_string_append_len (channel->encoded_read_buf, channel->read_buf->str,
  1414. + copy_len);
  1415. + g_string_erase (channel->read_buf, 0, copy_len);
  1416. + }
  1417. + }
  1418. +
  1419. + return status;
  1420. +}
  1421. +
  1422. +/**
  1423. + * g_io_channel_read_line:
  1424. + * @channel: a #GIOChannel
  1425. + * @str_return: The line read from the #GIOChannel, including the
  1426. + * line terminator. This data should be freed with g_free()
  1427. + * when no longer needed. This is a nul-terminated string.
  1428. + * If a @length of zero is returned, this will be %NULL instead.
  1429. + * @length: location to store length of the read data, or %NULL
  1430. + * @terminator_pos: location to store position of line terminator, or %NULL
  1431. + * @error: A location to return an error of type #GConvertError
  1432. + * or #GIOChannelError
  1433. + *
  1434. + * Reads a line, including the terminating character(s),
  1435. + * from a #GIOChannel into a newly-allocated string.
  1436. + * @str_return will contain allocated memory if the return
  1437. + * is %G_IO_STATUS_NORMAL.
  1438. + *
  1439. + * Return value: the status of the operation.
  1440. + **/
  1441. +GIOStatus
  1442. +g_io_channel_read_line (GIOChannel *channel,
  1443. + gchar **str_return,
  1444. + gsize *length,
  1445. + gsize *terminator_pos,
  1446. + GError **error)
  1447. +{
  1448. + GIOStatus status;
  1449. + gsize got_length;
  1450. +
  1451. + g_return_val_if_fail (channel != NULL, G_IO_STATUS_ERROR);
  1452. + g_return_val_if_fail (str_return != NULL, G_IO_STATUS_ERROR);
  1453. + g_return_val_if_fail ((error == NULL) || (*error == NULL),
  1454. + G_IO_STATUS_ERROR);
  1455. + g_return_val_if_fail (channel->is_readable, G_IO_STATUS_ERROR);
  1456. +
  1457. + status = g_io_channel_read_line_backend (channel, &got_length, terminator_pos, error);
  1458. +
  1459. + if (length)
  1460. + *length = got_length;
  1461. +
  1462. + if (status == G_IO_STATUS_NORMAL)
  1463. + {
  1464. + g_assert (USE_BUF (channel));
  1465. + *str_return = g_strndup (USE_BUF (channel)->str, got_length);
  1466. + g_string_erase (USE_BUF (channel), 0, got_length);
  1467. + }
  1468. + else
  1469. + *str_return = NULL;
  1470. +
  1471. + return status;
  1472. +}
  1473. +
  1474. +/**
  1475. + * g_io_channel_read_line_string:
  1476. + * @channel: a #GIOChannel
  1477. + * @buffer: a #GString into which the line will be written.
  1478. + * If @buffer already contains data, the old data will
  1479. + * be overwritten.
  1480. + * @terminator_pos: location to store position of line terminator, or %NULL
  1481. + * @error: a location to store an error of type #GConvertError
  1482. + * or #GIOChannelError
  1483. + *
  1484. + * Reads a line from a #GIOChannel, using a #GString as a buffer.
  1485. + *
  1486. + * Return value: the status of the operation.
  1487. + **/
  1488. +GIOStatus
  1489. +g_io_channel_read_line_string (GIOChannel *channel,
  1490. + GString *buffer,
  1491. + gsize *terminator_pos,
  1492. + GError **error)
  1493. +{
  1494. + gsize length;
  1495. + GIOStatus status;
  1496. +
  1497. + g_return_val_if_fail (channel != NULL, G_IO_STATUS_ERROR);
  1498. + g_return_val_if_fail (buffer != NULL, G_IO_STATUS_ERROR);
  1499. + g_return_val_if_fail ((error == NULL) || (*error == NULL),
  1500. + G_IO_STATUS_ERROR);
  1501. + g_return_val_if_fail (channel->is_readable, G_IO_STATUS_ERROR);
  1502. +
  1503. + if (buffer->len > 0)
  1504. + g_string_truncate (buffer, 0); /* clear out the buffer */
  1505. +
  1506. + status = g_io_channel_read_line_backend (channel, &length, terminator_pos, error);
  1507. +
  1508. + if (status == G_IO_STATUS_NORMAL)
  1509. + {
  1510. + g_assert (USE_BUF (channel));
  1511. + g_string_append_len (buffer, USE_BUF (channel)->str, length);
  1512. + g_string_erase (USE_BUF (channel), 0, length);
  1513. + }
  1514. +
  1515. + return status;
  1516. +}
  1517. +
  1518. +
  1519. +static GIOStatus
  1520. +g_io_channel_read_line_backend (GIOChannel *channel,
  1521. + gsize *length,
  1522. + gsize *terminator_pos,
  1523. + GError **error)
  1524. +{
  1525. + GIOStatus status;
  1526. + gsize checked_to, line_term_len, line_length, got_term_len;
  1527. + gboolean first_time = TRUE;
  1528. +
  1529. + if (!channel->use_buffer)
  1530. + {
  1531. + /* Can't do a raw read in read_line */
  1532. + g_set_error (error, G_CONVERT_ERROR, G_CONVERT_ERROR_FAILED,
  1533. + _("Can't do a raw read in g_io_channel_read_line_string"));
  1534. + return G_IO_STATUS_ERROR;
  1535. + }
  1536. +
  1537. + status = G_IO_STATUS_NORMAL;
  1538. +
  1539. + if (channel->line_term)
  1540. + line_term_len = channel->line_term_len;
  1541. + else
  1542. + line_term_len = 3;
  1543. + /* This value used for setting checked_to, it's the longest of the four
  1544. + * we autodetect for.
  1545. + */
  1546. +
  1547. + checked_to = 0;
  1548. +
  1549. + while (TRUE)
  1550. + {
  1551. + gchar *nextchar, *lastchar;
  1552. + GString *use_buf;
  1553. +
  1554. + if (!first_time || (BUF_LEN (USE_BUF (channel)) == 0))
  1555. + {
  1556. +read_again:
  1557. + status = g_io_channel_fill_buffer (channel, error);
  1558. + switch (status)
  1559. + {
  1560. + case G_IO_STATUS_NORMAL:
  1561. + if (BUF_LEN (USE_BUF (channel)) == 0)
  1562. + /* Can happen when using conversion and only read
  1563. + * part of a character
  1564. + */
  1565. + {
  1566. + first_time = FALSE;
  1567. + continue;
  1568. + }
  1569. + break;
  1570. + case G_IO_STATUS_EOF:
  1571. + if (BUF_LEN (USE_BUF (channel)) == 0)
  1572. + {
  1573. + if (length)
  1574. + *length = 0;
  1575. +
  1576. + if (channel->encoding && channel->read_buf->len != 0)
  1577. + {
  1578. + g_set_error (error, G_CONVERT_ERROR,
  1579. + G_CONVERT_ERROR_PARTIAL_INPUT,
  1580. + _("Leftover unconverted data in read buffer"));
  1581. + return G_IO_STATUS_ERROR;
  1582. + }
  1583. + else
  1584. + return G_IO_STATUS_EOF;
  1585. + }
  1586. + break;
  1587. + default:
  1588. + if (length)
  1589. + *length = 0;
  1590. + return status;
  1591. + }
  1592. + }
  1593. +
  1594. + g_assert (BUF_LEN (USE_BUF (channel)) != 0);
  1595. +
  1596. + use_buf = USE_BUF (channel); /* The buffer has been created by this point */
  1597. +
  1598. + first_time = FALSE;
  1599. +
  1600. + lastchar = use_buf->str + use_buf->len;
  1601. +
  1602. + for (nextchar = use_buf->str + checked_to; nextchar < lastchar;
  1603. + channel->encoding ? nextchar = g_utf8_next_char (nextchar) : nextchar++)
  1604. + {
  1605. + if (channel->line_term)
  1606. + {
  1607. + if (memcmp (channel->line_term, nextchar, line_term_len) == 0)
  1608. + {
  1609. + line_length = nextchar - use_buf->str;
  1610. + got_term_len = line_term_len;
  1611. + goto done;
  1612. + }
  1613. + }
  1614. + else /* auto detect */
  1615. + {
  1616. + switch (*nextchar)
  1617. + {
  1618. + case '\n': /* unix */
  1619. + line_length = nextchar - use_buf->str;
  1620. + got_term_len = 1;
  1621. + goto done;
  1622. + case '\r': /* Warning: do not use with sockets */
  1623. + line_length = nextchar - use_buf->str;
  1624. + if ((nextchar == lastchar - 1) && (status != G_IO_STATUS_EOF)
  1625. + && (lastchar == use_buf->str + use_buf->len))
  1626. + goto read_again; /* Try to read more data */
  1627. + if ((nextchar < lastchar - 1) && (*(nextchar + 1) == '\n')) /* dos */
  1628. + got_term_len = 2;
  1629. + else /* mac */
  1630. + got_term_len = 1;
  1631. + goto done;
  1632. + case '\xe2': /* Unicode paragraph separator */
  1633. + if (strncmp ("\xe2\x80\xa9", nextchar, 3) == 0)
  1634. + {
  1635. + line_length = nextchar - use_buf->str;
  1636. + got_term_len = 3;
  1637. + goto done;
  1638. + }
  1639. + break;
  1640. + case '\0': /* Embeded null in input */
  1641. + line_length = nextchar - use_buf->str;
  1642. + got_term_len = 1;
  1643. + goto done;
  1644. + default: /* no match */
  1645. + break;
  1646. + }
  1647. + }
  1648. + }
  1649. +
  1650. + /* If encoding != NULL, valid UTF-8, didn't overshoot */
  1651. + g_assert (nextchar == lastchar);
  1652. +
  1653. + /* Check for EOF */
  1654. +
  1655. + if (status == G_IO_STATUS_EOF)
  1656. + {
  1657. + if (channel->encoding && channel->read_buf->len > 0)
  1658. + {
  1659. + g_set_error (error, G_CONVERT_ERROR, G_CONVERT_ERROR_PARTIAL_INPUT,
  1660. + _("Channel terminates in a partial character"));
  1661. + return G_IO_STATUS_ERROR;
  1662. + }
  1663. + line_length = use_buf->len;
  1664. + got_term_len = 0;
  1665. + break;
  1666. + }
  1667. +
  1668. + if (use_buf->len > line_term_len - 1)
  1669. + checked_to = use_buf->len - (line_term_len - 1);
  1670. + else
  1671. + checked_to = 0;
  1672. + }
  1673. +
  1674. +done:
  1675. +
  1676. + if (terminator_pos)
  1677. + *terminator_pos = line_length;
  1678. +
  1679. + if (length)
  1680. + *length = line_length + got_term_len;
  1681. +
  1682. + return G_IO_STATUS_NORMAL;
  1683. +}
  1684. +
  1685. +/**
  1686. + * g_io_channel_read_to_end:
  1687. + * @channel: a #GIOChannel
  1688. + * @str_return: Location to store a pointer to a string holding
  1689. + * the remaining data in the #GIOChannel. This data should
  1690. + * be freed with g_free() when no longer needed. This
  1691. + * data is terminated by an extra nul character, but there
  1692. + * may be other nuls in the intervening data.
  1693. + * @length: location to store length of the data
  1694. + * @error: location to return an error of type #GConvertError
  1695. + * or #GIOChannelError
  1696. + *
  1697. + * Reads all the remaining data from the file.
  1698. + *
  1699. + * Return value: %G_IO_STATUS_NORMAL on success.
  1700. + * This function never returns %G_IO_STATUS_EOF.
  1701. + **/
  1702. +GIOStatus
  1703. +g_io_channel_read_to_end (GIOChannel *channel,
  1704. + gchar **str_return,
  1705. + gsize *length,
  1706. + GError **error)
  1707. +{
  1708. + GIOStatus status;
  1709. +
  1710. + g_return_val_if_fail (channel != NULL, G_IO_STATUS_ERROR);
  1711. + g_return_val_if_fail ((error == NULL) || (*error == NULL),
  1712. + G_IO_STATUS_ERROR);
  1713. + g_return_val_if_fail (channel->is_readable, G_IO_STATUS_ERROR);
  1714. +
  1715. + if (str_return)
  1716. + *str_return = NULL;
  1717. + if (length)
  1718. + *length = 0;
  1719. +
  1720. + if (!channel->use_buffer)
  1721. + {
  1722. + g_set_error (error, G_CONVERT_ERROR, G_CONVERT_ERROR_FAILED,
  1723. + _("Can't do a raw read in g_io_channel_read_to_end"));
  1724. + return G_IO_STATUS_ERROR;
  1725. + }
  1726. +
  1727. + do
  1728. + status = g_io_channel_fill_buffer (channel, error);
  1729. + while (status == G_IO_STATUS_NORMAL);
  1730. +
  1731. + if (status != G_IO_STATUS_EOF)
  1732. + return status;
  1733. +
  1734. + if (channel->encoding && channel->read_buf->len > 0)
  1735. + {
  1736. + g_set_error (error, G_CONVERT_ERROR, G_CONVERT_ERROR_PARTIAL_INPUT,
  1737. + _("Channel terminates in a partial character"));
  1738. + return G_IO_STATUS_ERROR;
  1739. + }
  1740. +
  1741. + if (USE_BUF (channel) == NULL)
  1742. + {
  1743. + /* length is already set to zero */
  1744. + if (str_return)
  1745. + *str_return = g_strdup ("");
  1746. + }
  1747. + else
  1748. + {
  1749. + if (length)
  1750. + *length = USE_BUF (channel)->len;
  1751. +
  1752. + if (str_return)
  1753. + *str_return = g_string_free (USE_BUF (channel), FALSE);
  1754. + else
  1755. + g_string_free (USE_BUF (channel), TRUE);
  1756. +
  1757. + if (channel->encoding)
  1758. + channel->encoded_read_buf = NULL;
  1759. + else
  1760. + channel->read_buf = NULL;
  1761. + }
  1762. +
  1763. + return G_IO_STATUS_NORMAL;
  1764. +}
  1765. +
  1766. +/**
  1767. + * g_io_channel_read_chars:
  1768. + * @channel: a #GIOChannel
  1769. + * @buf: a buffer to read data into
  1770. + * @count: the size of the buffer. Note that the buffer may
  1771. + * not be complelely filled even if there is data
  1772. + * in the buffer if the remaining data is not a
  1773. + * complete character.
  1774. + * @bytes_read: The number of bytes read. This may be zero even on
  1775. + * success if count < 6 and the channel's encoding is non-%NULL.
  1776. + * This indicates that the next UTF-8 character is too wide for
  1777. + * the buffer.
  1778. + * @error: a location to return an error of type #GConvertError
  1779. + * or #GIOChannelError.
  1780. + *
  1781. + * Replacement for g_io_channel_read() with the new API.
  1782. + *
  1783. + * Return value: the status of the operation.
  1784. + **/
  1785. +GIOStatus
  1786. +g_io_channel_read_chars (GIOChannel *channel,
  1787. + gchar *buf,
  1788. + gsize count,
  1789. + gsize *bytes_read,
  1790. + GError **error)
  1791. +{
  1792. + GIOStatus status;
  1793. + gsize got_bytes;
  1794. +
  1795. + g_return_val_if_fail (channel != NULL, G_IO_STATUS_ERROR);
  1796. + g_return_val_if_fail ((error == NULL) || (*error == NULL),
  1797. + G_IO_STATUS_ERROR);
  1798. + g_return_val_if_fail (channel->is_readable, G_IO_STATUS_ERROR);
  1799. +
  1800. + if (count == 0)
  1801. + {
  1802. + *bytes_read = 0;
  1803. + return G_IO_STATUS_NORMAL;
  1804. + }
  1805. + g_return_val_if_fail (buf != NULL, G_IO_STATUS_ERROR);
  1806. +
  1807. + if (!channel->use_buffer)
  1808. + {
  1809. + gsize tmp_bytes;
  1810. +
  1811. + g_assert (!channel->read_buf || channel->read_buf->len == 0);
  1812. +
  1813. + status = channel->funcs->io_read (channel, buf, count, &tmp_bytes, error);
  1814. +
  1815. + if (bytes_read)
  1816. + *bytes_read = tmp_bytes;
  1817. +
  1818. + return status;
  1819. + }
  1820. +
  1821. + status = G_IO_STATUS_NORMAL;
  1822. +
  1823. + while (BUF_LEN (USE_BUF (channel)) < count && status == G_IO_STATUS_NORMAL)
  1824. + status = g_io_channel_fill_buffer (channel, error);
  1825. +
  1826. + /* Only return an error if we have no data */
  1827. +
  1828. + if (BUF_LEN (USE_BUF (channel)) == 0)
  1829. + {
  1830. + g_assert (status != G_IO_STATUS_NORMAL);
  1831. +
  1832. + if (status == G_IO_STATUS_EOF && channel->encoding
  1833. + && BUF_LEN (channel->read_buf) > 0)
  1834. + {
  1835. + g_set_error (error, G_CONVERT_ERROR,
  1836. + G_CONVERT_ERROR_PARTIAL_INPUT,
  1837. + _("Leftover unconverted data in read buffer"));
  1838. + status = G_IO_STATUS_ERROR;
  1839. + }
  1840. +
  1841. + if (bytes_read)
  1842. + *bytes_read = 0;
  1843. +
  1844. + return status;
  1845. + }
  1846. +
  1847. + if (status == G_IO_STATUS_ERROR)
  1848. + g_clear_error (error);
  1849. +
  1850. + got_bytes = MIN (count, BUF_LEN (USE_BUF (channel)));
  1851. +
  1852. + g_assert (got_bytes > 0);
  1853. +
  1854. + if (channel->encoding)
  1855. + /* Don't validate for NULL encoding, binary safe */
  1856. + {
  1857. + gchar *nextchar, *prevchar;
  1858. +
  1859. + g_assert (USE_BUF (channel) == channel->encoded_read_buf);
  1860. +
  1861. + nextchar = channel->encoded_read_buf->str;
  1862. +
  1863. + do
  1864. + {
  1865. + prevchar = nextchar;
  1866. + nextchar = g_utf8_next_char (nextchar);
  1867. + g_assert (nextchar != prevchar); /* Possible for *prevchar of -1 or -2 */
  1868. + }
  1869. + while (nextchar < channel->encoded_read_buf->str + got_bytes);
  1870. +
  1871. + if (nextchar > channel->encoded_read_buf->str + got_bytes)
  1872. + got_bytes = prevchar - channel->encoded_read_buf->str;
  1873. +
  1874. + g_assert (got_bytes > 0 || count < 6);
  1875. + }
  1876. +
  1877. + memcpy (buf, USE_BUF (channel)->str, got_bytes);
  1878. + g_string_erase (USE_BUF (channel), 0, got_bytes);
  1879. +
  1880. + if (bytes_read)
  1881. + *bytes_read = got_bytes;
  1882. +
  1883. + return G_IO_STATUS_NORMAL;
  1884. +}
  1885. +
  1886. +/**
  1887. + * g_io_channel_read_unichar:
  1888. + * @channel: a #GIOChannel
  1889. + * @thechar: a location to return a character
  1890. + * @error: a location to return an error of type #GConvertError
  1891. + * or #GIOChannelError
  1892. + *
  1893. + * Reads a Unicode character from @channel.
  1894. + * This function cannot be called on a channel with %NULL encoding.
  1895. + *
  1896. + * Return value: a #GIOStatus
  1897. + **/
  1898. +GIOStatus
  1899. +g_io_channel_read_unichar (GIOChannel *channel,
  1900. + gunichar *thechar,
  1901. + GError **error)
  1902. +{
  1903. + GIOStatus status = G_IO_STATUS_NORMAL;
  1904. +
  1905. + g_return_val_if_fail (channel != NULL, G_IO_STATUS_ERROR);
  1906. + g_return_val_if_fail (channel->encoding != NULL, G_IO_STATUS_ERROR);
  1907. + g_return_val_if_fail ((error == NULL) || (*error == NULL),
  1908. + G_IO_STATUS_ERROR);
  1909. + g_return_val_if_fail (channel->is_readable, G_IO_STATUS_ERROR);
  1910. +
  1911. + while (BUF_LEN (channel->encoded_read_buf) == 0 && status == G_IO_STATUS_NORMAL)
  1912. + status = g_io_channel_fill_buffer (channel, error);
  1913. +
  1914. + /* Only return an error if we have no data */
  1915. +
  1916. + if (BUF_LEN (USE_BUF (channel)) == 0)
  1917. + {
  1918. + g_assert (status != G_IO_STATUS_NORMAL);
  1919. +
  1920. + if (status == G_IO_STATUS_EOF && BUF_LEN (channel->read_buf) > 0)
  1921. + {
  1922. + g_set_error (error, G_CONVERT_ERROR,
  1923. + G_CONVERT_ERROR_PARTIAL_INPUT,
  1924. + _("Leftover unconverted data in read buffer"));
  1925. + status = G_IO_STATUS_ERROR;
  1926. + }
  1927. +
  1928. + if (thechar)
  1929. + *thechar = (gunichar) -1;
  1930. +
  1931. + return status;
  1932. + }
  1933. +
  1934. + if (status == G_IO_STATUS_ERROR)
  1935. + g_clear_error (error);
  1936. +
  1937. + if (thechar)
  1938. + *thechar = g_utf8_get_char (channel->encoded_read_buf->str);
  1939. +
  1940. + g_string_erase (channel->encoded_read_buf, 0,
  1941. + g_utf8_next_char (channel->encoded_read_buf->str)
  1942. + - channel->encoded_read_buf->str);
  1943. +
  1944. + return G_IO_STATUS_NORMAL;
  1945. +}
  1946. +
  1947. +/**
  1948. + * g_io_channel_write_chars:
  1949. + * @channel: a #GIOChannel
  1950. + * @buf: a buffer to write data from
  1951. + * @count: the size of the buffer. If -1, the buffer
  1952. + * is taken to be a nul-terminated string.
  1953. + * @bytes_written: The number of bytes written. This can be nonzero
  1954. + * even if the return value is not %G_IO_STATUS_NORMAL.
  1955. + * If the return value is %G_IO_STATUS_NORMAL and the
  1956. + * channel is blocking, this will always be equal
  1957. + * to @count if @count >= 0.
  1958. + * @error: a location to return an error of type #GConvertError
  1959. + * or #GIOChannelError
  1960. + *
  1961. + * Replacement for g_io_channel_write() with the new API.
  1962. + *
  1963. + * On seekable channels with encodings other than %NULL or UTF-8, generic
  1964. + * mixing of reading and writing is not allowed. A call to g_io_channel_write_chars ()
  1965. + * may only be made on a channel from which data has been read in the
  1966. + * cases described in the documentation for g_io_channel_set_encoding ().
  1967. + *
  1968. + * Return value: the status of the operation.
  1969. + **/
  1970. +GIOStatus
  1971. +g_io_channel_write_chars (GIOChannel *channel,
  1972. + const gchar *buf,
  1973. + gssize count,
  1974. + gsize *bytes_written,
  1975. + GError **error)
  1976. +{
  1977. + GIOStatus status;
  1978. + gssize wrote_bytes = 0;
  1979. +
  1980. + g_return_val_if_fail (channel != NULL, G_IO_STATUS_ERROR);
  1981. + g_return_val_if_fail ((error == NULL) || (*error == NULL),
  1982. + G_IO_STATUS_ERROR);
  1983. + g_return_val_if_fail (channel->is_writeable, G_IO_STATUS_ERROR);
  1984. +
  1985. + if ((count < 0) && buf)
  1986. + count = strlen (buf);
  1987. +
  1988. + if (count == 0)
  1989. + {
  1990. + if (bytes_written)
  1991. + *bytes_written = 0;
  1992. + return G_IO_STATUS_NORMAL;
  1993. + }
  1994. +
  1995. + g_return_val_if_fail (buf != NULL, G_IO_STATUS_ERROR);
  1996. + g_return_val_if_fail (count > 0, G_IO_STATUS_ERROR);
  1997. +
  1998. + /* Raw write case */
  1999. +
  2000. + if (!channel->use_buffer)
  2001. + {
  2002. + gsize tmp_bytes;
  2003. +
  2004. + g_assert (!channel->write_buf || channel->write_buf->len == 0);
  2005. + g_assert (channel->partial_write_buf[0] == '\0');
  2006. +
  2007. + status = channel->funcs->io_write (channel, buf, count, &tmp_bytes, error);
  2008. +
  2009. + if (bytes_written)
  2010. + *bytes_written = tmp_bytes;
  2011. +
  2012. + return status;
  2013. + }
  2014. +
  2015. + /* General case */
  2016. +
  2017. + if (channel->is_seekable && (( BUF_LEN (channel->read_buf) > 0)
  2018. + || (BUF_LEN (channel->encoded_read_buf) > 0)))
  2019. + {
  2020. + if (channel->do_encode && BUF_LEN (channel->encoded_read_buf) > 0)
  2021. + {
  2022. + g_warning("Mixed reading and writing not allowed on encoded files");
  2023. + return G_IO_STATUS_ERROR;
  2024. + }
  2025. + status = g_io_channel_seek_position (channel, 0, G_SEEK_CUR, error);
  2026. + if (status != G_IO_STATUS_NORMAL)
  2027. + {
  2028. + if (bytes_written)
  2029. + *bytes_written = 0;
  2030. + return status;
  2031. + }
  2032. + }
  2033. +
  2034. + if (!channel->write_buf)
  2035. + channel->write_buf = g_string_sized_new (channel->buf_size);
  2036. +
  2037. + while (wrote_bytes < count)
  2038. + {
  2039. + gsize space_in_buf;
  2040. +
  2041. + /* If the buffer is full, try a write immediately. In
  2042. + * the nonblocking case, this prevents the user from
  2043. + * writing just a little bit to the buffer every time
  2044. + * and never receiving an EAGAIN.
  2045. + */
  2046. +
  2047. + if (channel->write_buf->len >= channel->buf_size - MAX_CHAR_SIZE)
  2048. + {
  2049. + gsize did_write = 0, this_time;
  2050. +
  2051. + do
  2052. + {
  2053. + status = channel->funcs->io_write (channel, channel->write_buf->str
  2054. + + did_write, channel->write_buf->len
  2055. + - did_write, &this_time, error);
  2056. + did_write += this_time;
  2057. + }
  2058. + while (status == G_IO_STATUS_NORMAL &&
  2059. + did_write < MIN (channel->write_buf->len, MAX_CHAR_SIZE));
  2060. +
  2061. + g_string_erase (channel->write_buf, 0, did_write);
  2062. +
  2063. + if (status != G_IO_STATUS_NORMAL)
  2064. + {
  2065. + if (status == G_IO_STATUS_AGAIN && wrote_bytes > 0)
  2066. + status = G_IO_STATUS_NORMAL;
  2067. + if (bytes_written)
  2068. + *bytes_written = wrote_bytes;
  2069. + return status;
  2070. + }
  2071. + }
  2072. +
  2073. + space_in_buf = MAX (channel->buf_size, channel->write_buf->allocated_len - 1)
  2074. + - channel->write_buf->len; /* 1 for NULL */
  2075. +
  2076. + /* This is only true because g_io_channel_set_buffer_size ()
  2077. + * ensures that channel->buf_size >= MAX_CHAR_SIZE.
  2078. + */
  2079. + g_assert (space_in_buf >= MAX_CHAR_SIZE);
  2080. +
  2081. + if (!channel->encoding)
  2082. + {
  2083. + gssize write_this = MIN (space_in_buf, count - wrote_bytes);
  2084. +
  2085. + g_string_append_len (channel->write_buf, buf, write_this);
  2086. + buf += write_this;
  2087. + wrote_bytes += write_this;
  2088. + }
  2089. + else
  2090. + {
  2091. + const gchar *from_buf;
  2092. + gsize from_buf_len, from_buf_old_len, left_len;
  2093. + gsize err;
  2094. + gint errnum;
  2095. +
  2096. + if (channel->partial_write_buf[0] != '\0')
  2097. + {
  2098. + g_assert (wrote_bytes == 0);
  2099. +
  2100. + from_buf = channel->partial_write_buf;
  2101. + from_buf_old_len = strlen (channel->partial_write_buf);
  2102. + g_assert (from_buf_old_len > 0);
  2103. + from_buf_len = MIN (6, from_buf_old_len + count);
  2104. +
  2105. + memcpy (channel->partial_write_buf + from_buf_old_len, buf,
  2106. + from_buf_len - from_buf_old_len);
  2107. + }
  2108. + else
  2109. + {
  2110. + from_buf = buf;
  2111. + from_buf_len = count - wrote_bytes;
  2112. + from_buf_old_len = 0;
  2113. + }
  2114. +
  2115. +reconvert:
  2116. +
  2117. + if (!channel->do_encode) /* UTF-8 encoding */
  2118. + {
  2119. + const gchar *badchar;
  2120. + gsize try_len = MIN (from_buf_len, space_in_buf);
  2121. +
  2122. + /* UTF-8, just validate, emulate g_iconv */
  2123. +
  2124. + if (!g_utf8_validate (from_buf, try_len, &badchar))
  2125. + {
  2126. + gunichar try_char;
  2127. + gsize incomplete_len = from_buf + try_len - badchar;
  2128. +
  2129. + left_len = from_buf + from_buf_len - badchar;
  2130. +
  2131. + try_char = g_utf8_get_char_validated (badchar, incomplete_len);
  2132. +
  2133. + switch (try_char)
  2134. + {
  2135. + case -2:
  2136. + g_assert (incomplete_len < 6);
  2137. + if (try_len == from_buf_len)
  2138. + {
  2139. + errnum = EINVAL;
  2140. + err = (gsize) -1;
  2141. + }
  2142. + else
  2143. + {
  2144. + errnum = 0;
  2145. + err = (gsize) 0;
  2146. + }
  2147. + break;
  2148. + case -1:
  2149. + g_warning ("Invalid UTF-8 passed to g_io_channel_write_chars().");
  2150. + /* FIXME bail here? */
  2151. + errnum = EILSEQ;
  2152. + err = (gsize) -1;
  2153. + break;
  2154. + default:
  2155. + g_assert_not_reached ();
  2156. + err = (gsize) -1;
  2157. + errnum = 0; /* Don't confunse the compiler */
  2158. + }
  2159. + }
  2160. + else
  2161. + {
  2162. + err = (gsize) 0;
  2163. + errnum = 0;
  2164. + left_len = from_buf_len - try_len;
  2165. + }
  2166. +
  2167. + g_string_append_len (channel->write_buf, from_buf,
  2168. + from_buf_len - left_len);
  2169. + from_buf += from_buf_len - left_len;
  2170. + }
  2171. + else
  2172. + {
  2173. + gchar *outbuf;
  2174. +
  2175. + left_len = from_buf_len;
  2176. + g_string_set_size (channel->write_buf, channel->write_buf->len
  2177. + + space_in_buf);
  2178. + outbuf = channel->write_buf->str + channel->write_buf->len
  2179. + - space_in_buf;
  2180. + err = g_iconv (channel->write_cd, (gchar **) &from_buf, &left_len,
  2181. + &outbuf, &space_in_buf);
  2182. + errnum = errno;
  2183. + g_string_truncate (channel->write_buf, channel->write_buf->len
  2184. + - space_in_buf);
  2185. + }
  2186. +
  2187. + if (err == (gsize) -1)
  2188. + {
  2189. + switch (errnum)
  2190. + {
  2191. + case EINVAL:
  2192. + g_assert (left_len < 6);
  2193. +
  2194. + if (from_buf_old_len == 0)
  2195. + {
  2196. + /* Not from partial_write_buf */
  2197. +
  2198. + memcpy (channel->partial_write_buf, from_buf, left_len);
  2199. + channel->partial_write_buf[left_len] = '\0';
  2200. + if (bytes_written)
  2201. + *bytes_written = count;
  2202. + return G_IO_STATUS_NORMAL;
  2203. + }
  2204. +
  2205. + /* Working in partial_write_buf */
  2206. +
  2207. + if (left_len == from_buf_len)
  2208. + {
  2209. + /* Didn't convert anything, must still have
  2210. + * less than a full character
  2211. + */
  2212. +
  2213. + g_assert (count == from_buf_len - from_buf_old_len);
  2214. +
  2215. + channel->partial_write_buf[from_buf_len] = '\0';
  2216. +
  2217. + if (bytes_written)
  2218. + *bytes_written = count;
  2219. +
  2220. + return G_IO_STATUS_NORMAL;
  2221. + }
  2222. +
  2223. + g_assert (from_buf_len - left_len >= from_buf_old_len);
  2224. +
  2225. + /* We converted all the old data. This is fine */
  2226. +
  2227. + break;
  2228. + case E2BIG:
  2229. + if (from_buf_len == left_len)
  2230. + {
  2231. + /* Nothing was written, add enough space for
  2232. + * at least one character.
  2233. + */
  2234. + space_in_buf += MAX_CHAR_SIZE;
  2235. + goto reconvert;
  2236. + }
  2237. + break;
  2238. + case EILSEQ:
  2239. + g_set_error (error, G_CONVERT_ERROR,
  2240. + G_CONVERT_ERROR_ILLEGAL_SEQUENCE,
  2241. + _("Invalid byte sequence in conversion input"));
  2242. + if (from_buf_old_len > 0 && from_buf_len == left_len)
  2243. + g_warning ("Illegal sequence due to partial character "
  2244. + "at the end of a previous write.\n");
  2245. + else
  2246. + wrote_bytes += from_buf_len - left_len - from_buf_old_len;
  2247. + if (bytes_written)
  2248. + *bytes_written = wrote_bytes;
  2249. + channel->partial_write_buf[0] = '\0';
  2250. + return G_IO_STATUS_ERROR;
  2251. + default:
  2252. + g_set_error (error, G_CONVERT_ERROR, G_CONVERT_ERROR_FAILED,
  2253. + _("Error during conversion: %s"), g_strerror (errnum));
  2254. + if (from_buf_len >= left_len + from_buf_old_len)
  2255. + wrote_bytes += from_buf_len - left_len - from_buf_old_len;
  2256. + if (bytes_written)
  2257. + *bytes_written = wrote_bytes;
  2258. + channel->partial_write_buf[0] = '\0';
  2259. + return G_IO_STATUS_ERROR;
  2260. + }
  2261. + }
  2262. +
  2263. + g_assert (from_buf_len - left_len >= from_buf_old_len);
  2264. +
  2265. + wrote_bytes += from_buf_len - left_len - from_buf_old_len;
  2266. +
  2267. + if (from_buf_old_len > 0)
  2268. + {
  2269. + /* We were working in partial_write_buf */
  2270. +
  2271. + buf += from_buf_len - left_len - from_buf_old_len;
  2272. + channel->partial_write_buf[0] = '\0';
  2273. + }
  2274. + else
  2275. + buf = from_buf;
  2276. + }
  2277. + }
  2278. +
  2279. + if (bytes_written)
  2280. + *bytes_written = count;
  2281. +
  2282. + return G_IO_STATUS_NORMAL;
  2283. +}
  2284. +
  2285. +/**
  2286. + * g_io_channel_write_unichar:
  2287. + * @channel: a #GIOChannel
  2288. + * @thechar: a character
  2289. + * @error: location to return an error of type #GConvertError
  2290. + * or #GIOChannelError
  2291. + *
  2292. + * Writes a Unicode character to @channel.
  2293. + * This function cannot be called on a channel with %NULL encoding.
  2294. + *
  2295. + * Return value: a #GIOStatus
  2296. + **/
  2297. +GIOStatus
  2298. +g_io_channel_write_unichar (GIOChannel *channel,
  2299. + gunichar thechar,
  2300. + GError **error)
  2301. +{
  2302. + GIOStatus status;
  2303. + gchar static_buf[6];
  2304. + gsize char_len, wrote_len;
  2305. +
  2306. + g_return_val_if_fail (channel != NULL, G_IO_STATUS_ERROR);
  2307. + g_return_val_if_fail (channel->encoding != NULL, G_IO_STATUS_ERROR);
  2308. + g_return_val_if_fail ((error == NULL) || (*error == NULL),
  2309. + G_IO_STATUS_ERROR);
  2310. + g_return_val_if_fail (channel->is_writeable, G_IO_STATUS_ERROR);
  2311. +
  2312. + char_len = g_unichar_to_utf8 (thechar, static_buf);
  2313. +
  2314. + if (channel->partial_write_buf[0] != '\0')
  2315. + {
  2316. + g_warning ("Partial charater written before writing unichar.\n");
  2317. + channel->partial_write_buf[0] = '\0';
  2318. + }
  2319. +
  2320. + status = g_io_channel_write_chars (channel, static_buf,
  2321. + char_len, &wrote_len, error);
  2322. +
  2323. + /* We validate UTF-8, so we can't get a partial write */
  2324. +
  2325. + g_assert (wrote_len == char_len || status != G_IO_STATUS_NORMAL);
  2326. +
  2327. + return status;
  2328. +}
  2329. +
  2330. +/**
  2331. + * g_io_channel_error_quark:
  2332. + *
  2333. + * Return value: the quark used as %G_IO_CHANNEL_ERROR
  2334. + **/
  2335. +GQuark
  2336. +g_io_channel_error_quark (void)
  2337. +{
  2338. + return g_quark_from_static_string ("g-io-channel-error-quark");
  2339. +}
  2340. diff --git a/clients/Instantbird/giounix.c b/clients/Instantbird/giounix.c
  2341. new file mode 100755
  2342. index 0000000..87197ed
  2343. --- /dev/null
  2344. +++ b/clients/Instantbird/giounix.c
  2345. @@ -0,0 +1,598 @@
  2346. +/* GLIB - Library of useful routines for C programming
  2347. + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
  2348. + *
  2349. + * giounix.c: IO Channels using unix file descriptors
  2350. + * Copyright 1998 Owen Taylor
  2351. + *
  2352. + * This library is free software; you can redistribute it and/or
  2353. + * modify it under the terms of the GNU Lesser General Public
  2354. + * License as published by the Free Software Foundation; either
  2355. + * version 2 of the License, or (at your option) any later version.
  2356. + *
  2357. + * This library is distributed in the hope that it will be useful,
  2358. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  2359. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  2360. + * Lesser General Public License for more details.
  2361. + *
  2362. + * You should have received a copy of the GNU Lesser General Public
  2363. + * License along with this library; if not, write to the
  2364. + * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  2365. + * Boston, MA 02111-1307, USA.
  2366. + */
  2367. +
  2368. +/*
  2369. + * Modified by the GLib Team and others 1997-2000. See the AUTHORS
  2370. + * file for a list of people on the GLib Team. See the ChangeLog
  2371. + * files for a list of changes. These files are distributed with
  2372. + * GLib at ftp://ftp.gtk.org/pub/gtk/.
  2373. + */
  2374. +
  2375. +/*
  2376. + * MT safe
  2377. + */
  2378. +
  2379. +#include "config.h"
  2380. +
  2381. +#define _POSIX_SOURCE /* for SSIZE_MAX */
  2382. +
  2383. +#include <sys/types.h>
  2384. +#include <sys/stat.h>
  2385. +#include <stdio.h>
  2386. +#include <unistd.h>
  2387. +#include <errno.h>
  2388. +#include <string.h>
  2389. +#include <fcntl.h>
  2390. +
  2391. +#include "glib.h"
  2392. +#include "galias.h"
  2393. +
  2394. +/*
  2395. + * Unix IO Channels
  2396. + */
  2397. +
  2398. +typedef struct _GIOUnixChannel GIOUnixChannel;
  2399. +typedef struct _GIOUnixWatch GIOUnixWatch;
  2400. +
  2401. +struct _GIOUnixChannel
  2402. +{
  2403. + GIOChannel channel;
  2404. + gint fd;
  2405. +};
  2406. +
  2407. +struct _GIOUnixWatch
  2408. +{
  2409. + GSource source;
  2410. + GPollFD pollfd;
  2411. + GIOChannel *channel;
  2412. + GIOCondition condition;
  2413. +};
  2414. +
  2415. +
  2416. +static GIOStatus g_io_unix_read (GIOChannel *channel,
  2417. + gchar *buf,
  2418. + gsize count,
  2419. + gsize *bytes_read,
  2420. + GError **err);
  2421. +static GIOStatus g_io_unix_write (GIOChannel *channel,
  2422. + const gchar *buf,
  2423. + gsize count,
  2424. + gsize *bytes_written,
  2425. + GError **err);
  2426. +static GIOStatus g_io_unix_seek (GIOChannel *channel,
  2427. + gint64 offset,
  2428. + GSeekType type,
  2429. + GError **err);
  2430. +static GIOStatus g_io_unix_close (GIOChannel *channel,
  2431. + GError **err);
  2432. +static void g_io_unix_free (GIOChannel *channel);
  2433. +static GSource* g_io_unix_create_watch (GIOChannel *channel,
  2434. + GIOCondition condition);
  2435. +static GIOStatus g_io_unix_set_flags (GIOChannel *channel,
  2436. + GIOFlags flags,
  2437. + GError **err);
  2438. +static GIOFlags g_io_unix_get_flags (GIOChannel *channel);
  2439. +
  2440. +static gboolean g_io_unix_prepare (GSource *source,
  2441. + gint *timeout);
  2442. +static gboolean g_io_unix_check (GSource *source);
  2443. +static gboolean g_io_unix_dispatch (GSource *source,
  2444. + GSourceFunc callback,
  2445. + gpointer user_data);
  2446. +static void g_io_unix_finalize (GSource *source);
  2447. +
  2448. +GSourceFuncs g_io_watch_funcs = {
  2449. + g_io_unix_prepare,
  2450. + g_io_unix_check,
  2451. + g_io_unix_dispatch,
  2452. + g_io_unix_finalize
  2453. +};
  2454. +
  2455. +static GIOFuncs unix_channel_funcs = {
  2456. + g_io_unix_read,
  2457. + g_io_unix_write,
  2458. + g_io_unix_seek,
  2459. + g_io_unix_close,
  2460. + g_io_unix_create_watch,
  2461. + g_io_unix_free,
  2462. + g_io_unix_set_flags,
  2463. + g_io_unix_get_flags,
  2464. +};
  2465. +
  2466. +static gboolean
  2467. +g_io_unix_prepare (GSource *source,
  2468. + gint *timeout)
  2469. +{
  2470. + GIOUnixWatch *watch = (GIOUnixWatch *)source;
  2471. + GIOCondition buffer_condition = g_io_channel_get_buffer_condition (watch->channel);
  2472. +
  2473. + *timeout = -1;
  2474. +
  2475. + /* Only return TRUE here if _all_ bits in watch->condition will be set
  2476. + */
  2477. + return ((watch->condition & buffer_condition) == watch->condition);
  2478. +}
  2479. +
  2480. +static gboolean
  2481. +g_io_unix_check (GSource *source)
  2482. +{
  2483. + GIOUnixWatch *watch = (GIOUnixWatch *)source;
  2484. + GIOCondition buffer_condition = g_io_channel_get_buffer_condition (watch->channel);
  2485. + GIOCondition poll_condition = watch->pollfd.revents;
  2486. +
  2487. + return ((poll_condition | buffer_condition) & watch->condition);
  2488. +}
  2489. +
  2490. +static gboolean
  2491. +g_io_unix_dispatch (GSource *source,
  2492. + GSourceFunc callback,
  2493. + gpointer user_data)
  2494. +
  2495. +{
  2496. + GIOFunc func = (GIOFunc)callback;
  2497. + GIOUnixWatch *watch = (GIOUnixWatch *)source;
  2498. + GIOCondition buffer_condition = g_io_channel_get_buffer_condition (watch->channel);
  2499. +
  2500. + if (!func)
  2501. + {
  2502. + g_warning ("IO watch dispatched without callback\n"
  2503. + "You must call g_source_connect().");
  2504. + return FALSE;
  2505. + }
  2506. +
  2507. + return (*func) (watch->channel,
  2508. + (watch->pollfd.revents | buffer_condition) & watch->condition,
  2509. + user_data);
  2510. +}
  2511. +
  2512. +static void
  2513. +g_io_unix_finalize (GSource *source)
  2514. +{
  2515. + GIOUnixWatch *watch = (GIOUnixWatch *)source;
  2516. +
  2517. + g_io_channel_unref (watch->channel);
  2518. +}
  2519. +
  2520. +static GIOStatus
  2521. +g_io_unix_read (GIOChannel *channel,
  2522. + gchar *buf,
  2523. + gsize count,
  2524. + gsize *bytes_read,
  2525. + GError **err)
  2526. +{
  2527. + GIOUnixChannel *unix_channel = (GIOUnixChannel *)channel;
  2528. + gssize result;
  2529. +
  2530. + if (count > SSIZE_MAX) /* At least according to the Debian manpage for read */
  2531. + count = SSIZE_MAX;
  2532. +
  2533. + retry:
  2534. + result = read (unix_channel->fd, buf, count);
  2535. +
  2536. + if (result < 0)
  2537. + {
  2538. + *bytes_read = 0;
  2539. +
  2540. + switch (errno)
  2541. + {
  2542. +#ifdef EINTR
  2543. + case EINTR:
  2544. + goto retry;
  2545. +#endif
  2546. +#ifdef EAGAIN
  2547. + case EAGAIN:
  2548. + return G_IO_STATUS_AGAIN;
  2549. +#endif
  2550. + default:
  2551. + g_set_error (err, G_IO_CHANNEL_ERROR,
  2552. + g_io_channel_error_from_errno (errno),
  2553. + g_strerror (errno));
  2554. + return G_IO_STATUS_ERROR;
  2555. + }
  2556. + }
  2557. +
  2558. + *bytes_read = result;
  2559. +
  2560. + return (result > 0) ? G_IO_STATUS_NORMAL : G_IO_STATUS_EOF;
  2561. +}
  2562. +
  2563. +static GIOStatus
  2564. +g_io_unix_write (GIOChannel *channel,
  2565. + const gchar *buf,
  2566. + gsize count,
  2567. + gsize *bytes_written,
  2568. + GError **err)
  2569. +{
  2570. + GIOUnixChannel *unix_channel = (GIOUnixChannel *)channel;
  2571. + gssize result;
  2572. +
  2573. + retry:
  2574. + result = write (unix_channel->fd, buf, count);
  2575. +
  2576. + if (result < 0)
  2577. + {
  2578. + *bytes_written = 0;
  2579. +
  2580. + switch (errno)
  2581. + {
  2582. +#ifdef EINTR
  2583. + case EINTR:
  2584. + goto retry;
  2585. +#endif
  2586. +#ifdef EAGAIN
  2587. + case EAGAIN:
  2588. + return G_IO_STATUS_AGAIN;
  2589. +#endif
  2590. + default:
  2591. + g_set_error (err, G_IO_CHANNEL_ERROR,
  2592. + g_io_channel_error_from_errno (errno),
  2593. + g_strerror (errno));
  2594. + return G_IO_STATUS_ERROR;
  2595. + }
  2596. + }
  2597. +
  2598. + *bytes_written = result;
  2599. +
  2600. + return G_IO_STATUS_NORMAL;
  2601. +}
  2602. +
  2603. +static GIOStatus
  2604. +g_io_unix_seek (GIOChannel *channel,
  2605. + gint64 offset,
  2606. + GSeekType type,
  2607. + GError **err)
  2608. +{
  2609. + GIOUnixChannel *unix_channel = (GIOUnixChannel *)channel;
  2610. + int whence;
  2611. + off_t tmp_offset;
  2612. + off_t result;
  2613. +
  2614. + switch (type)
  2615. + {
  2616. + case G_SEEK_SET:
  2617. + whence = SEEK_SET;
  2618. + break;
  2619. + case G_SEEK_CUR:
  2620. + whence = SEEK_CUR;
  2621. + break;
  2622. + case G_SEEK_END:
  2623. + whence = SEEK_END;
  2624. + break;
  2625. + default:
  2626. + whence = -1; /* Shut the compiler up */
  2627. + g_assert_not_reached ();
  2628. + }
  2629. +
  2630. + tmp_offset = offset;
  2631. + if (tmp_offset != offset)
  2632. + {
  2633. + g_set_error (err, G_IO_CHANNEL_ERROR,
  2634. + g_io_channel_error_from_errno (EINVAL),
  2635. + g_strerror (EINVAL));
  2636. + return G_IO_STATUS_ERROR;
  2637. + }
  2638. +
  2639. + result = lseek (unix_channel->fd, tmp_offset, whence);
  2640. +
  2641. + if (result < 0)
  2642. + {
  2643. + g_set_error (err, G_IO_CHANNEL_ERROR,
  2644. + g_io_channel_error_from_errno (errno),
  2645. + g_strerror (errno));
  2646. + return G_IO_STATUS_ERROR;
  2647. + }
  2648. +
  2649. + return G_IO_STATUS_NORMAL;
  2650. +}
  2651. +
  2652. +
  2653. +static GIOStatus
  2654. +g_io_unix_close (GIOChannel *channel,
  2655. + GError **err)
  2656. +{
  2657. + GIOUnixChannel *unix_channel = (GIOUnixChannel *)channel;
  2658. +
  2659. + if (close (unix_channel->fd) < 0)
  2660. + {
  2661. + g_set_error (err, G_IO_CHANNEL_ERROR,
  2662. + g_io_channel_error_from_errno (errno),
  2663. + g_strerror (errno));
  2664. + return G_IO_STATUS_ERROR;
  2665. + }
  2666. +
  2667. + return G_IO_STATUS_NORMAL;
  2668. +}
  2669. +
  2670. +static void
  2671. +g_io_unix_free (GIOChannel *channel)
  2672. +{
  2673. + GIOUnixChannel *unix_channel = (GIOUnixChannel *)channel;
  2674. +
  2675. + g_free (unix_channel);
  2676. +}
  2677. +
  2678. +static GSource *
  2679. +g_io_unix_create_watch (GIOChannel *channel,
  2680. + GIOCondition condition)
  2681. +{
  2682. + GIOUnixChannel *unix_channel = (GIOUnixChannel *)channel;
  2683. + GSource *source;
  2684. + GIOUnixWatch *watch;
  2685. +
  2686. +
  2687. + source = g_source_new (&g_io_watch_funcs, sizeof (GIOUnixWatch));
  2688. + watch = (GIOUnixWatch *)source;
  2689. +
  2690. + watch->channel = channel;
  2691. + g_io_channel_ref (channel);
  2692. +
  2693. + watch->condition = condition;
  2694. +
  2695. + watch->pollfd.fd = unix_channel->fd;
  2696. + watch->pollfd.events = condition;
  2697. +
  2698. + g_source_add_poll (source, &watch->pollfd);
  2699. +
  2700. + return source;
  2701. +}
  2702. +
  2703. +static GIOStatus
  2704. +g_io_unix_set_flags (GIOChannel *channel,
  2705. + GIOFlags flags,
  2706. + GError **err)
  2707. +{
  2708. + glong fcntl_flags;
  2709. + GIOUnixChannel *unix_channel = (GIOUnixChannel *) channel;
  2710. +
  2711. + fcntl_flags = 0;
  2712. +
  2713. + if (flags & G_IO_FLAG_APPEND)
  2714. + fcntl_flags |= O_APPEND;
  2715. + if (flags & G_IO_FLAG_NONBLOCK)
  2716. +#ifdef O_NONBLOCK
  2717. + fcntl_flags |= O_NONBLOCK;
  2718. +#else
  2719. + fcntl_flags |= O_NDELAY;
  2720. +#endif
  2721. +
  2722. + if (fcntl (unix_channel->fd, F_SETFL, fcntl_flags) == -1)
  2723. + {
  2724. + g_set_error (err, G_IO_CHANNEL_ERROR,
  2725. + g_io_channel_error_from_errno (errno),
  2726. + g_strerror (errno));
  2727. + return G_IO_STATUS_ERROR;
  2728. + }
  2729. +
  2730. + return G_IO_STATUS_NORMAL;
  2731. +}
  2732. +
  2733. +static GIOFlags
  2734. +g_io_unix_get_flags (GIOChannel *channel)
  2735. +{
  2736. + GIOFlags flags = 0;
  2737. + glong fcntl_flags;
  2738. + GIOUnixChannel *unix_channel = (GIOUnixChannel *) channel;
  2739. +
  2740. + fcntl_flags = fcntl (unix_channel->fd, F_GETFL);
  2741. +
  2742. + if (fcntl_flags == -1)
  2743. + {
  2744. + g_warning (G_STRLOC "Error while getting flags for FD: %s (%d)\n",
  2745. + g_strerror (errno), errno);
  2746. + return 0;
  2747. + }
  2748. +
  2749. + if (fcntl_flags & O_APPEND)
  2750. + flags |= G_IO_FLAG_APPEND;
  2751. +#ifdef O_NONBLOCK
  2752. + if (fcntl_flags & O_NONBLOCK)
  2753. +#else
  2754. + if (fcntl_flags & O_NDELAY)
  2755. +#endif
  2756. + flags |= G_IO_FLAG_NONBLOCK;
  2757. +
  2758. + switch (fcntl_flags & (O_RDONLY | O_WRONLY | O_RDWR))
  2759. + {
  2760. + case O_RDONLY:
  2761. + channel->is_readable = TRUE;
  2762. + channel->is_writeable = FALSE;
  2763. + break;
  2764. + case O_WRONLY:
  2765. + channel->is_readable = FALSE;
  2766. + channel->is_writeable = TRUE;
  2767. + break;
  2768. + case O_RDWR:
  2769. + channel->is_readable = TRUE;
  2770. + channel->is_writeable = TRUE;
  2771. + break;
  2772. + default:
  2773. + g_assert_not_reached ();
  2774. + }
  2775. +
  2776. + return flags;
  2777. +}
  2778. +
  2779. +GIOChannel *
  2780. +g_io_channel_new_file (const gchar *filename,
  2781. + const gchar *mode,
  2782. + GError **error)
  2783. +{
  2784. + int fid, flags;
  2785. + mode_t create_mode;
  2786. + GIOChannel *channel;
  2787. + enum { /* Cheesy hack */
  2788. + MODE_R = 1 << 0,
  2789. + MODE_W = 1 << 1,
  2790. + MODE_A = 1 << 2,
  2791. + MODE_PLUS = 1 << 3
  2792. + } mode_num;
  2793. + struct stat buffer;
  2794. +
  2795. + g_return_val_if_fail (filename != NULL, NULL);
  2796. + g_return_val_if_fail (mode != NULL, NULL);
  2797. + g_return_val_if_fail ((error == NULL) || (*error == NULL), NULL);
  2798. +
  2799. + switch (mode[0])
  2800. + {
  2801. + case 'r':
  2802. + mode_num = MODE_R;
  2803. + break;
  2804. + case 'w':
  2805. + mode_num = MODE_W;
  2806. + break;
  2807. + case 'a':
  2808. + mode_num = MODE_A;
  2809. + break;
  2810. + default:
  2811. + g_warning ("Invalid GIOFileMode %s.\n", mode);
  2812. + return NULL;
  2813. + }
  2814. +
  2815. + switch (mode[1])
  2816. + {
  2817. + case '\0':
  2818. + break;
  2819. + case '+':
  2820. + if (mode[2] == '\0')
  2821. + {
  2822. + mode_num |= MODE_PLUS;
  2823. + break;
  2824. + }
  2825. + /* Fall through */
  2826. + default:
  2827. + g_warning ("Invalid GIOFileMode %s.\n", mode);
  2828. + return NULL;
  2829. + }
  2830. +
  2831. + switch (mode_num)
  2832. + {
  2833. + case MODE_R:
  2834. + flags = O_RDONLY;
  2835. + break;
  2836. + case MODE_W:
  2837. + flags = O_WRONLY | O_TRUNC | O_CREAT;
  2838. + break;
  2839. + case MODE_A:
  2840. + flags = O_WRONLY | O_APPEND | O_CREAT;
  2841. + break;
  2842. + case MODE_R | MODE_PLUS:
  2843. + flags = O_RDWR;
  2844. + break;
  2845. + case MODE_W | MODE_PLUS:
  2846. + flags = O_RDWR | O_TRUNC | O_CREAT;
  2847. + break;
  2848. + case MODE_A | MODE_PLUS:
  2849. + flags = O_RDWR | O_APPEND | O_CREAT;
  2850. + break;
  2851. + default:
  2852. + g_assert_not_reached ();
  2853. + flags = 0;
  2854. + }
  2855. +
  2856. + create_mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
  2857. + fid = open (filename, flags, create_mode);
  2858. + if (fid == -1)
  2859. + {
  2860. + g_set_error (error, G_FILE_ERROR,
  2861. + g_file_error_from_errno (errno),
  2862. + g_strerror (errno));
  2863. + return (GIOChannel *)NULL;
  2864. + }
  2865. +
  2866. + if (fstat (fid, &buffer) == -1) /* In case someone opens a FIFO */
  2867. + {
  2868. + close (fid);
  2869. + g_set_error (error, G_FILE_ERROR,
  2870. + g_file_error_from_errno (errno),
  2871. + g_strerror (errno));
  2872. + return (GIOChannel *)NULL;
  2873. + }
  2874. +
  2875. + channel = (GIOChannel *) g_new (GIOUnixChannel, 1);
  2876. +
  2877. + channel->is_seekable = S_ISREG (buffer.st_mode) || S_ISCHR (buffer.st_mode)
  2878. + || S_ISBLK (buffer.st_mode);
  2879. +
  2880. + switch (mode_num)
  2881. + {
  2882. + case MODE_R:
  2883. + channel->is_readable = TRUE;
  2884. + channel->is_writeable = FALSE;
  2885. + break;
  2886. + case MODE_W:
  2887. + case MODE_A:
  2888. + channel->is_readable = FALSE;
  2889. + channel->is_writeable = TRUE;
  2890. + break;
  2891. + case MODE_R | MODE_PLUS:
  2892. + case MODE_W | MODE_PLUS:
  2893. + case MODE_A | MODE_PLUS:
  2894. + channel->is_readable = TRUE;
  2895. + channel->is_writeable = TRUE;
  2896. + break;
  2897. + default:
  2898. + g_assert_not_reached ();
  2899. + }
  2900. +
  2901. + g_io_channel_init (channel);
  2902. + channel->close_on_unref = TRUE; /* must be after g_io_channel_init () */
  2903. + channel->funcs = &unix_channel_funcs;
  2904. +
  2905. + ((GIOUnixChannel *) channel)->fd = fid;
  2906. + return channel;
  2907. +}
  2908. +
  2909. +GIOChannel *
  2910. +g_io_channel_unix_new (gint fd)
  2911. +{
  2912. + struct stat buffer;
  2913. + GIOUnixChannel *unix_channel = g_new (GIOUnixChannel, 1);
  2914. + GIOChannel *channel = (GIOChannel *)unix_channel;
  2915. +
  2916. + g_io_channel_init (channel);
  2917. + channel->funcs = &unix_channel_funcs;
  2918. +
  2919. + unix_channel->fd = fd;
  2920. +
  2921. + /* I'm not sure if fstat on a non-file (e.g., socket) works
  2922. + * it should be safe to say if it fails, the fd isn't seekable.
  2923. + */
  2924. + /* Newer UNIX versions support S_ISSOCK(), fstat() will probably
  2925. + * succeed in most cases.
  2926. + */
  2927. + if (fstat (unix_channel->fd, &buffer) == 0)
  2928. + channel->is_seekable = S_ISREG (buffer.st_mode) || S_ISCHR (buffer.st_mode)
  2929. + || S_ISBLK (buffer.st_mode);
  2930. + else /* Assume not seekable */
  2931. + channel->is_seekable = FALSE;
  2932. +
  2933. + g_io_unix_get_flags (channel); /* Sets is_readable, is_writeable */
  2934. +
  2935. + return channel;
  2936. +}
  2937. +
  2938. +gint
  2939. +g_io_channel_unix_get_fd (GIOChannel *channel)
  2940. +{
  2941. + GIOUnixChannel *unix_channel = (GIOUnixChannel *)channel;
  2942. + return unix_channel->fd;
  2943. +}
  2944. diff --git a/clients/Instantbird/giowin32.c b/clients/Instantbird/giowin32.c
  2945. new file mode 100755
  2946. index 0000000..83cb86c
  2947. --- /dev/null
  2948. +++ b/clients/Instantbird/giowin32.c
  2949. @@ -0,0 +1,2129 @@
  2950. +/* GLIB - Library of useful routines for C programming
  2951. + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
  2952. + *
  2953. + * giowin32.c: IO Channels for Win32.
  2954. + * Copyright 1998 Owen Taylor and Tor Lillqvist
  2955. + * Copyright 1999-2000 Tor Lillqvist and Craig Setera
  2956. + * Copyright 2001-2003 Andrew Lanoix
  2957. + *
  2958. + * This library is free software; you can redistribute it and/or
  2959. + * modify it under the terms of the GNU Lesser General Public
  2960. + * License as published by the Free Software Foundation; either
  2961. + * version 2 of the License, or (at your option) any later version.
  2962. + *
  2963. + * This library is distributed in the hope that it will be useful,
  2964. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  2965. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  2966. + * Lesser General Public License for more details.
  2967. + *
  2968. + * You should have received a copy of the GNU Lesser General Public
  2969. + * License along with this library; if not, write to the
  2970. + * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  2971. + * Boston, MA 02111-1307, USA.
  2972. + */
  2973. +
  2974. +/*
  2975. + * Modified by the GLib Team and others 1997-2000. See the AUTHORS
  2976. + * file for a list of people on the GLib Team. See the ChangeLog
  2977. + * files for a list of changes. These files are distributed with
  2978. + * GLib at ftp://ftp.gtk.org/pub/gtk/.
  2979. + */
  2980. +
  2981. +#include "config.h"
  2982. +
  2983. +#include "glib.h"
  2984. +
  2985. +#include <stdlib.h>
  2986. +#include <winsock2.h>
  2987. +#include <windows.h>
  2988. +#include <conio.h>
  2989. +#include <fcntl.h>
  2990. +#include <io.h>
  2991. +#include <process.h>
  2992. +#include <errno.h>
  2993. +#include <sys/stat.h>
  2994. +
  2995. +#include "gstdio.h"
  2996. +#include "glibintl.h"
  2997. +
  2998. +#include "galias.h"
  2999. +
  3000. +typedef struct _GIOWin32Channel GIOWin32Channel;
  3001. +typedef struct _GIOWin32Watch GIOWin32Watch;
  3002. +
  3003. +#define BUFFER_SIZE 4096
  3004. +
  3005. +typedef enum {
  3006. + G_IO_WIN32_WINDOWS_MESSAGES, /* Windows messages */
  3007. + G_IO_WIN32_FILE_DESC, /* Unix-like file descriptors from
  3008. + * _open() or _pipe(), except for console IO.
  3009. + * Have to create separate thread to read.
  3010. + */
  3011. + G_IO_WIN32_CONSOLE, /* Console IO (usually stdin, stdout, stderr) */
  3012. + G_IO_WIN32_SOCKET /* Sockets. No separate thread */
  3013. +} GIOWin32ChannelType;
  3014. +
  3015. +struct _GIOWin32Channel {
  3016. + GIOChannel channel;
  3017. + gint fd; /* Either a Unix-like file handle as provided
  3018. + * by the Microsoft C runtime, or a SOCKET
  3019. + * as provided by WinSock.
  3020. + */
  3021. + GIOWin32ChannelType type;
  3022. +
  3023. + gboolean debug;
  3024. +
  3025. + /* This is used by G_IO_WIN32_WINDOWS_MESSAGES channels */
  3026. + HWND hwnd; /* handle of window, or NULL */
  3027. +
  3028. + /* Following fields are used by fd channels. */
  3029. + CRITICAL_SECTION mutex;
  3030. +
  3031. + int direction; /* 0 means we read from it,
  3032. + * 1 means we write to it.
  3033. + */
  3034. +
  3035. + gboolean running; /* Is reader thread running. FALSE if
  3036. + * EOF has been reached.
  3037. + */
  3038. + gboolean needs_close; /* If the channel has been closed while
  3039. + * the reader thread was still running.
  3040. + */
  3041. + guint thread_id; /* If non-NULL has a reader thread, or has
  3042. + * had.*/
  3043. + HANDLE data_avail_event;
  3044. +
  3045. + gushort revents;
  3046. +
  3047. + /* Following fields used by fd channels for input */
  3048. +
  3049. + /* Data is kept in a circular buffer. To be able to distinguish between
  3050. + * empty and full buffer, we cannot fill it completely, but have to
  3051. + * leave a one character gap.
  3052. + *
  3053. + * Data available is between indexes rdp and wrp-1 (modulo BUFFER_SIZE).
  3054. + *
  3055. + * Empty: wrp == rdp
  3056. + * Full: (wrp + 1) % BUFFER_SIZE == rdp
  3057. + * Partial: otherwise
  3058. + */
  3059. + guchar *buffer; /* (Circular) buffer */
  3060. + gint wrp, rdp; /* Buffer indices for writing and reading */
  3061. + HANDLE space_avail_event;
  3062. +
  3063. + /* Following fields used by socket channels */
  3064. + int event_mask;
  3065. + int last_events;
  3066. + int event;
  3067. + gboolean write_would_have_blocked;
  3068. +};
  3069. +
  3070. +#define LOCK(mutex) EnterCriticalSection (&mutex)
  3071. +#define UNLOCK(mutex) LeaveCriticalSection (&mutex)
  3072. +
  3073. +struct _GIOWin32Watch {
  3074. + GSource source;
  3075. + GPollFD pollfd;
  3076. + GIOChannel *channel;
  3077. + GIOCondition condition;
  3078. +};
  3079. +
  3080. +static void
  3081. +g_win32_print_access_mode (int flags)
  3082. +{
  3083. + g_print ("%s%s%s%s%s%s%s%s%s%s",
  3084. + ((flags & 0x3) == _O_RDWR ? "O_RDWR" :
  3085. + ((flags & 0x3) == _O_RDONLY ? "O_RDONLY" :
  3086. + ((flags & 0x3) == _O_WRONLY ? "O_WRONLY" : "0"))),
  3087. + (flags & _O_APPEND ? "|O_APPEND" : ""),
  3088. + (flags & _O_RANDOM ? "|O_RANDOM" : ""),
  3089. + (flags & _O_SEQUENTIAL ? "|O_SEQUENTIAL" : ""),
  3090. + (flags & _O_TEMPORARY ? "|O_TEMPORARY" : ""),
  3091. + (flags & _O_CREAT ? "|O_CREAT" : ""),
  3092. + (flags & _O_TRUNC ? "|O_TRUNC" : ""),
  3093. + (flags & _O_EXCL ? "|O_EXCL" : ""),
  3094. + (flags & _O_TEXT ? "|O_TEXT" : ""),
  3095. + (flags & _O_BINARY ? "|O_BINARY" : ""));
  3096. +}
  3097. +
  3098. +static void
  3099. +g_win32_print_gioflags (GIOFlags flags)
  3100. +{
  3101. + char *bar = "";
  3102. +
  3103. + if (flags & G_IO_FLAG_APPEND)
  3104. + bar = "|", g_print ("APPEND");
  3105. + if (flags & G_IO_FLAG_NONBLOCK)
  3106. + g_print ("%sNONBLOCK", bar), bar = "|";
  3107. + if (flags & G_IO_FLAG_IS_READABLE)
  3108. + g_print ("%sREADABLE", bar), bar = "|";
  3109. + if (flags & G_IO_FLAG_IS_WRITEABLE)
  3110. + g_print ("%sWRITEABLE", bar), bar = "|";
  3111. + if (flags & G_IO_FLAG_IS_SEEKABLE)
  3112. + g_print ("%sSEEKABLE", bar), bar = "|";
  3113. +}
  3114. +
  3115. +static const char *
  3116. +event_mask_to_string (int mask)
  3117. +{
  3118. + char buf[100];
  3119. + int checked_bits = 0;
  3120. + char *bufp = buf;
  3121. +
  3122. + if (mask == 0)
  3123. + return "";
  3124. +
  3125. +#define BIT(n) checked_bits |= FD_##n; if (mask & FD_##n) bufp += sprintf (bufp, "%s" #n, (bufp>buf ? "|" : ""))
  3126. +
  3127. + BIT (READ);
  3128. + BIT (WRITE);
  3129. + BIT (OOB);
  3130. + BIT (ACCEPT);
  3131. + BIT (CONNECT);
  3132. + BIT (CLOSE);
  3133. + BIT (QOS);
  3134. + BIT (GROUP_QOS);
  3135. + BIT (ROUTING_INTERFACE_CHANGE);
  3136. + BIT (ADDRESS_LIST_CHANGE);
  3137. +
  3138. +#undef BIT
  3139. +
  3140. + if ((mask & ~checked_bits) != 0)
  3141. + bufp += sprintf (bufp, "|%#x", mask & ~checked_bits);
  3142. +
  3143. + return g_quark_to_string (g_quark_from_string (buf));
  3144. +}
  3145. +
  3146. +static const char *
  3147. +condition_to_string (GIOCondition condition)
  3148. +{
  3149. + char buf[100];
  3150. + int checked_bits = 0;
  3151. + char *bufp = buf;
  3152. +
  3153. + if (condition == 0)
  3154. + return "";
  3155. +
  3156. +#define BIT(n) checked_bits |= G_IO_##n; if (condition & G_IO_##n) bufp += sprintf (bufp, "%s" #n, (bufp>buf ? "|" : ""))
  3157. +
  3158. + BIT (IN);
  3159. + BIT (OUT);
  3160. + BIT (PRI);
  3161. + BIT (ERR);
  3162. + BIT (HUP);
  3163. + BIT (NVAL);
  3164. +
  3165. +#undef BIT
  3166. +
  3167. + if ((condition & ~checked_bits) != 0)
  3168. + bufp += sprintf (bufp, "|%#x", condition & ~checked_bits);
  3169. +
  3170. + return g_quark_to_string (g_quark_from_string (buf));
  3171. +}
  3172. +
  3173. +static gboolean
  3174. +g_io_win32_get_debug_flag (void)
  3175. +{
  3176. + return (getenv ("G_IO_WIN32_DEBUG") != NULL);
  3177. +}
  3178. +
  3179. +static char *
  3180. +winsock_error_message (int number)
  3181. +{
  3182. + static char unk[100];
  3183. +
  3184. + switch (number) {
  3185. + case WSAEINTR:
  3186. + return "Interrupted function call";
  3187. + case WSAEACCES:
  3188. + return "Permission denied";
  3189. + case WSAEFAULT:
  3190. + return "Bad address";
  3191. + case WSAEINVAL:
  3192. + return "Invalid argument";
  3193. + case WSAEMFILE:
  3194. + return "Too many open sockets";
  3195. + case WSAEWOULDBLOCK:
  3196. + return "Resource temporarily unavailable";
  3197. + case WSAEINPROGRESS:
  3198. + return "Operation now in progress";
  3199. + case WSAEALREADY:
  3200. + return "Operation already in progress";
  3201. + case WSAENOTSOCK:
  3202. + return "Socket operation on nonsocket";
  3203. + case WSAEDESTADDRREQ:
  3204. + return "Destination address required";
  3205. + case WSAEMSGSIZE:
  3206. + return "Message too long";
  3207. + case WSAEPROTOTYPE:
  3208. + return "Protocol wrong type for socket";
  3209. + case WSAENOPROTOOPT:
  3210. + return "Bad protocol option";
  3211. + case WSAEPROTONOSUPPORT:
  3212. + return "Protocol not supported";
  3213. + case WSAESOCKTNOSUPPORT:
  3214. + return "Socket type not supported";
  3215. + case WSAEOPNOTSUPP:
  3216. + return "Operation not supported on transport endpoint";
  3217. + case WSAEPFNOSUPPORT:
  3218. + return "Protocol family not supported";
  3219. + case WSAEAFNOSUPPORT:
  3220. + return "Address family not supported by protocol family";
  3221. + case WSAEADDRINUSE:
  3222. + return "Address already in use";
  3223. + case WSAEADDRNOTAVAIL:
  3224. + return "Address not available";
  3225. + case WSAENETDOWN:
  3226. + return "Network interface is not configured";
  3227. + case WSAENETUNREACH:
  3228. + return "Network is unreachable";
  3229. + case WSAENETRESET:
  3230. + return "Network dropped connection on reset";
  3231. + case WSAECONNABORTED:
  3232. + return "Software caused connection abort";
  3233. + case WSAECONNRESET:
  3234. + return "Connection reset by peer";
  3235. + case WSAENOBUFS:
  3236. + return "No buffer space available";
  3237. + case WSAEISCONN:
  3238. + return "Socket is already connected";
  3239. + case WSAENOTCONN:
  3240. + return "Socket is not connected";
  3241. + case WSAESHUTDOWN:
  3242. + return "Can't send after socket shutdown";
  3243. + case WSAETIMEDOUT:
  3244. + return "Connection timed out";
  3245. + case WSAECONNREFUSED:
  3246. + return "Connection refused";
  3247. + case WSAEHOSTDOWN:
  3248. + return "Host is down";
  3249. + case WSAEHOSTUNREACH:
  3250. + return "Host is unreachable";
  3251. + case WSAEPROCLIM:
  3252. + return "Too many processes";
  3253. + case WSASYSNOTREADY:
  3254. + return "Network subsystem is unavailable";
  3255. + case WSAVERNOTSUPPORTED:
  3256. + return "Winsock.dll version out of range";
  3257. + case WSANOTINITIALISED:
  3258. + return "Successful WSAStartup not yet performed";
  3259. + case WSAEDISCON:
  3260. + return "Graceful shutdown in progress";
  3261. + case WSATYPE_NOT_FOUND:
  3262. + return "Class type not found";
  3263. + case WSAHOST_NOT_FOUND:
  3264. + return "Host not found";
  3265. + case WSATRY_AGAIN:
  3266. + return "Nonauthoritative host not found";
  3267. + case WSANO_RECOVERY:
  3268. + return "This is a nonrecoverable error";
  3269. + case WSANO_DATA:
  3270. + return "Valid name, no data record of requested type";
  3271. + case WSA_INVALID_HANDLE:
  3272. + return "Specified event object handle is invalid";
  3273. + case WSA_INVALID_PARAMETER:
  3274. + return "One or more parameters are invalid";
  3275. + case WSA_IO_INCOMPLETE:
  3276. + return "Overlapped I/O event object not in signaled state";
  3277. + case WSA_NOT_ENOUGH_MEMORY:
  3278. + return "Insufficient memory available";
  3279. + case WSA_OPERATION_ABORTED:
  3280. + return "Overlapped operation aborted";
  3281. + case WSAEINVALIDPROCTABLE:
  3282. + return "Invalid procedure table from service provider";
  3283. + case WSAEINVALIDPROVIDER:
  3284. + return "Invalid service provider version number";
  3285. + case WSAEPROVIDERFAILEDINIT:
  3286. + return "Unable to initialize a service provider";
  3287. + case WSASYSCALLFAILURE:
  3288. + return "System call failure";
  3289. + default:
  3290. + sprintf (unk, "Unknown WinSock error %d", number);
  3291. + return unk;
  3292. + }
  3293. +}
  3294. +
  3295. +static void
  3296. +g_io_channel_win32_init (GIOWin32Channel *channel)
  3297. +{
  3298. + channel->debug = g_io_win32_get_debug_flag ();
  3299. + channel->buffer = NULL;
  3300. + channel->running = FALSE;
  3301. + channel->needs_close = FALSE;
  3302. + channel->thread_id = 0;
  3303. + channel->data_avail_event = NULL;
  3304. + channel->revents = 0;
  3305. + channel->space_avail_event = NULL;
  3306. + channel->event_mask = 0;
  3307. + channel->last_events = 0;
  3308. + channel->event = 0;
  3309. + channel->write_would_have_blocked = FALSE;
  3310. + InitializeCriticalSection (&channel->mutex);
  3311. +}
  3312. +
  3313. +static void
  3314. +create_events (GIOWin32Channel *channel)
  3315. +{
  3316. + SECURITY_ATTRIBUTES sec_attrs;
  3317. +
  3318. + sec_attrs.nLength = sizeof (SECURITY_ATTRIBUTES);
  3319. + sec_attrs.lpSecurityDescriptor = NULL;
  3320. + sec_attrs.bInheritHandle = FALSE;
  3321. +
  3322. + /* The data available event is manual reset, the space available event
  3323. + * is automatic reset.
  3324. + */
  3325. + if (!(channel->data_avail_event = CreateEvent (&sec_attrs, TRUE, FALSE, NULL))
  3326. + || !(channel->space_avail_event = CreateEvent (&sec_attrs, FALSE, FALSE, NULL)))
  3327. + {
  3328. + gchar *emsg = g_win32_error_message (GetLastError ());
  3329. + g_error ("Error creating event: %s", emsg);
  3330. + g_free (emsg);
  3331. + }
  3332. +}
  3333. +
  3334. +static unsigned __stdcall
  3335. +read_thread (void *parameter)
  3336. +{
  3337. + GIOWin32Channel *channel = parameter;
  3338. + guchar *buffer;
  3339. + guint nbytes;
  3340. +
  3341. + g_io_channel_ref ((GIOChannel *)channel);
  3342. +
  3343. + if (channel->debug)
  3344. + g_print ("read_thread %#x: start fd=%d, data_avail=%#x space_avail=%#x\n",
  3345. + channel->thread_id,
  3346. + channel->fd,
  3347. + (guint) channel->data_avail_event,
  3348. + (guint) channel->space_avail_event);
  3349. +
  3350. + channel->direction = 0;
  3351. + channel->buffer = g_malloc (BUFFER_SIZE);
  3352. + channel->rdp = channel->wrp = 0;
  3353. + channel->running = TRUE;
  3354. +
  3355. + SetEvent (channel->space_avail_event);
  3356. +
  3357. + LOCK (channel->mutex);
  3358. + while (channel->running)
  3359. + {
  3360. + if (channel->debug)
  3361. + g_print ("read_thread %#x: rdp=%d, wrp=%d\n",
  3362. + channel->thread_id, channel->rdp, channel->wrp);
  3363. + if ((channel->wrp + 1) % BUFFER_SIZE == channel->rdp)
  3364. + {
  3365. + /* Buffer is full */
  3366. + if (channel->debug)
  3367. + g_print ("read_thread %#x: resetting space_avail\n",
  3368. + channel->thread_id);
  3369. + ResetEvent (channel->space_avail_event);
  3370. + if (channel->debug)
  3371. + g_print ("read_thread %#x: waiting for space\n",
  3372. + channel->thread_id);
  3373. + UNLOCK (channel->mutex);
  3374. + WaitForSingleObject (channel->space_avail_event, INFINITE);
  3375. + LOCK (channel->mutex);
  3376. + if (channel->debug)
  3377. + g_print ("read_thread %#x: rdp=%d, wrp=%d\n",
  3378. + channel->thread_id, channel->rdp, channel->wrp);
  3379. + }
  3380. +
  3381. + buffer = channel->buffer + channel->wrp;
  3382. +
  3383. + /* Always leave at least one byte unused gap to be able to
  3384. + * distinguish between the full and empty condition...
  3385. + */
  3386. + nbytes = MIN ((channel->rdp + BUFFER_SIZE - channel->wrp - 1) % BUFFER_SIZE,
  3387. + BUFFER_SIZE - channel->wrp);
  3388. +
  3389. + if (channel->debug)
  3390. + g_print ("read_thread %#x: calling read() for %d bytes\n",
  3391. + channel->thread_id, nbytes);
  3392. +
  3393. + UNLOCK (channel->mutex);
  3394. +
  3395. + nbytes = read (channel->fd, buffer, nbytes);
  3396. +
  3397. + LOCK (channel->mutex);
  3398. +
  3399. + channel->revents = G_IO_IN;
  3400. + if (nbytes == 0)
  3401. + channel->revents |= G_IO_HUP;
  3402. + else if (nbytes < 0)
  3403. + channel->revents |= G_IO_ERR;
  3404. +
  3405. + if (channel->debug)
  3406. + g_print ("read_thread %#x: read() returned %d, rdp=%d, wrp=%d\n",
  3407. + channel->thread_id, nbytes, channel->rdp, channel->wrp);
  3408. +
  3409. + if (nbytes <= 0)
  3410. + break;
  3411. +
  3412. + channel->wrp = (channel->wrp + nbytes) % BUFFER_SIZE;
  3413. + if (channel->debug)
  3414. + g_print ("read_thread %#x: rdp=%d, wrp=%d, setting data_avail\n",
  3415. + channel->thread_id, channel->rdp, channel->wrp);
  3416. + SetEvent (channel->data_avail_event);
  3417. + }
  3418. +
  3419. + channel->running = FALSE;
  3420. + if (channel->needs_close)
  3421. + {
  3422. + if (channel->debug)
  3423. + g_print ("read_thread %#x: channel fd %d needs closing\n",
  3424. + channel->thread_id, channel->fd);
  3425. + close (channel->fd);
  3426. + channel->fd = -1;
  3427. + }
  3428. +
  3429. + if (channel->debug)
  3430. + g_print ("read_thread %#x: EOF, rdp=%d, wrp=%d, setting data_avail\n",
  3431. + channel->thread_id, channel->rdp, channel->wrp);
  3432. + SetEvent (channel->data_avail_event);
  3433. + UNLOCK (channel->mutex);
  3434. +
  3435. + g_io_channel_unref ((GIOChannel *)channel);
  3436. +
  3437. + /* No need to call _endthreadex(), the actual thread starter routine
  3438. + * in MSVCRT (see crt/src/threadex.c:_threadstartex) calls
  3439. + * _endthreadex() for us.
  3440. + */
  3441. +
  3442. + return 0;
  3443. +}
  3444. +
  3445. +static unsigned __stdcall
  3446. +write_thread (void *parameter)
  3447. +{
  3448. + GIOWin32Channel *channel = parameter;
  3449. + guchar *buffer;
  3450. + guint nbytes;
  3451. +
  3452. + g_io_channel_ref ((GIOChannel *)channel);
  3453. +
  3454. + if (channel->debug)
  3455. + g_print ("write_thread %#x: start fd=%d, data_avail=%#x space_avail=%#x\n",
  3456. + channel->thread_id,
  3457. + channel->fd,
  3458. + (guint) channel->data_avail_event,
  3459. + (guint) channel->space_avail_event);
  3460. +
  3461. + channel->direction = 1;
  3462. + channel->buffer = g_malloc (BUFFER_SIZE);
  3463. + channel->rdp = channel->wrp = 0;
  3464. + channel->running = TRUE;
  3465. +
  3466. + SetEvent (channel->space_avail_event);
  3467. +
  3468. + /* We use the same event objects as for a reader thread, but with
  3469. + * reversed meaning. So, space_avail is used if data is available
  3470. + * for writing, and data_avail is used if space is available in the
  3471. + * write buffer.
  3472. + */
  3473. +
  3474. + LOCK (channel->mutex);
  3475. + while (channel->running || channel->rdp != channel->wrp)
  3476. + {
  3477. + if (channel->debug)
  3478. + g_print ("write_thread %#x: rdp=%d, wrp=%d\n",
  3479. + channel->thread_id, channel->rdp, channel->wrp);
  3480. + if (channel->wrp == channel->rdp)
  3481. + {
  3482. + /* Buffer is empty. */
  3483. + if (channel->debug)
  3484. + g_print ("write_thread %#x: resetting space_avail\n",
  3485. + channel->thread_id);
  3486. + ResetEvent (channel->space_avail_event);
  3487. + if (channel->debug)
  3488. + g_print ("write_thread %#x: waiting for data\n",
  3489. + channel->thread_id);
  3490. + channel->revents = G_IO_OUT;
  3491. + SetEvent (channel->data_avail_event);
  3492. + UNLOCK (channel->mutex);
  3493. + WaitForSingleObject (channel->space_avail_event, INFINITE);
  3494. +
  3495. + LOCK (channel->mutex);
  3496. + if (channel->rdp == channel->wrp)
  3497. + break;
  3498. +
  3499. + if (channel->debug)
  3500. + g_print ("write_thread %#x: rdp=%d, wrp=%d\n",
  3501. + channel->thread_id, channel->rdp, channel->wrp);
  3502. + }
  3503. +
  3504. + buffer = channel->buffer + channel->rdp;
  3505. + if (channel->rdp < channel->wrp)
  3506. + nbytes = channel->wrp - channel->rdp;
  3507. + else
  3508. + nbytes = BUFFER_SIZE - channel->rdp;
  3509. +
  3510. + if (channel->debug)
  3511. + g_print ("write_thread %#x: calling write() for %d bytes\n",
  3512. + channel->thread_id, nbytes);
  3513. +
  3514. + UNLOCK (channel->mutex);
  3515. + nbytes = write (channel->fd, buffer, nbytes);
  3516. + LOCK (channel->mutex);
  3517. +
  3518. + if (channel->debug)
  3519. + g_print ("write_thread %#x: write(%i) returned %d, rdp=%d, wrp=%d\n",
  3520. + channel->thread_id, channel->fd, nbytes, channel->rdp, channel->wrp);
  3521. +
  3522. + channel->revents = 0;
  3523. + if (nbytes > 0)
  3524. + channel->revents |= G_IO_OUT;
  3525. + else if (nbytes <= 0)
  3526. + channel->revents |= G_IO_ERR;
  3527. +
  3528. + channel->rdp = (channel->rdp + nbytes) % BUFFER_SIZE;
  3529. +
  3530. + if (nbytes <= 0)
  3531. + break;
  3532. +
  3533. + if (channel->debug)
  3534. + g_print ("write_thread: setting data_avail for thread %#x\n",
  3535. + channel->thread_id);
  3536. + SetEvent (channel->data_avail_event);
  3537. + }
  3538. +
  3539. + channel->running = FALSE;
  3540. + if (channel->needs_close)
  3541. + {
  3542. + if (channel->debug)
  3543. + g_print ("write_thread %#x: channel fd %d needs closing\n",
  3544. + channel->thread_id, channel->fd);
  3545. + close (channel->fd);
  3546. + channel->fd = -1;
  3547. + }
  3548. +
  3549. + UNLOCK (channel->mutex);
  3550. +
  3551. + g_io_channel_unref ((GIOChannel *)channel);
  3552. +
  3553. + return 0;
  3554. +}
  3555. +
  3556. +static void
  3557. +create_thread (GIOWin32Channel *channel,
  3558. + GIOCondition condition,
  3559. + unsigned (__stdcall *thread) (void *parameter))
  3560. +{
  3561. + HANDLE thread_handle;
  3562. +
  3563. + thread_handle = (HANDLE) _beginthreadex (NULL, 0, thread, channel, 0,
  3564. + &channel->thread_id);
  3565. + if (thread_handle == 0)
  3566. + g_warning (G_STRLOC ": Error creating reader thread: %s",
  3567. + g_strerror (errno));
  3568. + else if (!CloseHandle (thread_handle))
  3569. + g_warning (G_STRLOC ": Error closing thread handle: %s\n",
  3570. + g_win32_error_message (GetLastError ()));
  3571. +
  3572. + WaitForSingleObject (channel->space_avail_event, INFINITE);
  3573. +}
  3574. +
  3575. +static GIOStatus
  3576. +buffer_read (GIOWin32Channel *channel,
  3577. + guchar *dest,
  3578. + gsize count,
  3579. + gsize *bytes_read,
  3580. + GError **err)
  3581. +{
  3582. + guint nbytes;
  3583. + guint left = count;
  3584. +
  3585. + LOCK (channel->mutex);
  3586. + if (channel->debug)
  3587. + g_print ("reading from thread %#x %d bytes, rdp=%d, wrp=%d\n",
  3588. + channel->thread_id, count, channel->rdp, channel->wrp);
  3589. +
  3590. + if (channel->wrp == channel->rdp)
  3591. + {
  3592. + UNLOCK (channel->mutex);
  3593. + if (channel->debug)
  3594. + g_print ("waiting for data from thread %#x\n", channel->thread_id);
  3595. + WaitForSingleObject (channel->data_avail_event, INFINITE);
  3596. + if (channel->debug)
  3597. + g_print ("done waiting for data from thread %#x\n", channel->thread_id);
  3598. + LOCK (channel->mutex);
  3599. + if (channel->wrp == channel->rdp && !channel->running)
  3600. + {
  3601. + if (channel->debug)
  3602. + g_print ("wrp==rdp, !running\n");
  3603. + UNLOCK (channel->mutex);
  3604. + *bytes_read = 0;
  3605. + return G_IO_STATUS_EOF;
  3606. + }
  3607. + }
  3608. +
  3609. + if (channel->rdp < channel->wrp)
  3610. + nbytes = channel->wrp - channel->rdp;
  3611. + else
  3612. + nbytes = BUFFER_SIZE - channel->rdp;
  3613. + UNLOCK (channel->mutex);
  3614. + nbytes = MIN (left, nbytes);
  3615. + if (channel->debug)
  3616. + g_print ("moving %d bytes from thread %#x\n",
  3617. + nbytes, channel->thread_id);
  3618. + memcpy (dest, channel->buffer + channel->rdp, nbytes);
  3619. + dest += nbytes;
  3620. + left -= nbytes;
  3621. + LOCK (channel->mutex);
  3622. + channel->rdp = (channel->rdp + nbytes) % BUFFER_SIZE;
  3623. + if (channel->debug)
  3624. + g_print ("setting space_avail for thread %#x\n", channel->thread_id);
  3625. + SetEvent (channel->space_avail_event);
  3626. + if (channel->debug)
  3627. + g_print ("for thread %#x: rdp=%d, wrp=%d\n",
  3628. + channel->thread_id, channel->rdp, channel->wrp);
  3629. + if (channel->running && channel->wrp == channel->rdp)
  3630. + {
  3631. + if (channel->debug)
  3632. + g_print ("resetting data_avail of thread %#x\n",
  3633. + channel->thread_id);
  3634. + ResetEvent (channel->data_avail_event);
  3635. + };
  3636. + UNLOCK (channel->mutex);
  3637. +
  3638. + /* We have no way to indicate any errors form the actual
  3639. + * read() or recv() call in the reader thread. Should we have?
  3640. + */
  3641. + *bytes_read = count - left;
  3642. + return (*bytes_read > 0) ? G_IO_STATUS_NORMAL : G_IO_STATUS_EOF;
  3643. +}
  3644. +
  3645. +
  3646. +static GIOStatus
  3647. +buffer_write (GIOWin32Channel *channel,
  3648. + const guchar *dest,
  3649. + gsize count,
  3650. + gsize *bytes_written,
  3651. + GError **err)
  3652. +{
  3653. + guint nbytes;
  3654. + guint left = count;
  3655. +
  3656. + LOCK (channel->mutex);
  3657. + if (channel->debug)
  3658. + g_print ("buffer_write: writing to thread %#x %d bytes, rdp=%d, wrp=%d\n",
  3659. + channel->thread_id, count, channel->rdp, channel->wrp);
  3660. +
  3661. + if ((channel->wrp + 1) % BUFFER_SIZE == channel->rdp)
  3662. + {
  3663. + /* Buffer is full */
  3664. + if (channel->debug)
  3665. + g_print ("buffer_write: tid %#x: resetting data_avail\n",
  3666. + channel->thread_id);
  3667. + ResetEvent (channel->data_avail_event);
  3668. + if (channel->debug)
  3669. + g_print ("buffer_write: tid %#x: waiting for space\n",
  3670. + channel->thread_id);
  3671. + UNLOCK (channel->mutex);
  3672. + WaitForSingleObject (channel->data_avail_event, INFINITE);
  3673. + LOCK (channel->mutex);
  3674. + if (channel->debug)
  3675. + g_print ("buffer_write: tid %#x: rdp=%d, wrp=%d\n",
  3676. + channel->thread_id, channel->rdp, channel->wrp);
  3677. + }
  3678. +
  3679. + nbytes = MIN ((channel->rdp + BUFFER_SIZE - channel->wrp - 1) % BUFFER_SIZE,
  3680. + BUFFER_SIZE - channel->wrp);
  3681. +
  3682. + UNLOCK (channel->mutex);
  3683. + nbytes = MIN (left, nbytes);
  3684. + if (channel->debug)
  3685. + g_print ("buffer_write: tid %#x: writing %d bytes\n",
  3686. + channel->thread_id, nbytes);
  3687. + memcpy (channel->buffer + channel->wrp, dest, nbytes);
  3688. + dest += nbytes;
  3689. + left -= nbytes;
  3690. + LOCK (channel->mutex);
  3691. +
  3692. + channel->wrp = (channel->wrp + nbytes) % BUFFER_SIZE;
  3693. + if (channel->debug)
  3694. + g_print ("buffer_write: tid %#x: rdp=%d, wrp=%d, setting space_avail\n",
  3695. + channel->thread_id, channel->rdp, channel->wrp);
  3696. + SetEvent (channel->space_avail_event);
  3697. +
  3698. + if ((channel->wrp + 1) % BUFFER_SIZE == channel->rdp)
  3699. + {
  3700. + /* Buffer is full */
  3701. + if (channel->debug)
  3702. + g_print ("buffer_write: tid %#x: resetting data_avail\n",
  3703. + channel->thread_id);
  3704. + ResetEvent (channel->data_avail_event);
  3705. + }
  3706. +
  3707. + UNLOCK (channel->mutex);
  3708. +
  3709. + /* We have no way to indicate any errors form the actual
  3710. + * write() call in the writer thread. Should we have?
  3711. + */
  3712. + *bytes_written = count - left;
  3713. + return (*bytes_written > 0) ? G_IO_STATUS_NORMAL : G_IO_STATUS_EOF;
  3714. +}
  3715. +
  3716. +
  3717. +static gboolean
  3718. +g_io_win32_prepare (GSource *source,
  3719. + gint *timeout)
  3720. +{
  3721. + GIOWin32Watch *watch = (GIOWin32Watch *)source;
  3722. + GIOCondition buffer_condition = g_io_channel_get_buffer_condition (watch->channel);
  3723. + GIOWin32Channel *channel = (GIOWin32Channel *)watch->channel;
  3724. + int event_mask;
  3725. +
  3726. + *timeout = -1;
  3727. +
  3728. + switch (channel->type)
  3729. + {
  3730. + case G_IO_WIN32_WINDOWS_MESSAGES:
  3731. + case G_IO_WIN32_CONSOLE:
  3732. + break;
  3733. +
  3734. + case G_IO_WIN32_FILE_DESC:
  3735. + if (channel->debug)
  3736. + g_print ("g_io_win32_prepare: for thread %#x buffer_condition:{%s}\n"
  3737. + " watch->pollfd.events:{%s} watch->pollfd.revents:{%s} channel->revents:{%s}\n",
  3738. + channel->thread_id, condition_to_string (buffer_condition),
  3739. + condition_to_string (watch->pollfd.events),
  3740. + condition_to_string (watch->pollfd.revents),
  3741. + condition_to_string (channel->revents));
  3742. +
  3743. + LOCK (channel->mutex);
  3744. + if (channel->running)
  3745. + {
  3746. + if (channel->direction == 0 && channel->wrp == channel->rdp)
  3747. + {
  3748. + if (channel->debug)
  3749. + g_print ("g_io_win32_prepare: for thread %#x, setting channel->revents = 0\n",
  3750. + channel->thread_id);
  3751. + channel->revents = 0;
  3752. + }
  3753. + }
  3754. + else
  3755. + {
  3756. + if (channel->direction == 1
  3757. + && (channel->wrp + 1) % BUFFER_SIZE == channel->rdp)
  3758. + {
  3759. + if (channel->debug)
  3760. + g_print ("g_io_win32_prepare: for thread %#x, setting channel->revents = %i\n",
  3761. + channel->thread_id, 0);
  3762. + channel->revents = 0;
  3763. + }
  3764. + }
  3765. + UNLOCK (channel->mutex);
  3766. + break;
  3767. +
  3768. + case G_IO_WIN32_SOCKET:
  3769. + event_mask = 0;
  3770. + if (watch->condition & G_IO_IN)
  3771. + event_mask |= (FD_READ | FD_ACCEPT);
  3772. + if (watch->condition & G_IO_OUT)
  3773. + event_mask |= (FD_WRITE | FD_CONNECT);
  3774. + event_mask |= FD_CLOSE;
  3775. +
  3776. + if (channel->event_mask != event_mask /* || channel->event != watch->pollfd.fd*/)
  3777. + {
  3778. + if (channel->debug)
  3779. + g_print ("g_io_win32_prepare: WSAEventSelect(%d, %#x, {%s}\n",
  3780. + channel->fd, watch->pollfd.fd,
  3781. + event_mask_to_string (event_mask));
  3782. + if (WSAEventSelect (channel->fd, (HANDLE) watch->pollfd.fd,
  3783. + event_mask) == SOCKET_ERROR)
  3784. + ; /* What? */
  3785. + channel->event_mask = event_mask;
  3786. +#if 0
  3787. + channel->event = watch->pollfd.fd;
  3788. +#endif
  3789. + channel->last_events = 0;
  3790. + }
  3791. + break;
  3792. +
  3793. + default:
  3794. + g_assert_not_reached ();
  3795. + abort ();
  3796. + }
  3797. + return ((watch->condition & buffer_condition) == watch->condition);
  3798. +}
  3799. +
  3800. +static gboolean
  3801. +g_io_win32_check (GSource *source)
  3802. +{
  3803. + MSG msg;
  3804. + GIOWin32Watch *watch = (GIOWin32Watch *)source;
  3805. + GIOWin32Channel *channel = (GIOWin32Channel *)watch->channel;
  3806. + GIOCondition buffer_condition = g_io_channel_get_buffer_condition (watch->channel);
  3807. + WSANETWORKEVENTS events;
  3808. +
  3809. + switch (channel->type)
  3810. + {
  3811. + case G_IO_WIN32_WINDOWS_MESSAGES:
  3812. + return (PeekMessage (&msg, channel->hwnd, 0, 0, PM_NOREMOVE));
  3813. +
  3814. + case G_IO_WIN32_FILE_DESC:
  3815. + if (channel->debug)
  3816. + g_print ("g_io_win32_check: for thread %#x buffer_condition=%s\n"
  3817. + " watch->pollfd.events={%s} watch->pollfd.revents={%s} channel->revents={%s}\n",
  3818. + channel->thread_id, condition_to_string (buffer_condition),
  3819. + condition_to_string (watch->pollfd.events),
  3820. + condition_to_string (watch->pollfd.revents),
  3821. + condition_to_string (channel->revents));
  3822. +
  3823. + watch->pollfd.revents = (watch->pollfd.events & channel->revents);
  3824. +
  3825. + return ((watch->pollfd.revents | buffer_condition) & watch->condition);
  3826. +
  3827. + case G_IO_WIN32_CONSOLE:
  3828. + if (watch->channel->is_writeable)
  3829. + return TRUE;
  3830. + else if (watch->channel->is_readable)
  3831. + {
  3832. + INPUT_RECORD buffer;
  3833. + DWORD n;
  3834. + if (PeekConsoleInput ((HANDLE) watch->pollfd.fd, &buffer, 1, &n) &&
  3835. + n == 1)
  3836. + {
  3837. + /* _kbhit() does quite complex processing to find out
  3838. + * whether at least one of the key events pending corresponds
  3839. + * to a "real" character that can be read.
  3840. + */
  3841. + if (_kbhit ())
  3842. + return TRUE;
  3843. +
  3844. + /* Discard all other kinds of events */
  3845. + ReadConsoleInput ((HANDLE) watch->pollfd.fd, &buffer, 1, &n);
  3846. + }
  3847. + }
  3848. + return FALSE;
  3849. +
  3850. + case G_IO_WIN32_SOCKET:
  3851. + if (channel->last_events & FD_WRITE)
  3852. + {
  3853. + if (channel->debug)
  3854. + g_print ("g_io_win32_check: sock=%d event=%#x last_events has FD_WRITE\n",
  3855. + channel->fd, watch->pollfd.fd);
  3856. + }
  3857. + else
  3858. + {
  3859. + WSAEnumNetworkEvents (channel->fd, 0, &events);
  3860. +
  3861. + if (channel->debug)
  3862. + g_print ("g_io_win32_check: WSAEnumNetworkEvents (%d, %#x) revents={%s} condition={%s} events={%s}\n",
  3863. + channel->fd, watch->pollfd.fd,
  3864. + condition_to_string (watch->pollfd.revents),
  3865. + condition_to_string (watch->condition),
  3866. + event_mask_to_string (events.lNetworkEvents));
  3867. +
  3868. + if (watch->pollfd.revents != 0 &&
  3869. + events.lNetworkEvents == 0 &&
  3870. + !(channel->event_mask & FD_WRITE))
  3871. + {
  3872. + channel->event_mask = 0;
  3873. + if (channel->debug)
  3874. + g_print ("g_io_win32_check: WSAEventSelect(%d, %#x, {})\n",
  3875. + channel->fd, watch->pollfd.fd);
  3876. + WSAEventSelect (channel->fd, (HANDLE) watch->pollfd.fd, 0);
  3877. + if (channel->debug)
  3878. + g_print ("g_io_win32_check: ResetEvent(%#x)\n",
  3879. + watch->pollfd.fd);
  3880. + ResetEvent ((HANDLE) watch->pollfd.fd);
  3881. + }
  3882. + channel->last_events = events.lNetworkEvents;
  3883. + }
  3884. + watch->pollfd.revents = 0;
  3885. + if (channel->last_events & (FD_READ | FD_ACCEPT))
  3886. + watch->pollfd.revents |= G_IO_IN;
  3887. + if (channel->last_events & FD_WRITE)
  3888. + watch->pollfd.revents |= G_IO_OUT;
  3889. + else
  3890. + {
  3891. + /* We have called WSAEnumNetworkEvents() above but it didn't
  3892. + * set FD_WRITE.
  3893. + */
  3894. + if (events.lNetworkEvents & FD_CONNECT)
  3895. + {
  3896. + if (events.iErrorCode[FD_CONNECT_BIT] == 0)
  3897. + watch->pollfd.revents |= G_IO_OUT;
  3898. + else
  3899. + watch->pollfd.revents |= (G_IO_HUP | G_IO_ERR);
  3900. + }
  3901. + if (watch->pollfd.revents == 0 && (channel->last_events & (FD_CLOSE)))
  3902. + watch->pollfd.revents |= G_IO_HUP;
  3903. + }
  3904. +
  3905. + /* Regardless of WSAEnumNetworkEvents() result, if watching for
  3906. + * writability, unless last write would have blocked set
  3907. + * G_IO_OUT. But never set both G_IO_OUT and G_IO_HUP.
  3908. + */
  3909. + if (!(watch->pollfd.revents & G_IO_HUP) &&
  3910. + !channel->write_would_have_blocked &&
  3911. + (channel->event_mask & FD_WRITE))
  3912. + watch->pollfd.revents |= G_IO_OUT;
  3913. +
  3914. + return ((watch->pollfd.revents | buffer_condition) & watch->condition);
  3915. +
  3916. + default:
  3917. + g_assert_not_reached ();
  3918. + abort ();
  3919. + }
  3920. +}
  3921. +
  3922. +static gboolean
  3923. +g_io_win32_dispatch (GSource *source,
  3924. + GSourceFunc callback,
  3925. + gpointer user_data)
  3926. +{
  3927. + GIOFunc func = (GIOFunc)callback;
  3928. + GIOWin32Watch *watch = (GIOWin32Watch *)source;
  3929. + GIOWin32Channel *channel = (GIOWin32Channel *)watch->channel;
  3930. + GIOCondition buffer_condition = g_io_channel_get_buffer_condition (watch->channel);
  3931. +
  3932. + if (!func)
  3933. + {
  3934. + g_warning (G_STRLOC ": GIOWin32Watch dispatched without callback\n"
  3935. + "You must call g_source_connect().");
  3936. + return FALSE;
  3937. + }
  3938. +
  3939. + if (channel->debug)
  3940. + g_print ("g_io_win32_dispatch: pollfd.revents=%s condition=%s result=%s\n",
  3941. + condition_to_string (watch->pollfd.revents),
  3942. + condition_to_string (watch->condition),
  3943. + condition_to_string ((watch->pollfd.revents | buffer_condition) & watch->condition));
  3944. +
  3945. + return (*func) (watch->channel,
  3946. + (watch->pollfd.revents | buffer_condition) & watch->condition,
  3947. + user_data);
  3948. +}
  3949. +
  3950. +static void
  3951. +g_io_win32_finalize (GSource *source)
  3952. +{
  3953. + GIOWin32Watch *watch = (GIOWin32Watch *)source;
  3954. + GIOWin32Channel *channel = (GIOWin32Channel *)watch->channel;
  3955. +
  3956. + switch (channel->type)
  3957. + {
  3958. + case G_IO_WIN32_WINDOWS_MESSAGES:
  3959. + case G_IO_WIN32_CONSOLE:
  3960. + break;
  3961. +
  3962. + case G_IO_WIN32_FILE_DESC:
  3963. + LOCK (channel->mutex);
  3964. + if (channel->debug)
  3965. + g_print ("g_io_win32_finalize: channel with thread %#x\n",
  3966. + channel->thread_id);
  3967. + UNLOCK (channel->mutex);
  3968. + break;
  3969. +
  3970. + case G_IO_WIN32_SOCKET:
  3971. + if (channel->debug)
  3972. + g_print ("g_io_win32_finalize: channel is for sock=%d\n", channel->fd);
  3973. +#if 0
  3974. + CloseHandle ((HANDLE) watch->pollfd.fd);
  3975. + channel->event = 0;
  3976. + channel->event_mask = 0;
  3977. +#endif
  3978. + break;
  3979. +
  3980. + default:
  3981. + g_assert_not_reached ();
  3982. + abort ();
  3983. + }
  3984. + g_io_channel_unref (watch->channel);
  3985. +}
  3986. +
  3987. +GSourceFuncs g_io_watch_funcs = {
  3988. + g_io_win32_prepare,
  3989. + g_io_win32_check,
  3990. + g_io_win32_dispatch,
  3991. + g_io_win32_finalize
  3992. +};
  3993. +
  3994. +static GIOStatus
  3995. +g_io_win32_msg_read (GIOChannel *channel,
  3996. + gchar *buf,
  3997. + gsize count,
  3998. + gsize *bytes_read,
  3999. + GError **err)
  4000. +{
  4001. + GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
  4002. + MSG msg; /* In case of alignment problems */
  4003. +
  4004. + if (count < sizeof (MSG))
  4005. + {
  4006. + g_set_error (err, G_IO_CHANNEL_ERROR, G_IO_CHANNEL_ERROR_INVAL,
  4007. + "Incorrect message size"); /* Informative enough error message? */
  4008. + return G_IO_STATUS_ERROR;
  4009. + }
  4010. +
  4011. + if (win32_channel->debug)
  4012. + g_print ("g_io_win32_msg_read: for %#x\n",
  4013. + (guint) win32_channel->hwnd);
  4014. + if (!PeekMessage (&msg, win32_channel->hwnd, 0, 0, PM_REMOVE))
  4015. + return G_IO_STATUS_AGAIN;
  4016. +
  4017. + memmove (buf, &msg, sizeof (MSG));
  4018. + *bytes_read = sizeof (MSG);
  4019. +
  4020. + return G_IO_STATUS_NORMAL;
  4021. +}
  4022. +
  4023. +static GIOStatus
  4024. +g_io_win32_msg_write (GIOChannel *channel,
  4025. + const gchar *buf,
  4026. + gsize count,
  4027. + gsize *bytes_written,
  4028. + GError **err)
  4029. +{
  4030. + GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
  4031. + MSG msg;
  4032. +
  4033. + if (count != sizeof (MSG))
  4034. + {
  4035. + g_set_error (err, G_IO_CHANNEL_ERROR, G_IO_CHANNEL_ERROR_INVAL,
  4036. + "Incorrect message size"); /* Informative enough error message? */
  4037. + return G_IO_STATUS_ERROR;
  4038. + }
  4039. +
  4040. + /* In case of alignment problems */
  4041. + memmove (&msg, buf, sizeof (MSG));
  4042. + if (!PostMessage (win32_channel->hwnd, msg.message, msg.wParam, msg.lParam))
  4043. + {
  4044. + gchar *emsg = g_win32_error_message (GetLastError ());
  4045. + g_set_error (err, G_IO_CHANNEL_ERROR, G_IO_CHANNEL_ERROR_FAILED, emsg);
  4046. + g_free (emsg);
  4047. + return G_IO_STATUS_ERROR;
  4048. + }
  4049. +
  4050. + *bytes_written = sizeof (MSG);
  4051. +
  4052. + return G_IO_STATUS_NORMAL;
  4053. +}
  4054. +
  4055. +static GIOStatus
  4056. +g_io_win32_msg_close (GIOChannel *channel,
  4057. + GError **err)
  4058. +{
  4059. + /* Nothing to be done. Or should we set hwnd to some invalid value? */
  4060. +
  4061. + return G_IO_STATUS_NORMAL;
  4062. +}
  4063. +
  4064. +static void
  4065. +g_io_win32_free (GIOChannel *channel)
  4066. +{
  4067. + GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
  4068. +
  4069. + if (win32_channel->debug)
  4070. + g_print ("g_io_win32_free channel fd=%d\n", win32_channel->fd);
  4071. +
  4072. + if (win32_channel->data_avail_event)
  4073. + CloseHandle (win32_channel->data_avail_event);
  4074. + if (win32_channel->space_avail_event)
  4075. + CloseHandle (win32_channel->space_avail_event);
  4076. + if (win32_channel->type == G_IO_WIN32_SOCKET)
  4077. + WSAEventSelect (win32_channel->fd, NULL, 0);
  4078. + DeleteCriticalSection (&win32_channel->mutex);
  4079. +
  4080. + g_free (win32_channel->buffer);
  4081. + g_free (win32_channel);
  4082. +}
  4083. +
  4084. +static GSource *
  4085. +g_io_win32_msg_create_watch (GIOChannel *channel,
  4086. + GIOCondition condition)
  4087. +{
  4088. + GIOWin32Watch *watch;
  4089. + GSource *source;
  4090. +
  4091. + source = g_source_new (&g_io_watch_funcs, sizeof (GIOWin32Watch));
  4092. + watch = (GIOWin32Watch *)source;
  4093. +
  4094. + watch->channel = channel;
  4095. + g_io_channel_ref (channel);
  4096. +
  4097. + watch->condition = condition;
  4098. +
  4099. + watch->pollfd.fd = G_WIN32_MSG_HANDLE;
  4100. + watch->pollfd.events = condition;
  4101. +
  4102. + g_source_add_poll (source, &watch->pollfd);
  4103. +
  4104. + return source;
  4105. +}
  4106. +
  4107. +static GIOStatus
  4108. +g_io_win32_fd_and_console_read (GIOChannel *channel,
  4109. + gchar *buf,
  4110. + gsize count,
  4111. + gsize *bytes_read,
  4112. + GError **err)
  4113. +{
  4114. + GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
  4115. + gint result;
  4116. +
  4117. + if (win32_channel->debug)
  4118. + g_print ("g_io_win32_fd_read: fd=%d count=%d\n",
  4119. + win32_channel->fd, count);
  4120. +
  4121. + if (win32_channel->thread_id)
  4122. + {
  4123. + return buffer_read (win32_channel, buf, count, bytes_read, err);
  4124. + }
  4125. +
  4126. + result = read (win32_channel->fd, buf, count);
  4127. +
  4128. + if (win32_channel->debug)
  4129. + g_print ("g_io_win32_fd_read: read() => %d\n", result);
  4130. +
  4131. + if (result < 0)
  4132. + {
  4133. + *bytes_read = 0;
  4134. +
  4135. + switch (errno)
  4136. + {
  4137. +#ifdef EAGAIN
  4138. + case EAGAIN:
  4139. + return G_IO_STATUS_AGAIN;
  4140. +#endif
  4141. + default:
  4142. + g_set_error (err, G_IO_CHANNEL_ERROR,
  4143. + g_io_channel_error_from_errno (errno),
  4144. + g_strerror (errno));
  4145. + return G_IO_STATUS_ERROR;
  4146. + }
  4147. + }
  4148. +
  4149. + *bytes_read = result;
  4150. +
  4151. + return (result > 0) ? G_IO_STATUS_NORMAL : G_IO_STATUS_EOF;
  4152. +}
  4153. +
  4154. +static GIOStatus
  4155. +g_io_win32_fd_and_console_write (GIOChannel *channel,
  4156. + const gchar *buf,
  4157. + gsize count,
  4158. + gsize *bytes_written,
  4159. + GError **err)
  4160. +{
  4161. + GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
  4162. + gint result;
  4163. +
  4164. + if (win32_channel->thread_id)
  4165. + {
  4166. + return buffer_write (win32_channel, buf, count, bytes_written, err);
  4167. + }
  4168. +
  4169. + result = write (win32_channel->fd, buf, count);
  4170. + if (win32_channel->debug)
  4171. + g_print ("g_io_win32_fd_write: fd=%d count=%d => %d\n",
  4172. + win32_channel->fd, count, result);
  4173. +
  4174. + if (result < 0)
  4175. + {
  4176. + *bytes_written = 0;
  4177. +
  4178. + switch (errno)
  4179. + {
  4180. +#ifdef EAGAIN
  4181. + case EAGAIN:
  4182. + return G_IO_STATUS_AGAIN;
  4183. +#endif
  4184. + default:
  4185. + g_set_error (err, G_IO_CHANNEL_ERROR,
  4186. + g_io_channel_error_from_errno (errno),
  4187. + g_strerror (errno));
  4188. + return G_IO_STATUS_ERROR;
  4189. + }
  4190. + }
  4191. +
  4192. + *bytes_written = result;
  4193. +
  4194. + return G_IO_STATUS_NORMAL;
  4195. +}
  4196. +
  4197. +static GIOStatus
  4198. +g_io_win32_fd_seek (GIOChannel *channel,
  4199. + gint64 offset,
  4200. + GSeekType type,
  4201. + GError **err)
  4202. +{
  4203. + GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
  4204. + int whence;
  4205. + off_t tmp_offset;
  4206. + off_t result;
  4207. +
  4208. + switch (type)
  4209. + {
  4210. + case G_SEEK_SET:
  4211. + whence = SEEK_SET;
  4212. + break;
  4213. + case G_SEEK_CUR:
  4214. + whence = SEEK_CUR;
  4215. + break;
  4216. + case G_SEEK_END:
  4217. + whence = SEEK_END;
  4218. + break;
  4219. + default:
  4220. + whence = -1; /* Keep the compiler quiet */
  4221. + g_assert_not_reached ();
  4222. + abort ();
  4223. + }
  4224. +
  4225. + tmp_offset = offset;
  4226. + if (tmp_offset != offset)
  4227. + {
  4228. + g_set_error (err, G_IO_CHANNEL_ERROR,
  4229. + g_io_channel_error_from_errno (EINVAL),
  4230. + g_strerror (EINVAL));
  4231. + return G_IO_STATUS_ERROR;
  4232. + }
  4233. +
  4234. + result = lseek (win32_channel->fd, tmp_offset, whence);
  4235. +
  4236. + if (result < 0)
  4237. + {
  4238. + g_set_error (err, G_IO_CHANNEL_ERROR,
  4239. + g_io_channel_error_from_errno (errno),
  4240. + g_strerror (errno));
  4241. + return G_IO_STATUS_ERROR;
  4242. + }
  4243. +
  4244. + return G_IO_STATUS_NORMAL;
  4245. +}
  4246. +
  4247. +static GIOStatus
  4248. +g_io_win32_fd_close (GIOChannel *channel,
  4249. + GError **err)
  4250. +{
  4251. + GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
  4252. +
  4253. + if (win32_channel->debug)
  4254. + g_print ("thread %#x: closing fd %d\n",
  4255. + win32_channel->thread_id,
  4256. + win32_channel->fd);
  4257. + LOCK (win32_channel->mutex);
  4258. + if (win32_channel->running)
  4259. + {
  4260. + if (win32_channel->debug)
  4261. + g_print ("thread %#x: running, marking fd %d for later close\n",
  4262. + win32_channel->thread_id, win32_channel->fd);
  4263. + win32_channel->running = FALSE;
  4264. + win32_channel->needs_close = TRUE;
  4265. + if (win32_channel->direction == 0)
  4266. + SetEvent (win32_channel->data_avail_event);
  4267. + else
  4268. + SetEvent (win32_channel->space_avail_event);
  4269. + }
  4270. + else
  4271. + {
  4272. + if (win32_channel->debug)
  4273. + g_print ("closing fd %d\n", win32_channel->fd);
  4274. + close (win32_channel->fd);
  4275. + if (win32_channel->debug)
  4276. + g_print ("closed fd %d, setting to -1\n",
  4277. + win32_channel->fd);
  4278. + win32_channel->fd = -1;
  4279. + }
  4280. + UNLOCK (win32_channel->mutex);
  4281. +
  4282. + /* FIXME error detection? */
  4283. +
  4284. + return G_IO_STATUS_NORMAL;
  4285. +}
  4286. +
  4287. +static GSource *
  4288. +g_io_win32_fd_create_watch (GIOChannel *channel,
  4289. + GIOCondition condition)
  4290. +{
  4291. + GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
  4292. + GSource *source = g_source_new (&g_io_watch_funcs, sizeof (GIOWin32Watch));
  4293. + GIOWin32Watch *watch = (GIOWin32Watch *)source;
  4294. +
  4295. + watch->channel = channel;
  4296. + g_io_channel_ref (channel);
  4297. +
  4298. + watch->condition = condition;
  4299. +
  4300. + if (win32_channel->data_avail_event == NULL)
  4301. + create_events (win32_channel);
  4302. +
  4303. + watch->pollfd.fd = (gint) win32_channel->data_avail_event;
  4304. + watch->pollfd.events = condition;
  4305. +
  4306. + if (win32_channel->debug)
  4307. + g_print ("g_io_win32_fd_create_watch: fd=%d condition={%s} handle=%#x\n",
  4308. + win32_channel->fd, condition_to_string (condition), watch->pollfd.fd);
  4309. +
  4310. + LOCK (win32_channel->mutex);
  4311. + if (win32_channel->thread_id == 0)
  4312. + {
  4313. + if (condition & G_IO_IN)
  4314. + create_thread (win32_channel, condition, read_thread);
  4315. + else if (condition & G_IO_OUT)
  4316. + create_thread (win32_channel, condition, write_thread);
  4317. + }
  4318. +
  4319. + g_source_add_poll (source, &watch->pollfd);
  4320. + UNLOCK (win32_channel->mutex);
  4321. +
  4322. + return source;
  4323. +}
  4324. +
  4325. +static GIOStatus
  4326. +g_io_win32_console_close (GIOChannel *channel,
  4327. + GError **err)
  4328. +{
  4329. + GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
  4330. +
  4331. + if (close (win32_channel->fd) < 0)
  4332. + {
  4333. + g_set_error (err, G_IO_CHANNEL_ERROR,
  4334. + g_io_channel_error_from_errno (errno),
  4335. + g_strerror (errno));
  4336. + return G_IO_STATUS_ERROR;
  4337. + }
  4338. +
  4339. + return G_IO_STATUS_NORMAL;
  4340. +}
  4341. +
  4342. +static GSource *
  4343. +g_io_win32_console_create_watch (GIOChannel *channel,
  4344. + GIOCondition condition)
  4345. +{
  4346. + GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
  4347. + GSource *source = g_source_new (&g_io_watch_funcs, sizeof (GIOWin32Watch));
  4348. + GIOWin32Watch *watch = (GIOWin32Watch *)source;
  4349. +
  4350. + watch->channel = channel;
  4351. + g_io_channel_ref (channel);
  4352. +
  4353. + watch->condition = condition;
  4354. +
  4355. + watch->pollfd.fd = (gint) _get_osfhandle (win32_channel->fd);
  4356. + watch->pollfd.events = condition;
  4357. +
  4358. + g_source_add_poll (source, &watch->pollfd);
  4359. +
  4360. + return source;
  4361. +}
  4362. +
  4363. +static GIOStatus
  4364. +g_io_win32_sock_read (GIOChannel *channel,
  4365. + gchar *buf,
  4366. + gsize count,
  4367. + gsize *bytes_read,
  4368. + GError **err)
  4369. +{
  4370. + GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
  4371. + gint result;
  4372. + GIOChannelError error;
  4373. + int winsock_error;
  4374. +
  4375. + if (win32_channel->debug)
  4376. + g_print ("g_io_win32_sock_read: sockfd=%d count=%d\n",
  4377. + win32_channel->fd, count);
  4378. +
  4379. + result = recv (win32_channel->fd, buf, count, 0);
  4380. + if (result == SOCKET_ERROR)
  4381. + winsock_error = WSAGetLastError ();
  4382. +
  4383. + if (win32_channel->debug)
  4384. + g_print ("g_io_win32_sock_read: recv=%d %s\n",
  4385. + result,
  4386. + (result == SOCKET_ERROR ? winsock_error_message (winsock_error) : ""));
  4387. +
  4388. + if (result == SOCKET_ERROR)
  4389. + {
  4390. + *bytes_read = 0;
  4391. +
  4392. + switch (winsock_error)
  4393. + {
  4394. + case WSAEINVAL:
  4395. + error = G_IO_CHANNEL_ERROR_INVAL;
  4396. + break;
  4397. + case WSAEWOULDBLOCK:
  4398. + return G_IO_STATUS_AGAIN;
  4399. + default:
  4400. + error = G_IO_CHANNEL_ERROR_FAILED;
  4401. + break;
  4402. + }
  4403. + g_set_error (err, G_IO_CHANNEL_ERROR, error,
  4404. + winsock_error_message (winsock_error));
  4405. + return G_IO_STATUS_ERROR;
  4406. + }
  4407. + else
  4408. + {
  4409. + *bytes_read = result;
  4410. + if (result == 0)
  4411. + return G_IO_STATUS_EOF;
  4412. + else
  4413. + return G_IO_STATUS_NORMAL;
  4414. + }
  4415. +}
  4416. +
  4417. +static GIOStatus
  4418. +g_io_win32_sock_write (GIOChannel *channel,
  4419. + const gchar *buf,
  4420. + gsize count,
  4421. + gsize *bytes_written,
  4422. + GError **err)
  4423. +{
  4424. + GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
  4425. + gint result;
  4426. + GIOChannelError error;
  4427. + int winsock_error;
  4428. +
  4429. + if (win32_channel->debug)
  4430. + g_print ("g_io_win32_sock_write: sockfd=%d count=%d\n",
  4431. + win32_channel->fd, count);
  4432. +
  4433. + result = send (win32_channel->fd, buf, count, 0);
  4434. + if (result == SOCKET_ERROR)
  4435. + winsock_error = WSAGetLastError ();
  4436. +
  4437. + if (win32_channel->debug)
  4438. + g_print ("g_io_win32_sock_write: send=%d %s\n",
  4439. + result,
  4440. + (result == SOCKET_ERROR ? winsock_error_message (winsock_error) : ""));
  4441. +
  4442. + if (result == SOCKET_ERROR)
  4443. + {
  4444. + *bytes_written = 0;
  4445. +
  4446. + switch (winsock_error)
  4447. + {
  4448. + case WSAEINVAL:
  4449. + error = G_IO_CHANNEL_ERROR_INVAL;
  4450. + break;
  4451. + case WSAEWOULDBLOCK:
  4452. + win32_channel->write_would_have_blocked = TRUE;
  4453. + win32_channel->last_events = 0;
  4454. + return G_IO_STATUS_AGAIN;
  4455. + default:
  4456. + error = G_IO_CHANNEL_ERROR_FAILED;
  4457. + break;
  4458. + }
  4459. + g_set_error (err, G_IO_CHANNEL_ERROR, error,
  4460. + winsock_error_message (winsock_error));
  4461. +
  4462. + return G_IO_STATUS_ERROR;
  4463. + }
  4464. + else
  4465. + {
  4466. + *bytes_written = result;
  4467. + win32_channel->write_would_have_blocked = FALSE;
  4468. +
  4469. + return G_IO_STATUS_NORMAL;
  4470. + }
  4471. +}
  4472. +
  4473. +static GIOStatus
  4474. +g_io_win32_sock_close (GIOChannel *channel,
  4475. + GError **err)
  4476. +{
  4477. + GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
  4478. +
  4479. + if (win32_channel->fd != -1)
  4480. + {
  4481. + if (win32_channel->debug)
  4482. + g_print ("g_io_win32_sock_close: closing socket %d\n",
  4483. + win32_channel->fd);
  4484. +
  4485. + closesocket (win32_channel->fd);
  4486. + win32_channel->fd = -1;
  4487. + }
  4488. +
  4489. + /* FIXME error detection? */
  4490. +
  4491. + return G_IO_STATUS_NORMAL;
  4492. +}
  4493. +
  4494. +static GSource *
  4495. +g_io_win32_sock_create_watch (GIOChannel *channel,
  4496. + GIOCondition condition)
  4497. +{
  4498. + GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
  4499. + GSource *source = g_source_new (&g_io_watch_funcs, sizeof (GIOWin32Watch));
  4500. + GIOWin32Watch *watch = (GIOWin32Watch *)source;
  4501. +
  4502. + watch->channel = channel;
  4503. + g_io_channel_ref (channel);
  4504. +
  4505. + watch->condition = condition;
  4506. +
  4507. + if (win32_channel->event == 0)
  4508. + win32_channel->event = (int) WSACreateEvent ();
  4509. +
  4510. + watch->pollfd.fd = win32_channel->event;
  4511. + watch->pollfd.events = condition;
  4512. +
  4513. + if (win32_channel->debug)
  4514. + g_print ("g_io_win32_sock_create_watch: sock=%d handle=%#x condition={%s}\n",
  4515. + win32_channel->fd, watch->pollfd.fd,
  4516. + condition_to_string (watch->condition));
  4517. +
  4518. + g_source_add_poll (source, &watch->pollfd);
  4519. +
  4520. + return source;
  4521. +}
  4522. +
  4523. +GIOChannel *
  4524. +g_io_channel_new_file (const gchar *filename,
  4525. + const gchar *mode,
  4526. + GError **error)
  4527. +{
  4528. + int fid, flags, pmode;
  4529. + GIOChannel *channel;
  4530. +
  4531. + enum { /* Cheesy hack */
  4532. + MODE_R = 1 << 0,
  4533. + MODE_W = 1 << 1,
  4534. + MODE_A = 1 << 2,
  4535. + MODE_PLUS = 1 << 3,
  4536. + } mode_num;
  4537. +
  4538. + g_return_val_if_fail (filename != NULL, NULL);
  4539. + g_return_val_if_fail (mode != NULL, NULL);
  4540. + g_return_val_if_fail ((error == NULL) || (*error == NULL), NULL);
  4541. +
  4542. + switch (mode[0])
  4543. + {
  4544. + case 'r':
  4545. + mode_num = MODE_R;
  4546. + break;
  4547. + case 'w':
  4548. + mode_num = MODE_W;
  4549. + break;
  4550. + case 'a':
  4551. + mode_num = MODE_A;
  4552. + break;
  4553. + default:
  4554. + g_warning ("Invalid GIOFileMode %s.\n", mode);
  4555. + return NULL;
  4556. + }
  4557. +
  4558. + switch (mode[1])
  4559. + {
  4560. + case '\0':
  4561. + break;
  4562. + case '+':
  4563. + if (mode[2] == '\0')
  4564. + {
  4565. + mode_num |= MODE_PLUS;
  4566. + break;
  4567. + }
  4568. + /* Fall through */
  4569. + default:
  4570. + g_warning ("Invalid GIOFileMode %s.\n", mode);
  4571. + return NULL;
  4572. + }
  4573. +
  4574. + switch (mode_num)
  4575. + {
  4576. + case MODE_R:
  4577. + flags = O_RDONLY;
  4578. + pmode = _S_IREAD;
  4579. + break;
  4580. + case MODE_W:
  4581. + flags = O_WRONLY | O_TRUNC | O_CREAT;
  4582. + pmode = _S_IWRITE;
  4583. + break;
  4584. + case MODE_A:
  4585. + flags = O_WRONLY | O_APPEND | O_CREAT;
  4586. + pmode = _S_IWRITE;
  4587. + break;
  4588. + case MODE_R | MODE_PLUS:
  4589. + flags = O_RDWR;
  4590. + pmode = _S_IREAD | _S_IWRITE;
  4591. + break;
  4592. + case MODE_W | MODE_PLUS:
  4593. + flags = O_RDWR | O_TRUNC | O_CREAT;
  4594. + pmode = _S_IREAD | _S_IWRITE;
  4595. + break;
  4596. + case MODE_A | MODE_PLUS:
  4597. + flags = O_RDWR | O_APPEND | O_CREAT;
  4598. + pmode = _S_IREAD | _S_IWRITE;
  4599. + break;
  4600. + default:
  4601. + g_assert_not_reached ();
  4602. + abort ();
  4603. + }
  4604. +
  4605. + /* always open 'untranslated' */
  4606. + fid = g_open (filename, flags | _O_BINARY, pmode);
  4607. +
  4608. + if (g_io_win32_get_debug_flag ())
  4609. + {
  4610. + g_print ("g_io_channel_win32_new_file: open(\"%s\", ", filename);
  4611. + g_win32_print_access_mode (flags|_O_BINARY);
  4612. + g_print (",%#o)=%d\n", pmode, fid);
  4613. + }
  4614. +
  4615. + if (fid < 0)
  4616. + {
  4617. + g_set_error (error, G_FILE_ERROR,
  4618. + g_file_error_from_errno (errno),
  4619. + g_strerror (errno));
  4620. + return (GIOChannel *)NULL;
  4621. + }
  4622. +
  4623. + channel = g_io_channel_win32_new_fd (fid);
  4624. +
  4625. + /* XXX: move this to g_io_channel_win32_new_fd () */
  4626. + channel->close_on_unref = TRUE;
  4627. + channel->is_seekable = TRUE;
  4628. +
  4629. + /* g_io_channel_win32_new_fd sets is_readable and is_writeable to
  4630. + * correspond to actual readability/writeability. Set to FALSE those
  4631. + * that mode doesn't allow
  4632. + */
  4633. + switch (mode_num)
  4634. + {
  4635. + case MODE_R:
  4636. + channel->is_writeable = FALSE;
  4637. + break;
  4638. + case MODE_W:
  4639. + case MODE_A:
  4640. + channel->is_readable = FALSE;
  4641. + break;
  4642. + case MODE_R | MODE_PLUS:
  4643. + case MODE_W | MODE_PLUS:
  4644. + case MODE_A | MODE_PLUS:
  4645. + break;
  4646. + default:
  4647. + g_assert_not_reached ();
  4648. + abort ();
  4649. + }
  4650. +
  4651. + return channel;
  4652. +}
  4653. +
  4654. +#ifdef G_OS_WIN32
  4655. +
  4656. +#undef g_io_channel_new_file
  4657. +
  4658. +/* Binary compatibility version. Not for newly compiled code. */
  4659. +
  4660. +GIOChannel *
  4661. +g_io_channel_new_file (const gchar *filename,
  4662. + const gchar *mode,
  4663. + GError **error)
  4664. +{
  4665. + gchar *utf8_filename = g_locale_to_utf8 (filename, -1, NULL, NULL, error);
  4666. + GIOChannel *retval;
  4667. +
  4668. + if (utf8_filename == NULL)
  4669. + return NULL;
  4670. +
  4671. + retval = g_io_channel_new_file_utf8 (utf8_filename, mode, error);
  4672. +
  4673. + g_free (utf8_filename);
  4674. +
  4675. + return retval;
  4676. +}
  4677. +
  4678. +#endif
  4679. +
  4680. +static GIOStatus
  4681. +g_io_win32_unimpl_set_flags (GIOChannel *channel,
  4682. + GIOFlags flags,
  4683. + GError **err)
  4684. +{
  4685. + GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
  4686. +
  4687. + if (win32_channel->debug)
  4688. + {
  4689. + g_print ("g_io_win32_unimpl_set_flags: ");
  4690. + g_win32_print_gioflags (flags);
  4691. + g_print ("\n");
  4692. + }
  4693. +
  4694. + g_set_error (err, G_IO_CHANNEL_ERROR,
  4695. + G_IO_CHANNEL_ERROR_FAILED,
  4696. + "Not implemented on Win32");
  4697. +
  4698. + return G_IO_STATUS_ERROR;
  4699. +}
  4700. +
  4701. +static GIOFlags
  4702. +g_io_win32_fd_get_flags_internal (GIOChannel *channel,
  4703. + struct stat *st)
  4704. +{
  4705. + GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
  4706. + gchar c;
  4707. + DWORD count;
  4708. +
  4709. + if (st->st_mode & _S_IFIFO)
  4710. + {
  4711. + channel->is_readable =
  4712. + (PeekNamedPipe ((HANDLE) _get_osfhandle (win32_channel->fd), &c, 0, &count, NULL, NULL) != 0) || GetLastError () == ERROR_BROKEN_PIPE;
  4713. + channel->is_writeable =
  4714. + (WriteFile ((HANDLE) _get_osfhandle (win32_channel->fd), &c, 0, &count, NULL) != 0);
  4715. + channel->is_seekable = FALSE;
  4716. + }
  4717. + else
  4718. + {
  4719. + channel->is_readable =
  4720. + (ReadFile ((HANDLE) _get_osfhandle (win32_channel->fd), &c, 0, &count, NULL) != 0);
  4721. + channel->is_writeable =
  4722. + (WriteFile ((HANDLE) _get_osfhandle (win32_channel->fd), &c, 0, &count, NULL) != 0);
  4723. + channel->is_seekable = TRUE;
  4724. + }
  4725. +
  4726. + /* XXX: G_IO_FLAG_APPEND */
  4727. + /* XXX: G_IO_FLAG_NONBLOCK */
  4728. +
  4729. + return 0;
  4730. +}
  4731. +
  4732. +static GIOFlags
  4733. +g_io_win32_fd_get_flags (GIOChannel *channel)
  4734. +{
  4735. + struct stat st;
  4736. + GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
  4737. +
  4738. + g_return_val_if_fail (win32_channel != NULL, 0);
  4739. + g_return_val_if_fail (win32_channel->type == G_IO_WIN32_FILE_DESC, 0);
  4740. +
  4741. + if (0 == fstat (win32_channel->fd, &st))
  4742. + return g_io_win32_fd_get_flags_internal (channel, &st);
  4743. + else
  4744. + return 0;
  4745. +}
  4746. +
  4747. +static GIOFlags
  4748. +g_io_win32_console_get_flags_internal (GIOChannel *channel)
  4749. +{
  4750. + GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
  4751. + HANDLE handle = (HANDLE) _get_osfhandle (win32_channel->fd);
  4752. + gchar c;
  4753. + DWORD count;
  4754. + INPUT_RECORD record;
  4755. +
  4756. + channel->is_readable = PeekConsoleInput (handle, &record, 1, &count);
  4757. + channel->is_writeable = WriteFile (handle, &c, 0, &count, NULL);
  4758. + channel->is_seekable = FALSE;
  4759. +
  4760. + return 0;
  4761. +}
  4762. +
  4763. +static GIOFlags
  4764. +g_io_win32_console_get_flags (GIOChannel *channel)
  4765. +{
  4766. + GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
  4767. +
  4768. + g_return_val_if_fail (win32_channel != NULL, 0);
  4769. + g_return_val_if_fail (win32_channel->type == G_IO_WIN32_CONSOLE, 0);
  4770. +
  4771. + return g_io_win32_console_get_flags_internal (channel);
  4772. +}
  4773. +
  4774. +static GIOFlags
  4775. +g_io_win32_msg_get_flags (GIOChannel *channel)
  4776. +{
  4777. + return 0;
  4778. +}
  4779. +
  4780. +static GIOStatus
  4781. +g_io_win32_sock_set_flags (GIOChannel *channel,
  4782. + GIOFlags flags,
  4783. + GError **err)
  4784. +{
  4785. + GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
  4786. + u_long arg;
  4787. +
  4788. + if (win32_channel->debug)
  4789. + {
  4790. + g_print ("g_io_win32_sock_set_flags: ");
  4791. + g_win32_print_gioflags (flags);
  4792. + g_print ("\n");
  4793. + }
  4794. +
  4795. + if (flags & G_IO_FLAG_NONBLOCK)
  4796. + {
  4797. + arg = 1;
  4798. + if (ioctlsocket (win32_channel->fd, FIONBIO, &arg) == SOCKET_ERROR)
  4799. + {
  4800. + g_set_error (err, G_IO_CHANNEL_ERROR,
  4801. + G_IO_CHANNEL_ERROR_FAILED,
  4802. + winsock_error_message (WSAGetLastError ()));
  4803. + return G_IO_STATUS_ERROR;
  4804. + }
  4805. + }
  4806. + else
  4807. + {
  4808. + arg = 0;
  4809. + if (ioctlsocket (win32_channel->fd, FIONBIO, &arg) == SOCKET_ERROR)
  4810. + {
  4811. + g_set_error (err, G_IO_CHANNEL_ERROR,
  4812. + G_IO_CHANNEL_ERROR_FAILED,
  4813. + winsock_error_message (WSAGetLastError ()));
  4814. + return G_IO_STATUS_ERROR;
  4815. + }
  4816. + }
  4817. +
  4818. + return G_IO_STATUS_NORMAL;
  4819. +}
  4820. +
  4821. +static GIOFlags
  4822. +g_io_win32_sock_get_flags (GIOChannel *channel)
  4823. +{
  4824. + /* Could we do something here? */
  4825. + return 0;
  4826. +}
  4827. +
  4828. +static GIOFuncs win32_channel_msg_funcs = {
  4829. + g_io_win32_msg_read,
  4830. + g_io_win32_msg_write,
  4831. + NULL,
  4832. + g_io_win32_msg_close,
  4833. + g_io_win32_msg_create_watch,
  4834. + g_io_win32_free,
  4835. + g_io_win32_unimpl_set_flags,
  4836. + g_io_win32_msg_get_flags,
  4837. +};
  4838. +
  4839. +static GIOFuncs win32_channel_fd_funcs = {
  4840. + g_io_win32_fd_and_console_read,
  4841. + g_io_win32_fd_and_console_write,
  4842. + g_io_win32_fd_seek,
  4843. + g_io_win32_fd_close,
  4844. + g_io_win32_fd_create_watch,
  4845. + g_io_win32_free,
  4846. + g_io_win32_unimpl_set_flags,
  4847. + g_io_win32_fd_get_flags,
  4848. +};
  4849. +
  4850. +static GIOFuncs win32_channel_console_funcs = {
  4851. + g_io_win32_fd_and_console_read,
  4852. + g_io_win32_fd_and_console_write,
  4853. + NULL,
  4854. + g_io_win32_console_close,
  4855. + g_io_win32_console_create_watch,
  4856. + g_io_win32_free,
  4857. + g_io_win32_unimpl_set_flags,
  4858. + g_io_win32_console_get_flags,
  4859. +};
  4860. +
  4861. +static GIOFuncs win32_channel_sock_funcs = {
  4862. + g_io_win32_sock_read,
  4863. + g_io_win32_sock_write,
  4864. + NULL,
  4865. + g_io_win32_sock_close,
  4866. + g_io_win32_sock_create_watch,
  4867. + g_io_win32_free,
  4868. + g_io_win32_sock_set_flags,
  4869. + g_io_win32_sock_get_flags,
  4870. +};
  4871. +
  4872. +GIOChannel *
  4873. +g_io_channel_win32_new_messages (guint hwnd)
  4874. +{
  4875. + GIOWin32Channel *win32_channel = g_new (GIOWin32Channel, 1);
  4876. + GIOChannel *channel = (GIOChannel *)win32_channel;
  4877. +
  4878. + g_io_channel_init (channel);
  4879. + g_io_channel_win32_init (win32_channel);
  4880. + if (win32_channel->debug)
  4881. + g_print ("g_io_channel_win32_new_messages: hwnd=%#x\n", hwnd);
  4882. + channel->funcs = &win32_channel_msg_funcs;
  4883. + win32_channel->type = G_IO_WIN32_WINDOWS_MESSAGES;
  4884. + win32_channel->hwnd = (HWND) hwnd;
  4885. +
  4886. + /* XXX: check this. */
  4887. + channel->is_readable = IsWindow (win32_channel->hwnd);
  4888. + channel->is_writeable = IsWindow (win32_channel->hwnd);
  4889. +
  4890. + channel->is_seekable = FALSE;
  4891. +
  4892. + return channel;
  4893. +}
  4894. +
  4895. +static GIOChannel *
  4896. +g_io_channel_win32_new_fd_internal (gint fd,
  4897. + struct stat *st)
  4898. +{
  4899. + GIOWin32Channel *win32_channel;
  4900. + GIOChannel *channel;
  4901. +
  4902. + win32_channel = g_new (GIOWin32Channel, 1);
  4903. + channel = (GIOChannel *)win32_channel;
  4904. +
  4905. + g_io_channel_init (channel);
  4906. + g_io_channel_win32_init (win32_channel);
  4907. +
  4908. + win32_channel->fd = fd;
  4909. +
  4910. + if (win32_channel->debug)
  4911. + g_print ("g_io_channel_win32_new_fd: %u\n", fd);
  4912. + if (st->st_mode & _S_IFCHR) /* console */
  4913. + {
  4914. + channel->funcs = &win32_channel_console_funcs;
  4915. + win32_channel->type = G_IO_WIN32_CONSOLE;
  4916. + g_io_win32_console_get_flags_internal (channel);
  4917. + }
  4918. + else
  4919. + {
  4920. + channel->funcs = &win32_channel_fd_funcs;
  4921. + win32_channel->type = G_IO_WIN32_FILE_DESC;
  4922. + g_io_win32_fd_get_flags_internal (channel, st);
  4923. + }
  4924. +
  4925. + return channel;
  4926. +}
  4927. +
  4928. +GIOChannel *
  4929. +g_io_channel_win32_new_fd (gint fd)
  4930. +{
  4931. + struct stat st;
  4932. +
  4933. + if (fstat (fd, &st) == -1)
  4934. + {
  4935. + g_warning (G_STRLOC ": %d isn't a C library file descriptor", fd);
  4936. + return NULL;
  4937. + }
  4938. +
  4939. + return g_io_channel_win32_new_fd_internal (fd, &st);
  4940. +}
  4941. +
  4942. +gint
  4943. +g_io_channel_win32_get_fd (GIOChannel *channel)
  4944. +{
  4945. + GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
  4946. +
  4947. + return win32_channel->fd;
  4948. +}
  4949. +
  4950. +GIOChannel *
  4951. +g_io_channel_win32_new_socket (int socket)
  4952. +{
  4953. + GIOWin32Channel *win32_channel = g_new (GIOWin32Channel, 1);
  4954. + GIOChannel *channel = (GIOChannel *)win32_channel;
  4955. +
  4956. + g_io_channel_init (channel);
  4957. + g_io_channel_win32_init (win32_channel);
  4958. + if (win32_channel->debug)
  4959. + g_print ("g_io_channel_win32_new_socket: sockfd=%d\n", socket);
  4960. + channel->funcs = &win32_channel_sock_funcs;
  4961. + win32_channel->type = G_IO_WIN32_SOCKET;
  4962. + win32_channel->fd = socket;
  4963. +
  4964. + channel->is_readable = TRUE;
  4965. + channel->is_writeable = TRUE;
  4966. + channel->is_seekable = FALSE;
  4967. +
  4968. + return channel;
  4969. +}
  4970. +
  4971. +GIOChannel *
  4972. +g_io_channel_unix_new (gint fd)
  4973. +{
  4974. + gboolean is_fd, is_socket;
  4975. + struct stat st;
  4976. + int optval, optlen;
  4977. +
  4978. + is_fd = (fstat (fd, &st) == 0);
  4979. +
  4980. + optlen = sizeof (optval);
  4981. + is_socket = (getsockopt (fd, SOL_SOCKET, SO_TYPE, (char *) &optval, &optlen) != SOCKET_ERROR);
  4982. +
  4983. + if (is_fd && is_socket)
  4984. + g_warning (G_STRLOC ": %d is both a file descriptor and a socket, file descriptor interpretation assumed.", fd);
  4985. +
  4986. + if (is_fd)
  4987. + return g_io_channel_win32_new_fd_internal (fd, &st);
  4988. +
  4989. + if (is_socket)
  4990. + return g_io_channel_win32_new_socket(fd);
  4991. +
  4992. + g_warning (G_STRLOC ": %d is neither a file descriptor or a socket", fd);
  4993. +
  4994. + return NULL;
  4995. +}
  4996. +
  4997. +gint
  4998. +g_io_channel_unix_get_fd (GIOChannel *channel)
  4999. +{
  5000. + return g_io_channel_win32_get_fd (channel);
  5001. +}
  5002. +
  5003. +void
  5004. +g_io_channel_win32_set_debug (GIOChannel *channel,
  5005. + gboolean flag)
  5006. +{
  5007. + GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
  5008. +
  5009. + win32_channel->debug = flag;
  5010. +}
  5011. +
  5012. +gint
  5013. +g_io_channel_win32_poll (GPollFD *fds,
  5014. + gint n_fds,
  5015. + gint timeout)
  5016. +{
  5017. + int result;
  5018. +
  5019. + g_return_val_if_fail (n_fds >= 0, 0);
  5020. +
  5021. + result = (*g_main_context_get_poll_func (NULL)) (fds, n_fds, timeout);
  5022. +
  5023. + return result;
  5024. +}
  5025. +
  5026. +void
  5027. +g_io_channel_win32_make_pollfd (GIOChannel *channel,
  5028. + GIOCondition condition,
  5029. + GPollFD *fd)
  5030. +{
  5031. + GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
  5032. +
  5033. + switch (win32_channel->type)
  5034. + {
  5035. + case G_IO_WIN32_FILE_DESC:
  5036. + if (win32_channel->data_avail_event == NULL)
  5037. + create_events (win32_channel);
  5038. +
  5039. + fd->fd = (gint) win32_channel->data_avail_event;
  5040. +
  5041. + if (win32_channel->thread_id == 0 && (condition & G_IO_IN))
  5042. + {
  5043. + if (condition & G_IO_IN)
  5044. + create_thread (win32_channel, condition, read_thread);
  5045. + else if (condition & G_IO_OUT)
  5046. + create_thread (win32_channel, condition, write_thread);
  5047. + }
  5048. + break;
  5049. +
  5050. + case G_IO_WIN32_CONSOLE:
  5051. + fd->fd = (gint) _get_osfhandle (win32_channel->fd);
  5052. + break;
  5053. +
  5054. + case G_IO_WIN32_SOCKET:
  5055. + fd->fd = (int) WSACreateEvent ();
  5056. + break;
  5057. +
  5058. + case G_IO_WIN32_WINDOWS_MESSAGES:
  5059. + fd->fd = G_WIN32_MSG_HANDLE;
  5060. + break;
  5061. +
  5062. + default:
  5063. + g_assert_not_reached ();
  5064. + abort ();
  5065. + }
  5066. +
  5067. + fd->events = condition;
  5068. +}
  5069. +
  5070. +/* Binary compatibility */
  5071. +GIOChannel *
  5072. +g_io_channel_win32_new_stream_socket (int socket)
  5073. +{
  5074. + return g_io_channel_win32_new_socket (socket);
  5075. +}
  5076. +
  5077. +#define __G_IO_WIN32_C__
  5078. +#include "galiasdef.c"
  5079. diff --git a/clients/Instantbird/gstrcmp0.c b/clients/Instantbird/gstrcmp0.c
  5080. new file mode 100755
  5081. index 0000000..d21c31a
  5082. --- /dev/null
  5083. +++ b/clients/Instantbird/gstrcmp0.c
  5084. @@ -0,0 +1,22 @@
  5085. +/**
  5086. + * g_strcmp0:
  5087. + * @str1: a C string or %NULL
  5088. + * @str2: another C string or %NULL
  5089. + *
  5090. + * Compares @str1 and @str2 like strcmp(). Handles %NULL
  5091. + * gracefully by sorting it before non-%NULL strings.
  5092. + *
  5093. + * Returns: -1, 0 or 1, if @str1 is <, == or > than @str2.
  5094. + *
  5095. + * Since: 2.16
  5096. + */
  5097. +int
  5098. +g_strcmp0 (const char *str1,
  5099. + const char *str2)
  5100. +{
  5101. + if (!str1)
  5102. + return -(str1 != str2);
  5103. + if (!str2)
  5104. + return str1 != str2;
  5105. + return strcmp (str1, str2);
  5106. +}
  5107. diff --git a/clients/Instantbird/linux/Makefile.in b/clients/Instantbird/linux/Makefile.in
  5108. new file mode 100755
  5109. index 0000000..2916764
  5110. --- /dev/null
  5111. +++ b/clients/Instantbird/linux/Makefile.in
  5112. @@ -0,0 +1,62 @@
  5113. +DEPTH = ../../../..
  5114. +topsrcdir = @top_srcdir@
  5115. +srcdir = @srcdir@
  5116. +VPATH = @srcdir@
  5117. +PROTOCOL = msn_pecan
  5118. +
  5119. +include $(srcdir)/../prpl.mk
  5120. +
  5121. +DEFINES += \
  5122. + -DHAVE_LIBPURPLE \
  5123. + -D_XOPEN_SOURCE \
  5124. + -DINSTANTBIRD \
  5125. + -DPECAN_CVR \
  5126. + -DPECAN_USE_PSM
  5127. +
  5128. +CSRCS = \
  5129. + giochannel.c giounix.c gstrcmp0.c \
  5130. + msn.c \
  5131. + nexus.c \
  5132. + notification.c \
  5133. + page.c \
  5134. + session.c \
  5135. + switchboard.c \
  5136. + sync.c \
  5137. + pn_log.c \
  5138. + pn_printf.c \
  5139. + pn_util.c \
  5140. + pn_buffer.c \
  5141. + pn_error.c \
  5142. + pn_status.c \
  5143. + pn_oim.c \
  5144. + pn_dp_manager.c \
  5145. + cmd/cmdproc.c \
  5146. + cmd/command.c \
  5147. + cmd/msg.c \
  5148. + cmd/table.c \
  5149. + cmd/transaction.c \
  5150. + io/pn_parser.c \
  5151. + ab/pn_group.c \
  5152. + ab/pn_contact.c \
  5153. + ab/pn_contactlist.c \
  5154. + io/pn_stream.c \
  5155. + io/pn_node.c \
  5156. + io/pn_cmd_server.c \
  5157. + io/pn_http_server.c \
  5158. + io/pn_ssl_conn.c \
  5159. + cvr/pn_peer_call.c \
  5160. + cvr/pn_peer_link.c \
  5161. + cvr/pn_peer_msg.c \
  5162. + cvr/pn_msnobj.c \
  5163. + libpurple/xfer.c \
  5164. + fix_purple.c \
  5165. + $(NULL)
  5166. +
  5167. +export::
  5168. + mkdir -p cmd
  5169. + mkdir -p io
  5170. + mkdir -p ab
  5171. + mkdir -p cvr
  5172. + mkdir -p libpurple
  5173. +
  5174. +include $(srcdir)/../prpl-rules.mk
  5175. diff --git a/clients/Instantbird/macosx/Makefile.in b/clients/Instantbird/macosx/Makefile.in
  5176. new file mode 100755
  5177. index 0000000..7f55408
  5178. --- /dev/null
  5179. +++ b/clients/Instantbird/macosx/Makefile.in
  5180. @@ -0,0 +1,63 @@
  5181. +DEPTH = ../../../..
  5182. +topsrcdir = @top_srcdir@
  5183. +srcdir = @srcdir@
  5184. +VPATH = @srcdir@
  5185. +PROTOCOL = msn_pecan
  5186. +
  5187. +include $(srcdir)/../prpl.mk
  5188. +
  5189. +DEFINES += \
  5190. + -DHAVE_LIBPURPLE \
  5191. + -D_XOPEN_SOURCE \
  5192. + -DINSTANTBIRD \
  5193. + -DINTERNAL_MAINLOOP \
  5194. + -DPECAN_CVR \
  5195. + -DPECAN_USE_PSM
  5196. +
  5197. +CSRCS = \
  5198. + giochannel.c giounix.c gstrcmp0.c \
  5199. + msn.c \
  5200. + nexus.c \
  5201. + notification.c \
  5202. + page.c \
  5203. + session.c \
  5204. + switchboard.c \
  5205. + sync.c \
  5206. + pn_log.c \
  5207. + pn_printf.c \
  5208. + pn_util.c \
  5209. + pn_buffer.c \
  5210. + pn_error.c \
  5211. + pn_status.c \
  5212. + pn_oim.c \
  5213. + pn_dp_manager.c \
  5214. + cmd/cmdproc.c \
  5215. + cmd/command.c \
  5216. + cmd/msg.c \
  5217. + cmd/table.c \
  5218. + cmd/transaction.c \
  5219. + io/pn_parser.c \
  5220. + ab/pn_group.c \
  5221. + ab/pn_contact.c \
  5222. + ab/pn_contactlist.c \
  5223. + io/pn_stream.c \
  5224. + io/pn_node.c \
  5225. + io/pn_cmd_server.c \
  5226. + io/pn_http_server.c \
  5227. + io/pn_ssl_conn.c \
  5228. + cvr/pn_peer_call.c \
  5229. + cvr/pn_peer_link.c \
  5230. + cvr/pn_peer_msg.c \
  5231. + cvr/pn_msnobj.c \
  5232. + libpurple/xfer.c \
  5233. + fix_purple.c \
  5234. + $(NULL)
  5235. +
  5236. +export::
  5237. + mkdir -p cmd
  5238. + mkdir -p io
  5239. + mkdir -p ab
  5240. + mkdir -p cvr
  5241. + mkdir -p libpurple
  5242. +
  5243. +include $(srcdir)/../prpl-rules.mk
  5244. diff --git a/clients/Instantbird/win32/Makefile.in b/clients/Instantbird/win32/Makefile.in
  5245. new file mode 100755
  5246. index 0000000..11c136c
  5247. --- /dev/null
  5248. +++ b/clients/Instantbird/win32/Makefile.in
  5249. @@ -0,0 +1,63 @@
  5250. +DEPTH = ../../../..
  5251. +topsrcdir = @top_srcdir@
  5252. +srcdir = @srcdir@
  5253. +VPATH = @srcdir@
  5254. +PROTOCOL = msn_pecan
  5255. +
  5256. +include $(srcdir)/../prpl.mk
  5257. +
  5258. +DEFINES += \
  5259. + -DHAVE_LIBPURPLE \
  5260. + -D_XOPEN_SOURCE \
  5261. + -DINSTANTBIRD \
  5262. + -DINTERNAL_MAINLOOP \
  5263. + -DPECAN_CVR \
  5264. + -DPECAN_USE_PSM
  5265. +
  5266. +CSRCS = \
  5267. + giochannel.c giowin32.c gstrcmp0.c \
  5268. + msn.c \
  5269. + nexus.c \
  5270. + notification.c \
  5271. + page.c \
  5272. + session.c \
  5273. + switchboard.c \
  5274. + sync.c \
  5275. + pn_log.c \
  5276. + pn_printf.c \
  5277. + pn_util.c \
  5278. + pn_buffer.c \
  5279. + pn_error.c \
  5280. + pn_status.c \
  5281. + pn_oim.c \
  5282. + pn_dp_manager.c \
  5283. + cmd/cmdproc.c \
  5284. + cmd/command.c \
  5285. + cmd/msg.c \
  5286. + cmd/table.c \
  5287. + cmd/transaction.c \
  5288. + io/pn_parser.c \
  5289. + ab/pn_group.c \
  5290. + ab/pn_contact.c \
  5291. + ab/pn_contactlist.c \
  5292. + io/pn_stream.c \
  5293. + io/pn_node.c \
  5294. + io/pn_cmd_server.c \
  5295. + io/pn_http_server.c \
  5296. + io/pn_ssl_conn.c \
  5297. + cvr/pn_peer_call.c \
  5298. + cvr/pn_peer_link.c \
  5299. + cvr/pn_peer_msg.c \
  5300. + cvr/pn_msnobj.c \
  5301. + libpurple/xfer.c \
  5302. + fix_purple.c \
  5303. + $(NULL)
  5304. +
  5305. +export::
  5306. + mkdir -p cmd
  5307. + mkdir -p io
  5308. + mkdir -p ab
  5309. + mkdir -p cvr
  5310. + mkdir -p libpurple
  5311. +
  5312. +include $(srcdir)/../prpl-rules.mk
  5313. diff --git a/msn.c b/msn.c
  5314. index 9db608c..560da52 100644
  5315. --- a/msn.c
  5316. +++ b/msn.c
  5317. @@ -1922,6 +1922,9 @@ init_plugin (PurplePlugin *plugin)
  5318. purple_prefs_remove ("/plugins/prpl/msn");
  5319. }
  5320.  
  5321. +#ifdef INSTANTBIRD
  5322. +PURPLE_INIT_PLUGIN(msn_pecan, init_plugin, info);
  5323. +#else
  5324. #ifndef STATIC_PECAN
  5325. G_MODULE_EXPORT gboolean
  5326. purple_init_plugin(PurplePlugin *plugin)
  5327. @@ -1941,3 +1944,4 @@ purple_init_msn_pecan_plugin(void)
  5328. return purple_plugin_register(plugin);
  5329. }
  5330. #endif
  5331. +#endif /* INSTANTBIRD */
  5332. --
  5333. 1.6.5
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement