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