1 | /* |
---|
2 | * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. |
---|
3 | * All rights reserved. |
---|
4 | * Copyright (c) 1990, 1993 |
---|
5 | * The Regents of the University of California. All rights reserved. |
---|
6 | * |
---|
7 | * This code is derived from software contributed to Berkeley by |
---|
8 | * Chris Torek. |
---|
9 | * |
---|
10 | * By using this file, you agree to the terms and conditions set |
---|
11 | * forth in the LICENSE file which can be found at the top level of |
---|
12 | * the sendmail distribution. |
---|
13 | */ |
---|
14 | |
---|
15 | #include <sm/gen.h> |
---|
16 | SM_RCSID("@(#)$Id: fget.c,v 1.1.1.1 2003-04-08 15:06:04 zacheiss Exp $") |
---|
17 | #include <stdlib.h> |
---|
18 | #include <string.h> |
---|
19 | #include <sm/io.h> |
---|
20 | #include <sm/assert.h> |
---|
21 | #include "local.h" |
---|
22 | |
---|
23 | /* |
---|
24 | ** SM_IO_FGETS -- get a string from a file |
---|
25 | ** |
---|
26 | ** Read at most n-1 characters from the given file. |
---|
27 | ** Stop when a newline has been read, or the count ('n') runs out. |
---|
28 | ** |
---|
29 | ** Parameters: |
---|
30 | ** fp -- the file to read from |
---|
31 | ** timeout -- time to complete reading the string in milliseconds |
---|
32 | ** buf -- buffer to place read string in |
---|
33 | ** n -- size of 'buf' |
---|
34 | ** |
---|
35 | ** Returns: |
---|
36 | ** success: returns value of 'buf' |
---|
37 | ** failure: NULL (no characters were read) |
---|
38 | ** timeout: NULL and errno set to EAGAIN |
---|
39 | ** |
---|
40 | ** Side Effects: |
---|
41 | ** may move the file pointer |
---|
42 | */ |
---|
43 | |
---|
44 | char * |
---|
45 | sm_io_fgets(fp, timeout, buf, n) |
---|
46 | register SM_FILE_T *fp; |
---|
47 | int timeout; |
---|
48 | char *buf; |
---|
49 | register int n; |
---|
50 | { |
---|
51 | register int len; |
---|
52 | register char *s; |
---|
53 | register unsigned char *p, *t; |
---|
54 | |
---|
55 | SM_REQUIRE_ISA(fp, SmFileMagic); |
---|
56 | if (n <= 0) /* sanity check */ |
---|
57 | return NULL; |
---|
58 | |
---|
59 | s = buf; |
---|
60 | n--; /* leave space for NUL */ |
---|
61 | while (n > 0) |
---|
62 | { |
---|
63 | /* If the buffer is empty, refill it. */ |
---|
64 | if ((len = fp->f_r) <= 0) |
---|
65 | { |
---|
66 | |
---|
67 | /* |
---|
68 | ** Timeout is only passed if we can't get the data |
---|
69 | ** from the buffer (which is counted as immediately). |
---|
70 | */ |
---|
71 | |
---|
72 | if (sm_refill(fp, timeout) != 0) |
---|
73 | { |
---|
74 | /* EOF/error: stop with partial or no line */ |
---|
75 | if (s == buf) |
---|
76 | return NULL; |
---|
77 | break; |
---|
78 | } |
---|
79 | len = fp->f_r; |
---|
80 | } |
---|
81 | p = fp->f_p; |
---|
82 | |
---|
83 | /* |
---|
84 | ** Scan through at most n bytes of the current buffer, |
---|
85 | ** looking for '\n'. If found, copy up to and including |
---|
86 | ** newline, and stop. Otherwise, copy entire chunk |
---|
87 | ** and loop. |
---|
88 | */ |
---|
89 | |
---|
90 | if (len > n) |
---|
91 | len = n; |
---|
92 | t = (unsigned char *) memchr((void *) p, '\n', len); |
---|
93 | if (t != NULL) |
---|
94 | { |
---|
95 | len = ++t - p; |
---|
96 | fp->f_r -= len; |
---|
97 | fp->f_p = t; |
---|
98 | (void) memcpy((void *) s, (void *) p, len); |
---|
99 | s[len] = 0; |
---|
100 | return buf; |
---|
101 | } |
---|
102 | fp->f_r -= len; |
---|
103 | fp->f_p += len; |
---|
104 | (void) memcpy((void *) s, (void *) p, len); |
---|
105 | s += len; |
---|
106 | n -= len; |
---|
107 | } |
---|
108 | *s = 0; |
---|
109 | return buf; |
---|
110 | } |
---|