meillo@367: /* meillo@367: ** MasqMail meillo@367: ** Copyright (C) 2000 Oliver Kurth meillo@367: ** meillo@367: ** This program is free software; you can redistribute it and/or modify meillo@367: ** it under the terms of the GNU General Public License as published by meillo@367: ** the Free Software Foundation; either version 2 of the License, or meillo@367: ** (at your option) any later version. meillo@367: ** meillo@367: ** This program is distributed in the hope that it will be useful, meillo@367: ** but WITHOUT ANY WARRANTY; without even the implied warranty of meillo@367: ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the meillo@367: ** GNU General Public License for more details. meillo@367: ** meillo@367: ** You should have received a copy of the GNU General Public License meillo@367: ** along with this program; if not, write to the Free Software meillo@367: ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. meillo@0: */ meillo@0: meillo@0: #include meillo@0: #include meillo@0: #include meillo@0: #include meillo@0: #include meillo@0: #include meillo@15: meillo@0: #include "readsock.h" meillo@0: meillo@0: jmp_buf jmp_timeout; meillo@0: meillo@10: static void meillo@10: sig_timeout_handler(int sig) meillo@0: { meillo@10: longjmp(jmp_timeout, 1); meillo@0: } meillo@0: meillo@0: static struct sigaction old_sa_alrm; meillo@0: meillo@10: static void meillo@10: alarm_on(int timeout) meillo@0: { meillo@10: struct sigaction sa; meillo@0: meillo@10: sa.sa_handler = sig_timeout_handler; meillo@10: sigemptyset(&(sa.sa_mask)); meillo@10: sa.sa_flags = 0; meillo@10: sigaction(SIGALRM, &sa, &old_sa_alrm); meillo@0: meillo@10: if (timeout > 0) meillo@10: alarm(timeout); meillo@0: } meillo@0: meillo@10: static void meillo@10: alarm_off() meillo@0: { meillo@10: alarm(0); meillo@0: meillo@10: sigaction(SIGALRM, &old_sa_alrm, NULL); meillo@0: } meillo@0: meillo@10: static void meillo@366: _read_chug(FILE *in) meillo@0: { meillo@10: int c = 0; meillo@0: meillo@10: c = fgetc(in); meillo@10: while (isspace(c) && (c != EOF)) meillo@10: c = fgetc(in); meillo@10: ungetc(c, in); meillo@0: } meillo@0: meillo@10: static int meillo@366: _read_line(FILE *in, char *buf, int buf_len, int timeout) meillo@0: { meillo@10: int p = 0; meillo@10: int c = 0; meillo@0: meillo@10: c = fgetc(in); meillo@10: while ((c != '\n') && (c != EOF) && (p < buf_len - 1)) { meillo@10: buf[p++] = c; meillo@10: c = fgetc(in); meillo@10: } meillo@0: meillo@15: buf[p] = '\0'; meillo@0: meillo@10: if (c == EOF) meillo@10: return -1; meillo@10: else if (p >= buf_len) { meillo@10: ungetc(c, in); meillo@10: return -2; meillo@10: } meillo@0: meillo@10: buf[p++] = c; /* \n */ meillo@15: buf[p] = '\0'; meillo@0: meillo@10: return p; meillo@0: } meillo@0: meillo@10: int meillo@366: read_sockline(FILE *in, char *buf, int buf_len, int timeout, unsigned int flags) meillo@0: { meillo@10: int p = 0; meillo@0: meillo@10: if (setjmp(jmp_timeout) != 0) { meillo@10: alarm_off(); meillo@10: return -3; meillo@10: } meillo@0: meillo@10: alarm_on(timeout); meillo@0: meillo@10: /* strip leading spaces */ meillo@10: if (flags & READSOCKL_CHUG) { meillo@10: _read_chug(in); meillo@10: } meillo@0: meillo@10: p = _read_line(in, buf, buf_len, timeout); meillo@0: meillo@10: alarm_off(); meillo@0: meillo@10: if (p > 1) { meillo@10: /* here we are sure that buf[p-1] == '\n' */ meillo@10: if (flags & READSOCKL_CVT_CRLF) { meillo@10: if ((buf[p - 2] == '\r') && (buf[p - 1] == '\n')) { meillo@10: buf[p - 2] = '\n'; meillo@10: buf[p - 1] = 0; meillo@10: p--; meillo@10: } meillo@10: } meillo@10: } meillo@10: return p; meillo@0: } meillo@0: meillo@10: int meillo@367: read_sockline1(FILE *in, char **pbuf, int *buf_len, int timeout, meillo@367: unsigned int flags) meillo@0: { meillo@10: int p = 0, size = *buf_len; meillo@10: char *buf; meillo@0: meillo@10: if (setjmp(jmp_timeout) != 0) { meillo@10: alarm_off(); meillo@10: return -3; meillo@10: } meillo@0: meillo@10: alarm_on(timeout); meillo@0: meillo@10: /* strip leading spaces */ meillo@10: if (flags & READSOCKL_CHUG) { meillo@10: _read_chug(in); meillo@10: } meillo@0: meillo@377: if (!*pbuf) { meillo@377: *pbuf = (char *) malloc(size); meillo@377: if (!*pbuf) { meillo@377: fprintf(stderr, "Out of memory.\n"); meillo@377: exit(1); meillo@377: } meillo@377: } meillo@10: buf = *pbuf; meillo@0: meillo@10: while (1) { meillo@10: int pp; meillo@0: meillo@10: pp = _read_line(in, buf, size, timeout); meillo@10: if (pp == -2) { meillo@10: *pbuf = realloc(*pbuf, *buf_len + size); meillo@10: buf = *pbuf + *buf_len; meillo@10: *buf_len += size; meillo@10: p += size; meillo@10: } else { meillo@10: if (pp > 0) meillo@10: p += pp; meillo@10: else meillo@10: p = pp; meillo@10: break; meillo@10: } meillo@10: } meillo@0: meillo@10: alarm_off(); meillo@10: meillo@10: if (p > 1) { meillo@10: buf = *pbuf; meillo@10: /* here we are sure that buf[p-1] == '\n' */ meillo@10: if (flags & READSOCKL_CVT_CRLF) { meillo@10: if ((buf[p - 2] == '\r') && (buf[p - 1] == '\n')) { meillo@10: buf[p - 2] = '\n'; meillo@15: buf[p - 1] = '\0'; meillo@10: p--; meillo@10: } meillo@10: } meillo@10: } meillo@10: return p; meillo@0: }