xref: /freebsd/contrib/sendmail/libsm/fget.c (revision ee7b0571c2c18bdec848ed2044223cc88db29bd8)
140266059SGregory Neil Shapiro /*
25dd76dd0SGregory Neil Shapiro  * Copyright (c) 2000-2001, 2013 Proofpoint, Inc. and its suppliers.
340266059SGregory Neil Shapiro  *      All rights reserved.
440266059SGregory Neil Shapiro  * Copyright (c) 1990, 1993
540266059SGregory Neil Shapiro  *	The Regents of the University of California.  All rights reserved.
640266059SGregory Neil Shapiro  *
740266059SGregory Neil Shapiro  * This code is derived from software contributed to Berkeley by
840266059SGregory Neil Shapiro  * Chris Torek.
940266059SGregory Neil Shapiro  *
1040266059SGregory Neil Shapiro  * By using this file, you agree to the terms and conditions set
1140266059SGregory Neil Shapiro  * forth in the LICENSE file which can be found at the top level of
1240266059SGregory Neil Shapiro  * the sendmail distribution.
1340266059SGregory Neil Shapiro  */
1440266059SGregory Neil Shapiro 
1540266059SGregory Neil Shapiro #include <sm/gen.h>
16*4313cc83SGregory Neil Shapiro SM_RCSID("@(#)$Id: fget.c,v 1.26 2013-11-22 20:51:42 ca Exp $")
1740266059SGregory Neil Shapiro #include <stdlib.h>
1840266059SGregory Neil Shapiro #include <string.h>
1940266059SGregory Neil Shapiro #include <sm/io.h>
2040266059SGregory Neil Shapiro #include <sm/assert.h>
2140266059SGregory Neil Shapiro #include "local.h"
2240266059SGregory Neil Shapiro 
2340266059SGregory Neil Shapiro /*
2440266059SGregory Neil Shapiro **  SM_IO_FGETS -- get a string from a file
2540266059SGregory Neil Shapiro **
2640266059SGregory Neil Shapiro **  Read at most n-1 characters from the given file.
2740266059SGregory Neil Shapiro **  Stop when a newline has been read, or the count ('n') runs out.
2840266059SGregory Neil Shapiro **
2940266059SGregory Neil Shapiro **	Parameters:
3040266059SGregory Neil Shapiro **		fp -- the file to read from
3140266059SGregory Neil Shapiro **		timeout -- time to complete reading the string in milliseconds
3240266059SGregory Neil Shapiro **		buf -- buffer to place read string in
3340266059SGregory Neil Shapiro **		n -- size of 'buf'
3440266059SGregory Neil Shapiro **
3540266059SGregory Neil Shapiro **	Returns:
36552d4955SGregory Neil Shapiro **		success: number of characters
37552d4955SGregory Neil Shapiro **		failure: -1
38552d4955SGregory Neil Shapiro **		timeout: -1 and errno set to EAGAIN
3940266059SGregory Neil Shapiro **
4040266059SGregory Neil Shapiro **	Side Effects:
4140266059SGregory Neil Shapiro **		may move the file pointer
4240266059SGregory Neil Shapiro */
4340266059SGregory Neil Shapiro 
44552d4955SGregory Neil Shapiro int
4540266059SGregory Neil Shapiro sm_io_fgets(fp, timeout, buf, n)
4640266059SGregory Neil Shapiro 	register SM_FILE_T *fp;
4740266059SGregory Neil Shapiro 	int timeout;
4840266059SGregory Neil Shapiro 	char *buf;
4940266059SGregory Neil Shapiro 	register int n;
5040266059SGregory Neil Shapiro {
51552d4955SGregory Neil Shapiro 	int len, r;
52552d4955SGregory Neil Shapiro 	char *s;
53552d4955SGregory Neil Shapiro 	unsigned char *p, *t;
5440266059SGregory Neil Shapiro 
5540266059SGregory Neil Shapiro 	SM_REQUIRE_ISA(fp, SmFileMagic);
5640266059SGregory Neil Shapiro 	if (n <= 0)		/* sanity check */
57552d4955SGregory Neil Shapiro 		return -1;
5840266059SGregory Neil Shapiro 
5940266059SGregory Neil Shapiro 	s = buf;
6040266059SGregory Neil Shapiro 	n--;			/* leave space for NUL */
61552d4955SGregory Neil Shapiro 	r = 0;
6240266059SGregory Neil Shapiro 	while (n > 0)
6340266059SGregory Neil Shapiro 	{
6440266059SGregory Neil Shapiro 		/* If the buffer is empty, refill it. */
6540266059SGregory Neil Shapiro 		if ((len = fp->f_r) <= 0)
6640266059SGregory Neil Shapiro 		{
6740266059SGregory Neil Shapiro 
6840266059SGregory Neil Shapiro 			/*
6940266059SGregory Neil Shapiro 			**  Timeout is only passed if we can't get the data
7040266059SGregory Neil Shapiro 			**  from the buffer (which is counted as immediately).
7140266059SGregory Neil Shapiro 			*/
7240266059SGregory Neil Shapiro 
7340266059SGregory Neil Shapiro 			if (sm_refill(fp, timeout) != 0)
7440266059SGregory Neil Shapiro 			{
7540266059SGregory Neil Shapiro 				/* EOF/error: stop with partial or no line */
7640266059SGregory Neil Shapiro 				if (s == buf)
77552d4955SGregory Neil Shapiro 					return -1;
7840266059SGregory Neil Shapiro 				break;
7940266059SGregory Neil Shapiro 			}
8040266059SGregory Neil Shapiro 			len = fp->f_r;
8140266059SGregory Neil Shapiro 		}
8240266059SGregory Neil Shapiro 		p = fp->f_p;
8340266059SGregory Neil Shapiro 
8440266059SGregory Neil Shapiro 		/*
8540266059SGregory Neil Shapiro 		**  Scan through at most n bytes of the current buffer,
8640266059SGregory Neil Shapiro 		**  looking for '\n'.  If found, copy up to and including
8740266059SGregory Neil Shapiro 		**  newline, and stop.  Otherwise, copy entire chunk
8840266059SGregory Neil Shapiro 		**  and loop.
8940266059SGregory Neil Shapiro 		*/
9040266059SGregory Neil Shapiro 
9140266059SGregory Neil Shapiro 		if (len > n)
9240266059SGregory Neil Shapiro 			len = n;
9340266059SGregory Neil Shapiro 		t = (unsigned char *) memchr((void *) p, '\n', len);
9440266059SGregory Neil Shapiro 		if (t != NULL)
9540266059SGregory Neil Shapiro 		{
9640266059SGregory Neil Shapiro 			len = ++t - p;
97552d4955SGregory Neil Shapiro 			r += len;
9840266059SGregory Neil Shapiro 			fp->f_r -= len;
9940266059SGregory Neil Shapiro 			fp->f_p = t;
10040266059SGregory Neil Shapiro 			(void) memcpy((void *) s, (void *) p, len);
10140266059SGregory Neil Shapiro 			s[len] = 0;
102552d4955SGregory Neil Shapiro 			return r;
10340266059SGregory Neil Shapiro 		}
10440266059SGregory Neil Shapiro 		fp->f_r -= len;
10540266059SGregory Neil Shapiro 		fp->f_p += len;
10640266059SGregory Neil Shapiro 		(void) memcpy((void *) s, (void *) p, len);
10740266059SGregory Neil Shapiro 		s += len;
108552d4955SGregory Neil Shapiro 		r += len;
10940266059SGregory Neil Shapiro 		n -= len;
11040266059SGregory Neil Shapiro 	}
11140266059SGregory Neil Shapiro 	*s = 0;
112552d4955SGregory Neil Shapiro 	return r;
11340266059SGregory Neil Shapiro }
114