fget.c revision 90792
190792Sgshapiro/* 290792Sgshapiro * Copyright (c) 2000-2001 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> 1690792SgshapiroSM_RCSID("@(#)$Id: fget.c,v 1.24 2001/09/11 04:04:48 gshapiro 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: 3690792Sgshapiro** success: returns value of 'buf' 3790792Sgshapiro** failure: NULL (no characters were read) 3890792Sgshapiro** timeout: NULL and errno set to EAGAIN 3990792Sgshapiro** 4090792Sgshapiro** Side Effects: 4190792Sgshapiro** may move the file pointer 4290792Sgshapiro*/ 4390792Sgshapiro 4490792Sgshapirochar * 4590792Sgshapirosm_io_fgets(fp, timeout, buf, n) 4690792Sgshapiro register SM_FILE_T *fp; 4790792Sgshapiro int timeout; 4890792Sgshapiro char *buf; 4990792Sgshapiro register int n; 5090792Sgshapiro{ 5190792Sgshapiro register int len; 5290792Sgshapiro register char *s; 5390792Sgshapiro register unsigned char *p, *t; 5490792Sgshapiro 5590792Sgshapiro SM_REQUIRE_ISA(fp, SmFileMagic); 5690792Sgshapiro if (n <= 0) /* sanity check */ 5790792Sgshapiro return NULL; 5890792Sgshapiro 5990792Sgshapiro s = buf; 6090792Sgshapiro n--; /* leave space for NUL */ 6190792Sgshapiro while (n > 0) 6290792Sgshapiro { 6390792Sgshapiro /* If the buffer is empty, refill it. */ 6490792Sgshapiro if ((len = fp->f_r) <= 0) 6590792Sgshapiro { 6690792Sgshapiro 6790792Sgshapiro /* 6890792Sgshapiro ** Timeout is only passed if we can't get the data 6990792Sgshapiro ** from the buffer (which is counted as immediately). 7090792Sgshapiro */ 7190792Sgshapiro 7290792Sgshapiro if (sm_refill(fp, timeout) != 0) 7390792Sgshapiro { 7490792Sgshapiro /* EOF/error: stop with partial or no line */ 7590792Sgshapiro if (s == buf) 7690792Sgshapiro return NULL; 7790792Sgshapiro break; 7890792Sgshapiro } 7990792Sgshapiro len = fp->f_r; 8090792Sgshapiro } 8190792Sgshapiro p = fp->f_p; 8290792Sgshapiro 8390792Sgshapiro /* 8490792Sgshapiro ** Scan through at most n bytes of the current buffer, 8590792Sgshapiro ** looking for '\n'. If found, copy up to and including 8690792Sgshapiro ** newline, and stop. Otherwise, copy entire chunk 8790792Sgshapiro ** and loop. 8890792Sgshapiro */ 8990792Sgshapiro 9090792Sgshapiro if (len > n) 9190792Sgshapiro len = n; 9290792Sgshapiro t = (unsigned char *) memchr((void *) p, '\n', len); 9390792Sgshapiro if (t != NULL) 9490792Sgshapiro { 9590792Sgshapiro len = ++t - p; 9690792Sgshapiro fp->f_r -= len; 9790792Sgshapiro fp->f_p = t; 9890792Sgshapiro (void) memcpy((void *) s, (void *) p, len); 9990792Sgshapiro s[len] = 0; 10090792Sgshapiro return buf; 10190792Sgshapiro } 10290792Sgshapiro fp->f_r -= len; 10390792Sgshapiro fp->f_p += len; 10490792Sgshapiro (void) memcpy((void *) s, (void *) p, len); 10590792Sgshapiro s += len; 10690792Sgshapiro n -= len; 10790792Sgshapiro } 10890792Sgshapiro *s = 0; 10990792Sgshapiro return buf; 11090792Sgshapiro} 111