chiark / gitweb /
Fixed spurious failure with Interrupted system call; Fixed race when fd closed at...
[userv.git] / both.c
diff --git a/both.c b/both.c
new file mode 100644 (file)
index 0000000..46cf85c
--- /dev/null
+++ b/both.c
@@ -0,0 +1,56 @@
+/*
+ * userv - both.c
+ * Useful very-low-level utility routines, used in both client and daemon.
+ * These do not (and cannot) depend on infrastructure eg syscallerror,
+ * because these are not the same.
+ *
+ * Copyright (C)1999 Ian Jackson
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with userv; if not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/* Some nasty people can return 0/EOF + EINTR from stdio !
+ * These functions attempt to work around this braindamage by retrying
+ * the call after clearerr.  If this doesn't work then clearly your
+ * libc is _completely_ fubar rather than just somewhat fubar.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#include "both.h"
+
+int working_getc(FILE *file) {
+  int c;
+  
+  for (;;) {
+    c= getc(file);
+    if (c != EOF || errno != EINTR) return c;
+    clearerr(file);
+  }
+}
+
+size_t working_fread(void *ptr, size_t sz, FILE *file) {
+  size_t done, nr;
+
+  done= 0;
+  for (;;) {
+    nr= fread((char*)ptr + done, 1, sz-done, file);
+    done += nr;
+    if (done == sz || !ferror(file) || errno != EINTR) return done;
+    clearerr(file);
+  }
+}