1 | /* |
---|
2 | * Public interface to remctl client library. |
---|
3 | * |
---|
4 | * Written by Russ Allbery <rra@stanford.edu> |
---|
5 | * Based on prior work by Anton Ushakov |
---|
6 | * Copyright 2002, 2003, 2004, 2005, 2006, 2007, 2008 |
---|
7 | * Board of Trustees, Leland Stanford Jr. University |
---|
8 | * |
---|
9 | * Permission to use, copy, modify, and distribute this software and its |
---|
10 | * documentation for any purpose and without fee is hereby granted, provided |
---|
11 | * that the above copyright notice appear in all copies and that both that |
---|
12 | * copyright notice and this permission notice appear in supporting |
---|
13 | * documentation, and that the name of Stanford University not be used in |
---|
14 | * advertising or publicity pertaining to distribution of the software without |
---|
15 | * specific, written prior permission. Stanford University makes no |
---|
16 | * representations about the suitability of this software for any purpose. It |
---|
17 | * is provided "as is" without express or implied warranty. |
---|
18 | * |
---|
19 | * THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED |
---|
20 | * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF |
---|
21 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. |
---|
22 | */ |
---|
23 | |
---|
24 | #ifndef REMCTL_H |
---|
25 | #define REMCTL_H 1 |
---|
26 | |
---|
27 | #include <sys/types.h> /* size_t */ |
---|
28 | |
---|
29 | /* |
---|
30 | * Normally we treat this as an opaque struct and clients who want to use the |
---|
31 | * iovec interface need to include <sys/uio.h> themselves. However, Windows |
---|
32 | * doesn't provide this struct, so we define it for Windows. It will already |
---|
33 | * be defined by remctl's internal build system, so deal with that. |
---|
34 | */ |
---|
35 | #if defined(_WIN32) && !defined(PORTABLE_UIO_H) |
---|
36 | struct iovec { |
---|
37 | void *iov_base; |
---|
38 | size_t iov_len; |
---|
39 | }; |
---|
40 | #else |
---|
41 | struct iovec; |
---|
42 | #endif |
---|
43 | |
---|
44 | /* |
---|
45 | * BEGIN_DECLS is used at the beginning of declarations so that C++ |
---|
46 | * compilers don't mangle their names. END_DECLS is used at the end. |
---|
47 | */ |
---|
48 | #undef BEGIN_DECLS |
---|
49 | #undef END_DECLS |
---|
50 | #ifdef __cplusplus |
---|
51 | # define BEGIN_DECLS extern "C" { |
---|
52 | # define END_DECLS } |
---|
53 | #else |
---|
54 | # define BEGIN_DECLS /* empty */ |
---|
55 | # define END_DECLS /* empty */ |
---|
56 | #endif |
---|
57 | |
---|
58 | /* The standard remctl port and the legacy port used before 2.11. */ |
---|
59 | #define REMCTL_PORT 4373 |
---|
60 | #define REMCTL_PORT_OLD 4444 |
---|
61 | |
---|
62 | /* The standard remctl service name for /etc/services. */ |
---|
63 | #define REMCTL_SERVICE "remctl" |
---|
64 | |
---|
65 | /* Used to hold the return from a simple remctl call. */ |
---|
66 | struct remctl_result { |
---|
67 | char *error; /* remctl error if non-NULL. */ |
---|
68 | char *stdout_buf; /* Standard output. */ |
---|
69 | size_t stdout_len; /* Length of standard output. */ |
---|
70 | char *stderr_buf; /* Standard error. */ |
---|
71 | size_t stderr_len; /* Length of standard error. */ |
---|
72 | int status; /* Exit status of remote command. */ |
---|
73 | }; |
---|
74 | |
---|
75 | /* The type of a remctl_output struct. */ |
---|
76 | enum remctl_output_type { |
---|
77 | REMCTL_OUT_OUTPUT, |
---|
78 | REMCTL_OUT_STATUS, |
---|
79 | REMCTL_OUT_ERROR, |
---|
80 | REMCTL_OUT_DONE |
---|
81 | }; |
---|
82 | |
---|
83 | /* Used to return incremental output from a persistant connection. */ |
---|
84 | struct remctl_output { |
---|
85 | enum remctl_output_type type; |
---|
86 | char *data; |
---|
87 | size_t length; |
---|
88 | int stream; /* 1 == stdout, 2 == stderr */ |
---|
89 | int status; /* Exit status of remote command. */ |
---|
90 | int error; /* Remote error code. */ |
---|
91 | }; |
---|
92 | |
---|
93 | /* Opaque struct representing an open remctl connection. */ |
---|
94 | struct remctl; |
---|
95 | |
---|
96 | BEGIN_DECLS |
---|
97 | |
---|
98 | /* |
---|
99 | * First, the simple interface. Given a host, a port (may be 0 to use |
---|
100 | * REMCTL_PORT with fallback to REMCTL_PORT_OLD), the principal to |
---|
101 | * authenticate as (may be NULL to use host/<host>), and a command (as a |
---|
102 | * null-terminated argv-style vector), run the command on that host and port |
---|
103 | * and return a struct remctl_result. The result should be freed with |
---|
104 | * remctl_result_free. |
---|
105 | */ |
---|
106 | struct remctl_result *remctl(const char *host, unsigned short port, |
---|
107 | const char *principal, const char **command); |
---|
108 | void remctl_result_free(struct remctl_result *); |
---|
109 | |
---|
110 | /* |
---|
111 | * Now, the more complex persistant interface. The basic housekeeping |
---|
112 | * functions. port may be 0, in which case REMCTL_PORT is used with fallback |
---|
113 | * to REMCTL_PORT_OLD. principal may be NULL, in which case host/<host> is |
---|
114 | * used (with no transformations applied to host at all). |
---|
115 | */ |
---|
116 | struct remctl *remctl_new(void); |
---|
117 | int remctl_open(struct remctl *, const char *host, unsigned short port, |
---|
118 | const char *principal); |
---|
119 | void remctl_close(struct remctl *); |
---|
120 | |
---|
121 | /* |
---|
122 | * Send a complete remote command. Returns true on success, false on failure. |
---|
123 | * On failure, use remctl_error to get the error. There are two forms of this |
---|
124 | * function; remctl_command takes a NULL-terminated array of nul-terminated |
---|
125 | * strings and remctl_commandv takes an array of struct iovecs of length |
---|
126 | * count. The latter form should be used for binary data. |
---|
127 | */ |
---|
128 | int remctl_command(struct remctl *, const char **command); |
---|
129 | int remctl_commandv(struct remctl *, const struct iovec *, size_t count); |
---|
130 | |
---|
131 | /* |
---|
132 | * Retrieve output from the remote server. Each call to this function on the |
---|
133 | * same connection invalidates the previous returned remctl_output struct, so |
---|
134 | * copy any data that should be persistant before calling this function again. |
---|
135 | * |
---|
136 | * This function will return zero or more REMCTL_OUT_OUTPUT types followed by |
---|
137 | * a REMCTL_OUT_STATUS type, *or* a REMCTL_OUT_ERROR type. In either case, |
---|
138 | * any subsequent call before sending a new command will return |
---|
139 | * REMCTL_OUT_DONE. If the function returns NULL, an internal error occurred; |
---|
140 | * call remctl_error to retrieve the error message. |
---|
141 | * |
---|
142 | * The remctl_output struct should *not* be freed by the caller. It will be |
---|
143 | * invalidated after another call to remctl_output or to remctl_close on the |
---|
144 | * same connection. |
---|
145 | */ |
---|
146 | struct remctl_output *remctl_output(struct remctl *); |
---|
147 | |
---|
148 | /* |
---|
149 | * Call remctl_error after an error return to retrieve the internal error |
---|
150 | * message. The returned error string will be invalidated by any subsequent |
---|
151 | * call to a remctl library function. |
---|
152 | */ |
---|
153 | const char *remctl_error(struct remctl *); |
---|
154 | |
---|
155 | END_DECLS |
---|
156 | |
---|
157 | #endif /* !REMCTL_H */ |
---|