source: web/old/remctl-2.14/perl/Remctl.xs @ f6f3e91

web
Last change on this file since f6f3e91 was f6f3e91, checked in by Jessica B. Hamrick <jhamrick@…>, 15 years ago

Preserve directory hierarchy (not sure what happened to it)

  • Property mode set to 100644
File size: 6.1 KB
Line 
1/*
2 * Perl bindings for the remctl client library.
3 *
4 * This is an XS source file, suitable for processing by xsubpp, that
5 * generates Perl bindings for the libremctl client library.  It supports
6 * both the simplified interface (via a simple remctl call) and the more
7 * complex interface (returning a Net::Remctl object which is then used for
8 * subsequent calls).
9 *
10 * The remctl opaque struct is mapped to a Net::Remctl object and supports
11 * methods equivalent to the library functions prefixed by remctl_ that take
12 * struct remctl * as their first argument.  remctl_new() is mapped to the
13 * new method of the class.  remctl_output structs are returned as
14 * Net::Remctl::Output objects with accessor functions that return the
15 * elements of the remctl_output struct.  The types (output, status, error,
16 * and done) are returned as lowercase strings rather than as numeric
17 * constants.
18 *
19 * The simple interface is available via an exported remctl function which
20 * returns a Net::Remctl::Result object with accessor functions for the
21 * members of the struct.
22 *
23 * Written by Russ Allbery <rra@stanford.edu>
24 * Copyright 2007, 2008 Board of Trustees, Leland Stanford Jr. University
25 *
26 * See LICENSE for licensing terms.
27 */
28
29#include <EXTERN.h>
30#include <perl.h>
31#include <XSUB.h>
32
33#include <errno.h>
34
35#include <remctl.h>
36
37/*
38 * These typedefs are needed for xsubpp to work its magic with type
39 * translation to Perl objects.
40 */
41typedef struct remctl *         Net__Remctl;
42typedef struct remctl_result *  Net__Remctl__Result;
43typedef struct remctl_output *  Net__Remctl__Output;
44
45/* Map the remctl_output type constants to strings. */
46const struct {
47    enum remctl_output_type type;
48    const char *name;
49} OUTPUT_TYPE[] = {
50    { REMCTL_OUT_OUTPUT, "output" },
51    { REMCTL_OUT_STATUS, "status" },
52    { REMCTL_OUT_ERROR,  "error"  },
53    { REMCTL_OUT_DONE,   "done"   },
54    { 0,                 NULL     }
55};
56
57/* XS code below this point. */
58
59MODULE = Net::Remctl    PACKAGE = Net::Remctl   PREFIX = remctl_
60
61PROTOTYPES: ENABLE
62
63Net::Remctl::Result
64remctl(host, port, principal, ...)
65    const char *host
66    unsigned short port
67    const char *principal
68  PREINIT:
69    size_t count = items - 3;
70    size_t i;
71    const char **command;
72  CODE:
73    if (items <= 3)
74        croak("Too few arguments to Net::Remctl::remctl");
75    if (principal != NULL && *principal == '\0')
76        principal = NULL;
77    command = malloc(sizeof(char *) * (count + 1));
78    if (command == NULL)
79        croak("Error allocating memory in Net::Remctl::remctl: %s",
80              strerror(errno));
81    for (i = 0; i <= count; i++)
82        command[i] = SvPV_nolen(ST(i + 3));
83    command[count] = NULL;
84    RETVAL = remctl(host, port, principal, command);
85    if (RETVAL == NULL)
86        croak("Error creating Net::Remctl::Result object: %s",
87              strerror(errno));
88    free(command);
89  OUTPUT:
90    RETVAL
91
92Net::Remctl
93remctl_new(class)
94    const char *class
95  CODE:
96    RETVAL = remctl_new();
97    if (RETVAL == NULL)
98        croak("Error creating %s object: %s", class, strerror(errno));
99  OUTPUT:
100    RETVAL
101
102void
103DESTROY(self)
104    Net::Remctl self
105  CODE:
106    if (self != NULL)
107        remctl_close(self);
108
109void
110remctl_open(self, host, ...)
111    Net::Remctl self
112    const char *host
113  PROTOTYPE: DISABLE
114  PREINIT:
115    size_t count = items - 2;
116    unsigned short port = 0;
117    const char *principal = NULL;
118  PPCODE:
119    if (count > 2)
120        croak("Too many arguments to Net::Remctl::open");
121    if (count >= 1)
122        port = SvUV(ST(2));
123    if (count >= 2 && ST(3) != &PL_sv_undef) {
124        principal = SvPV_nolen(ST(3));
125        if (*principal == '\0')
126            principal = NULL;
127    }
128    if (remctl_open(self, host, port, principal))
129        XSRETURN_YES;
130    else
131        XSRETURN_UNDEF;
132
133void
134remctl_command(self, ...)
135    Net::Remctl self
136  PREINIT:
137    struct iovec *args;
138    size_t count = items - 1;
139    size_t i;
140    int status;
141  PPCODE:
142    if (count == 0)
143        croak("Too few arguments to Net::Remctl::command");
144    args = malloc(sizeof(struct iovec) * count);
145    if (args == NULL)
146        croak("Error allocating memory in Net::Remctl::command: %s",
147              strerror(errno));
148    for (i = 1; i <= count; i++)
149        args[i - 1].iov_base = SvPV(ST(i), args[i - 1].iov_len);
150    status = remctl_commandv(self, args, count);
151    free(args);
152    if (status)
153        XSRETURN_YES;
154    else
155        XSRETURN_UNDEF;
156
157Net::Remctl::Output
158remctl_output(self)
159    Net::Remctl self
160
161const char *
162remctl_error(self)
163    Net::Remctl self
164
165MODULE = Net::Remctl    PACKAGE = Net::Remctl::Result
166
167void
168DESTROY(self)
169    Net::Remctl::Result self
170  CODE:
171    remctl_result_free(self);
172
173char *
174error(self)
175    Net::Remctl::Result self
176  CODE:
177    RETVAL = self->error;
178  OUTPUT:
179    RETVAL
180
181SV *
182stdout(self)
183    Net::Remctl::Result self
184  CODE:
185    if (self->stdout_buf == NULL)
186        XSRETURN_UNDEF;
187    else
188        RETVAL = newSVpvn(self->stdout_buf, self->stdout_len);
189  OUTPUT:
190    RETVAL
191
192SV *
193stderr(self)
194    Net::Remctl::Result self
195  CODE:
196    if (self->stderr_buf == NULL)
197        XSRETURN_UNDEF;
198    else
199        RETVAL = newSVpvn(self->stderr_buf, self->stderr_len);
200  OUTPUT:
201    RETVAL
202
203int
204status(self)
205    Net::Remctl::Result self
206  CODE:
207    RETVAL = self->status;
208  OUTPUT:
209    RETVAL
210
211MODULE = Net::Remctl    PACKAGE = Net::Remctl::Output
212
213const char *
214type(self)
215    Net::Remctl::Output self
216  PREINIT:
217    size_t i;
218  CODE:
219    RETVAL = NULL;
220    for (i = 0; OUTPUT_TYPE[i].name != NULL; i++)
221        if (OUTPUT_TYPE[i].type == self->type) {
222            RETVAL = OUTPUT_TYPE[self->type].name;
223            break;
224        }
225  OUTPUT:
226    RETVAL
227
228SV *
229data(self)
230    Net::Remctl::Output self
231  CODE:
232    if (self->data == NULL)
233        XSRETURN_UNDEF;
234    else
235        RETVAL = newSVpvn(self->data, self->length);
236  OUTPUT:
237    RETVAL
238
239size_t
240length(self)
241    Net::Remctl::Output self
242  CODE:
243    RETVAL = self->length;
244  OUTPUT:
245    RETVAL
246
247int
248stream(self)
249    Net::Remctl::Output self
250  CODE:
251    RETVAL = self->stream;
252  OUTPUT:
253    RETVAL
254
255int
256status(self)
257    Net::Remctl::Output self
258  CODE:
259    RETVAL = self->status;
260  OUTPUT:
261    RETVAL
262
263int
264error(self)
265    Net::Remctl::Output self
266  CODE:
267    RETVAL = self->error;
268  OUTPUT:
269    RETVAL
Note: See TracBrowser for help on using the repository browser.