+ static int readtimeout();
+
+ /* set the timeout */
+ if (ReadTimeout != 0)
+ {
+ if (setjmp(CtxReadTimeout) != 0)
+ {
+# ifdef LOG
+ syslog(LOG_NOTICE,
+ "timeout waiting for input from %s\n",
+ RealHostName? RealHostName: "local");
+# endif
+ errno = 0;
+ usrerr("451 timeout waiting for input");
+ buf[0] = '\0';
+ return (NULL);
+ }
+ ev = setevent((time_t) ReadTimeout, readtimeout, 0);
+ }
+
+ /* try to read */
+ p = NULL;
+ while (p == NULL && !feof(fp) && !ferror(fp))
+ {
+ errno = 0;
+ p = fgets(buf, siz, fp);
+ if (errno == EINTR)
+ clearerr(fp);
+ }
+
+ /* clear the event if it has not sprung */
+ clrevent(ev);
+
+ /* clean up the books and exit */
+ LineNumber++;
+ if (p == NULL)
+ {
+ buf[0] = '\0';
+ return (NULL);
+ }
+ if (!EightBit)
+ for (p = buf; *p != '\0'; p++)
+ *p &= ~0200;
+ return (buf);
+}
+
+static
+readtimeout()
+{
+ longjmp(CtxReadTimeout, 1);
+}
+\f/*
+** FGETFOLDED -- like fgets, but know about folded lines.
+**
+** Parameters:
+** buf -- place to put result.
+** n -- bytes available.
+** f -- file to read from.
+**
+** Returns:
+** buf on success, NULL on error or EOF.
+**
+** Side Effects:
+** buf gets lines from f, with continuation lines (lines
+** with leading white space) appended. CRLF's are mapped
+** into single newlines. Any trailing NL is stripped.
+*/
+
+char *
+fgetfolded(buf, n, f)