fget.c revision 249729
190792Sgshapiro/* 2249729Sgshapiro * Copyright (c) 2000-2001, 2013 Sendmail, Inc. and its suppliers. 390792Sgshapiro * All rights reserved. 490792Sgshapiro * Copyright (c) 1990, 1993 590792Sgshapiro * The Regents of the University of California. All rights reserved. 690792Sgshapiro * 790792Sgshapiro * This code is derived from software contributed to Berkeley by 890792Sgshapiro * Chris Torek. 990792Sgshapiro * 1090792Sgshapiro * By using this file, you agree to the terms and conditions set 1190792Sgshapiro * forth in the LICENSE file which can be found at the top level of 1290792Sgshapiro * the sendmail distribution. 1390792Sgshapiro */ 1490792Sgshapiro 1590792Sgshapiro#include <sm/gen.h> 16249729SgshapiroSM_RCSID("@(#)$Id: fget.c,v 1.25 2013/03/12 15:24:50 ca Exp $") 1790792Sgshapiro#include <stdlib.h> 1890792Sgshapiro#include <string.h> 1990792Sgshapiro#include <sm/io.h> 2090792Sgshapiro#include <sm/assert.h> 2190792Sgshapiro#include "local.h" 2290792Sgshapiro 2390792Sgshapiro/* 2490792Sgshapiro** SM_IO_FGETS -- get a string from a file 2590792Sgshapiro** 2690792Sgshapiro** Read at most n-1 characters from the given file. 2790792Sgshapiro** Stop when a newline has been read, or the count ('n') runs out. 2890792Sgshapiro** 2990792Sgshapiro** Parameters: 3090792Sgshapiro** fp -- the file to read from 3190792Sgshapiro** timeout -- time to complete reading the string in milliseconds 3290792Sgshapiro** buf -- buffer to place read string in 3390792Sgshapiro** n -- size of 'buf' 3490792Sgshapiro** 3590792Sgshapiro** Returns: 36249729Sgshapiro** success: number of characters 37249729Sgshapiro** failure: -1 38249729Sgshapiro** timeout: -1 and errno set to EAGAIN 3990792Sgshapiro** 4090792Sgshapiro** Side Effects: 4190792Sgshapiro** may move the file pointer 4290792Sgshapiro*/ 4390792Sgshapiro 44249729Sgshapiroint 4590792Sgshapirosm_io_fgets(fp, timeout, buf, n) 4690792Sgshapiro register SM_FILE_T *fp; 4790792Sgshapiro int timeout; 4890792Sgshapiro char *buf; 4990792Sgshapiro register int n; 5090792Sgshapiro{ 51249729Sgshapiro int len, r; 52249729Sgshapiro char *s; 53249729Sgshapiro unsigned char *p, *t; 5490792Sgshapiro 5590792Sgshapiro SM_REQUIRE_ISA(fp, SmFileMagic); 5690792Sgshapiro if (n <= 0) /* sanity check */ 57249729Sgshapiro return -1; 5890792Sgshapiro 5990792Sgshapiro s = buf; 6090792Sgshapiro n--; /* leave space for NUL */ 61249729Sgshapiro r = 0; 6290792Sgshapiro while (n > 0) 6390792Sgshapiro { 6490792Sgshapiro /* If the buffer is empty, refill it. */ 6590792Sgshapiro if ((len = fp->f_r) <= 0) 6690792Sgshapiro { 6790792Sgshapiro 6890792Sgshapiro /* 6990792Sgshapiro ** Timeout is only passed if we can't get the data 7090792Sgshapiro ** from the buffer (which is counted as immediately). 7190792Sgshapiro */ 7290792Sgshapiro 7390792Sgshapiro if (sm_refill(fp, timeout) != 0) 7490792Sgshapiro { 7590792Sgshapiro /* EOF/error: stop with partial or no line */ 7690792Sgshapiro if (s == buf) 77249729Sgshapiro return -1; 7890792Sgshapiro break; 7990792Sgshapiro } 8090792Sgshapiro len = fp->f_r; 8190792Sgshapiro } 8290792Sgshapiro p = fp->f_p; 8390792Sgshapiro 8490792Sgshapiro /* 8590792Sgshapiro ** Scan through at most n bytes of the current buffer, 8690792Sgshapiro ** looking for '\n'. If found, copy up to and including 8790792Sgshapiro ** newline, and stop. Otherwise, copy entire chunk 8890792Sgshapiro ** and loop. 8990792Sgshapiro */ 9090792Sgshapiro 9190792Sgshapiro if (len > n) 9290792Sgshapiro len = n; 9390792Sgshapiro t = (unsigned char *) memchr((void *) p, '\n', len); 9490792Sgshapiro if (t != NULL) 9590792Sgshapiro { 9690792Sgshapiro len = ++t - p; 97249729Sgshapiro r += len; 9890792Sgshapiro fp->f_r -= len; 9990792Sgshapiro fp->f_p = t; 10090792Sgshapiro (void) memcpy((void *) s, (void *) p, len); 10190792Sgshapiro s[len] = 0; 102249729Sgshapiro return r; 10390792Sgshapiro } 10490792Sgshapiro fp->f_r -= len; 10590792Sgshapiro fp->f_p += len; 10690792Sgshapiro (void) memcpy((void *) s, (void *) p, len); 10790792Sgshapiro s += len; 108249729Sgshapiro r += len; 10990792Sgshapiro n -= len; 11090792Sgshapiro } 11190792Sgshapiro *s = 0; 112249729Sgshapiro return r; 11390792Sgshapiro} 114