summaryrefslogtreecommitdiff
path: root/src/util.h
blob: eb6e22ee91051e8c38a67bb879f8829117a95738 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
/* Copyright (c) 2015-2016 Yoran Heling

  Permission is hereby granted, free of charge, to any person obtaining
  a copy of this software and associated documentation files (the
  "Software"), to deal in the Software without restriction, including
  without limitation the rights to use, copy, modify, merge, publish,
  distribute, sublicense, and/or sell copies of the Software, and to
  permit persons to whom the Software is furnished to do so, subject to
  the following conditions:

  The above copyright notice and this permission notice shall be included
  in all copies or substantial portions of the Software.

  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
  CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

#ifndef FCGY_UTIL_H
#define FCGY_UTIL_H

/* This is pretty much a struct sockaddr_storage, but also incorporates UNIX
 * sockets. */
typedef union {
    struct sockaddr generic;
    struct sockaddr_in in;
    struct sockaddr_in6 in6;
    struct sockaddr_un un;
} util_sockaddr;

/* Should be large enough to hold a full IPv6 addr + port or a complete UNIX
 * path.  The latter tends to have a larger maximum limit. */
#define UTIL_ADDRSTRLEN sizeof(struct sockaddr_un)


#define FCGY_NONBLOCK 1
#define FCGY_CLOEXEC 2

int util_fd_flags(int, uint32_t);
int util_serversock(int, void *, socklen_t, uint32_t);


/* Parse a socket address specification, supports the following formats:
 *   [ipv6]:port
 *   ipv4:port
 *   port        (interpreted as 0.0.0.0:port)
 *   /unix/path  (must be absolute)
 *   -           (standard I/O)
 * Writes the address into *sock and returns 0 on success.
 * Standard I/O is indicated as sock->generic.sa_family = 0.
 * TODO: Support and resolve hostnames? (Can't support hostnames with multiple
 * A/AAAA records, however). */
int util_parse_addr(const char *, util_sockaddr *);

/* Reverse of util_parse_addr(). Destination buffer must be large enough to
 * hold UTIL_ADDRSTRLEN bytes. */
void util_format_addr(const util_sockaddr *, char *);


static inline socklen_t util_sockaddr_len(int type) {
    switch(type) {
    case AF_INET:  return sizeof(struct sockaddr_in); break;
    case AF_INET6: return sizeof(struct sockaddr_in6); break;
    case AF_UNIX:  return sizeof(struct sockaddr_un); break;
    }
    return 0;
}


/* Parse a shell command line into an argv list. Splits the string into tokens
 * and parses shell escapes and quoting. This function is limited only to
 * \-escapes and single/double quotes. Comments, variable expansions, globs,
 * etc, etc are not interpreted and are passed through as-is.
 * Returns -1 if the string ends with an escape char or unmatched quote.
 * Returns 0 on success, and the resulting vector is written to the second
 * argument. The argument list can be freed with util_free_argv().
 */
typedef vec_t(char *) util_argv;
void util_free_argv(util_argv *);
int util_parse_argv(const char *, util_argv *);

#endif