190792Sgshapiro/*
2261194Sgshapiro * Copyright (c) 2000-2001, 2013 Proofpoint, 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>
16266527SgshapiroSM_RCSID("@(#)$Id: fget.c,v 1.26 2013-11-22 20:51:42 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