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