1/*
2 * This program is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU General Public License as
4 * published by the Free Software Foundation; either version 2 of
5 * the License, or (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
15 * MA 02111-1307 USA
16 */
17/*
18 * Part of Very Secure FTPd
19 * Licence: GPL v2
20 * Author: Chris Evans
21 * netstr.c
22 *
23 * The netstr interface extends the standard string interface, adding
24 * functions which can cope safely with building strings from the network,
25 * and send them out too.
26 */
27
28#include "netstr.h"
29#include "str.h"
30#include "sysstr.h"
31#include "utility.h"
32#include "sysutil.h"
33
34void
35str_netfd_alloc(struct mystr* p_str, int fd, char term, char* p_readbuf,
36                unsigned int maxlen)
37{
38  int retval;
39  unsigned int bytes_read;
40  unsigned int i;
41  char* p_readpos = p_readbuf;
42  unsigned int left = maxlen;
43  while (1)
44  {
45    if (p_readpos + left != p_readbuf + maxlen)
46    {
47      bug("poor buffer accounting in str_netfd_alloc");
48    }
49    /* Did we hit the max? */
50    if (left == 0)
51    {
52      str_empty(p_str);
53      return;
54    }
55    retval = vsf_sysutil_recv_peek(fd, p_readpos, left);
56    if (vsf_sysutil_retval_is_error(retval))
57    {
58      die("vsf_sysutil_recv_peek");
59    }
60    else if (retval == 0)
61    {
62      die("vsf_sysutil_recv_peek: no data");
63    }
64    bytes_read = (unsigned int) retval;
65    /* Search for the terminator */
66    for (i=0; i < bytes_read; i++)
67    {
68      if (p_readpos[i] == term)
69      {
70        /* Got it! */
71        retval = vsf_sysutil_read_loop(fd, p_readpos, i + 1);
72        if (vsf_sysutil_retval_is_error(retval) ||
73            (unsigned int) retval != i + 1)
74        {
75          die("vsf_sysutil_read_loop");
76        }
77        if (p_readpos[i] != term)
78        {
79          die("missing terminator in str_netfd_alloc");
80        }
81        str_alloc_alt_term(p_str, p_readbuf, term);
82        return;
83      }
84    }
85    /* Not found in this read chunk, so consume the data and re-loop */
86    if (bytes_read > left)
87    {
88      bug("bytes_read > left in str_netfd_alloc");
89    }
90    left -= bytes_read;
91    retval = vsf_sysutil_read_loop(fd, p_readpos, bytes_read);
92    if (vsf_sysutil_retval_is_error(retval) ||
93        (unsigned int) retval != bytes_read)
94    {
95      die("vsf_sysutil_read_loop");
96    }
97    p_readpos += bytes_read;
98  } /* END: while(1) */
99}
100
101int
102str_netfd_write(const struct mystr* p_str, int fd)
103{
104  int ret = 0;
105  int retval;
106  unsigned int str_len = str_getlen(p_str);
107  if (str_len == 0)
108  {
109    bug("zero str_len in str_netfd_write");
110  }
111  retval = str_write_loop(p_str, fd);
112  if (vsf_sysutil_retval_is_error(retval) || (unsigned int) retval != str_len)
113  {
114    ret = -1;
115  }
116  return ret;
117}
118
119int
120str_netfd_read(struct mystr* p_str, int fd, unsigned int len)
121{
122  int retval;
123  str_reserve(p_str, len);
124  str_trunc(p_str, len);
125  retval = str_read_loop(p_str, fd);
126  if (vsf_sysutil_retval_is_error(retval) || (unsigned int) retval != len)
127  {
128    return -1;
129  }
130  return retval;
131}
132
133