~jamesodhunt/ubuntu/raring/upstart/1.6

« back to all changes in this revision

Viewing changes to nih-dbus-tool/main.c

  • Committer: Scott James Remnant
  • Date: 2010-02-04 23:39:59 UTC
  • mfrom: (1182.1.45 upstart)
  • mto: This revision was merged to the branch mainline in revision 1250.
  • Revision ID: scott@netsplit.com-20100204233959-7kajqjnaoh7208ob
Tags: upstream-0.6.5
ImportĀ upstreamĀ versionĀ 0.6.5

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* nih-dbus-tool
2
 
 *
3
 
 * Copyright Ā© 2009 Scott James Remnant <scott@netsplit.com>.
4
 
 * Copyright Ā© 2009 Canonical Ltd.
5
 
 *
6
 
 * This program is free software; you can redistribute it and/or modify
7
 
 * it under the terms of the GNU General Public License version 2, as
8
 
 * published by the Free Software Foundation.
9
 
 *
10
 
 * This program is distributed in the hope that it will be useful,
11
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 
 * GNU General Public License for more details.
14
 
 *
15
 
 * You should have received a copy of the GNU General Public License along
16
 
 * with this program; if not, write to the Free Software Foundation, Inc.,
17
 
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18
 
 */
19
 
 
20
 
#ifdef HAVE_CONFIG_H
21
 
# include <config.h>
22
 
#endif /* HAVE_CONFIG_H */
23
 
 
24
 
 
25
 
#include <sys/types.h>
26
 
#include <sys/stat.h>
27
 
 
28
 
#include <errno.h>
29
 
#include <fcntl.h>
30
 
#include <stdio.h>
31
 
#include <stdlib.h>
32
 
#include <string.h>
33
 
#include <unistd.h>
34
 
 
35
 
#include <nih/macros.h>
36
 
#include <nih/alloc.h>
37
 
#include <nih/string.h>
38
 
#include <nih/main.h>
39
 
#include <nih/option.h>
40
 
#include <nih/logging.h>
41
 
#include <nih/error.h>
42
 
 
43
 
#include "node.h"
44
 
#include "interface.h"
45
 
#include "parse.h"
46
 
#include "output.h"
47
 
 
48
 
 
49
 
/* Prototypes for option functions */
50
 
int mode_option (NihOption *option, const char *arg);
51
 
 
52
 
/* Prototypes for local functions */
53
 
char *source_file_path (const void *parent, const char *output_path,
54
 
                        const char *filename)
55
 
        __attribute__ ((warn_unused_result, malloc));
56
 
char *header_file_path (const void *parent, const char *output_path,
57
 
                        const char *filename)
58
 
        __attribute__ ((warn_unused_result, malloc));
59
 
 
60
 
 
61
 
/**
62
 
 * mode_option:
63
 
 * @option: NihOption invoked,
64
 
 * @arg: argument to parse.
65
 
 *
66
 
 * This option setter parses the output mode argument @arg and sets
67
 
 * the value member of @option, which must be a pointer to an integer.
68
 
 *
69
 
 * The arg_name member of @option must not be NULL.
70
 
 **/
71
 
int
72
 
mode_option (NihOption * option,
73
 
             const char *arg)
74
 
{
75
 
        int *value;
76
 
 
77
 
        nih_assert (option != NULL);
78
 
        nih_assert (option->value != NULL);
79
 
        nih_assert (arg != NULL);
80
 
 
81
 
        value = (int *)option->value;
82
 
 
83
 
        if (! strcmp (arg, "proxy")) {
84
 
                *value = FALSE;
85
 
        } else if (! strcmp (arg, "object")) {
86
 
                *value = TRUE;
87
 
        } else {
88
 
                fprintf (stderr, _("%s: illegal output mode: %s\n"),
89
 
                         program_name, arg);
90
 
                nih_main_suggest_help ();
91
 
                return -1;
92
 
        }
93
 
 
94
 
        return 0;
95
 
}
96
 
 
97
 
 
98
 
/**
99
 
 * source_file_path:
100
 
 * @parent: parent object for new string,
101
 
 * @output_path: output path,
102
 
 * @filename: input filename.
103
 
 *
104
 
 * Generates a path to the output source (.c) file from either the output
105
 
 * path given in @output_path or the input filename given in @filename,
106
 
 * depending on which one is not NULL.
107
 
 *
108
 
 * If @parent is not NULL, it should be a pointer to another object which
109
 
 * will be used as a parent for the returned string.  When all parents
110
 
 * of the returned string are freed, the returned string will also be
111
 
 * freed.
112
 
 *
113
 
 * Returns: newly allocated string or NULL if insufficient memory.
114
 
 **/
115
 
char *
116
 
source_file_path (const void *parent,
117
 
                  const char *output_path,
118
 
                  const char *filename)
119
 
{
120
 
        char *path;
121
 
 
122
 
        nih_assert ((output_path != NULL) || (filename != NULL));
123
 
 
124
 
        if (output_path) {
125
 
                char *ptr;
126
 
 
127
 
                /* When the output path is given, return it; but allow for
128
 
                 * the output path being the header to make Makefile rules
129
 
                 * easier, and replace extension with .c when given one.
130
 
                 */
131
 
                ptr = strrchr (output_path, '.');
132
 
                if (ptr && (! strcmp (ptr, ".h"))) {
133
 
                        path = nih_strndup (parent, output_path,
134
 
                                            ptr - output_path);
135
 
                        if (! path)
136
 
                                return NULL;
137
 
 
138
 
                        if (! nih_strcat (&path, parent, ".c")) {
139
 
                                nih_free (path);
140
 
                                return NULL;
141
 
                        }
142
 
                } else {
143
 
                        path = nih_strdup (parent, output_path);
144
 
                }
145
 
 
146
 
        } else if (filename) {
147
 
                char *ptr;
148
 
 
149
 
                /* Always output to the current directory */
150
 
                ptr = strrchr (filename, '/');
151
 
                if (ptr)
152
 
                        filename = ptr + 1;
153
 
 
154
 
                /* When the input filename is given, strip the extension off
155
 
                 * and replace with .c unless the extension is .c or .h in
156
 
                 * which case we append the .c extension instead
157
 
                 */
158
 
                ptr = strrchr (filename, '.');
159
 
                if (ptr && strcmp (ptr, ".c") && strcmp (ptr, ".h")) {
160
 
                        path = nih_strndup (parent, filename, ptr - filename);
161
 
                        if (! path)
162
 
                                return NULL;
163
 
                } else {
164
 
                        path = nih_strdup (parent, filename);
165
 
                        if (! path)
166
 
                                return NULL;
167
 
                }
168
 
 
169
 
                if (! nih_strcat (&path, parent, ".c")) {
170
 
                        nih_free (path);
171
 
                        return NULL;
172
 
                }
173
 
        }
174
 
 
175
 
        return path;
176
 
}
177
 
 
178
 
/**
179
 
 * header_file_path:
180
 
 * @parent: parent object for new string,
181
 
 * @output_path: output path,
182
 
 * @filename: input filename.
183
 
 *
184
 
 * Generates a path to the output header (.h) file from either the output
185
 
 * path given in @output_path or the input filename given in @filename,
186
 
 * depending on which one is not NULL.
187
 
 *
188
 
 * If @parent is not NULL, it should be a pointer to another object which
189
 
 * will be used as a parent for the returned string.  When all parents
190
 
 * of the returned string are freed, the returned string will also be
191
 
 * freed.
192
 
 *
193
 
 * Returns: newly allocated string or NULL if insufficient memory.
194
 
 **/
195
 
char *
196
 
header_file_path (const void *parent,
197
 
                  const char *output_path,
198
 
                  const char *filename)
199
 
{
200
 
        char *path;
201
 
 
202
 
        nih_assert ((output_path != NULL) || (filename != NULL));
203
 
 
204
 
        if (output_path) {
205
 
                char *ptr;
206
 
 
207
 
                /* When the output path is given, and is the header file,
208
 
                 * return it; otherwise replace the extension with .h or
209
 
                 * append it if there was no extension
210
 
                 */
211
 
                ptr = strrchr (output_path, '.');
212
 
                if (ptr && (! strcmp (ptr, ".h"))) {
213
 
                        path = nih_strdup (parent, output_path);
214
 
                } else if (ptr) {
215
 
                        path = nih_strndup (parent, output_path,
216
 
                                            ptr - output_path);
217
 
                        if (! path)
218
 
                                return NULL;
219
 
 
220
 
                        if (! nih_strcat (&path, parent, ".h")) {
221
 
                                nih_free (path);
222
 
                                return NULL;
223
 
                        }
224
 
                } else {
225
 
                        path = nih_strdup (parent, output_path);
226
 
                        if (! path)
227
 
                                return NULL;
228
 
 
229
 
                        if (! nih_strcat (&path, parent, ".h")) {
230
 
                                nih_free (path);
231
 
                                return NULL;
232
 
                        }
233
 
                }
234
 
 
235
 
 
236
 
        } else if (filename) {
237
 
                char *ptr;
238
 
 
239
 
                /* Always output to the current directory */
240
 
                ptr = strrchr (filename, '/');
241
 
                if (ptr)
242
 
                        filename = ptr + 1;
243
 
 
244
 
                /* When the input filename is given, strip the extension off
245
 
                 * and replace with .h unless the extension is .c or .h in
246
 
                 * which case we append the .h extension instead
247
 
                 */
248
 
                ptr = strrchr (filename, '.');
249
 
                if (ptr && strcmp (ptr, ".c") && strcmp (ptr, ".h")) {
250
 
                        path = nih_strndup (parent, filename, ptr - filename);
251
 
                        if (! path)
252
 
                                return NULL;
253
 
                } else {
254
 
                        path = nih_strdup (parent, filename);
255
 
                        if (! path)
256
 
                                return NULL;
257
 
                }
258
 
 
259
 
                if (! nih_strcat (&path, parent, ".h")) {
260
 
                        nih_free (path);
261
 
                        return NULL;
262
 
                }
263
 
        }
264
 
 
265
 
        return path;
266
 
}
267
 
 
268
 
 
269
 
#ifndef TEST
270
 
/**
271
 
 * object:
272
 
 *
273
 
 * Set to TRUE to output code for a remote object with C access methods or
274
 
 * FALSE for a local object implementation wrapping existing C functions.
275
 
 **/
276
 
static int object = FALSE;
277
 
 
278
 
/**
279
 
 * prefix:
280
 
 *
281
 
 * Prefix of expected and generated functions.
282
 
 **/
283
 
static const char *prefix = NULL;
284
 
 
285
 
/**
286
 
 * default_interface:
287
 
 *
288
 
 * Interface which should not have the last component of its name included
289
 
 * in generated symbol names.
290
 
 **/
291
 
static const char *default_interface = NULL;
292
 
 
293
 
/**
294
 
 * output_path:
295
 
 *
296
 
 * Path to output C code to, header is automatically placed alongside.
297
 
 **/
298
 
static const char *output_path = NULL;
299
 
 
300
 
 
301
 
/**
302
 
 * options:
303
 
 *
304
 
 * Command-line options accepted by this tool.
305
 
 **/
306
 
static NihOption options[] = {
307
 
        { 0,   "mode", N_("output mode: object, or proxy [default: proxy]"),
308
 
          NULL, "MODE", &object, mode_option },
309
 
        { 0,   "prefix", N_("prefix for C functions [default: dbus]"),
310
 
          NULL, "PREFIX", &prefix, NULL },
311
 
        { 0,   "default-interface", N_("interface name not included in symbols"),
312
 
          NULL, "INTERFACE", &default_interface, NULL },
313
 
        { 'o', "output", N_("write C source to FILENAME, header alongside"),
314
 
          NULL, "FILENAME", &output_path, NULL },
315
 
 
316
 
        NIH_OPTION_LAST
317
 
};
318
 
 
319
 
 
320
 
int
321
 
main (int   argc,
322
 
      char *argv[])
323
 
{
324
 
        char **         args;
325
 
        char *          filename;
326
 
        nih_local char *source_path = NULL;
327
 
        nih_local char *header_path = NULL;
328
 
        int             source_fd;
329
 
        int             header_fd;
330
 
        Node *          node;
331
 
 
332
 
        nih_main_init (argv[0]);
333
 
 
334
 
        nih_option_set_usage (_("[XMLFILE]"));
335
 
        nih_option_set_synopsis (_("Generate C bindings for D-Bus objects"));
336
 
        nih_option_set_help (_("Fill this in later"));
337
 
 
338
 
        args = nih_option_parser (NULL, argc, argv, options, FALSE);
339
 
        if (! args)
340
 
                exit (1);
341
 
 
342
 
        /* Filename defaults to standard input when not specified, or when
343
 
         * specified as "-".
344
 
         */
345
 
        filename = args[0];
346
 
        if (filename && (! strcmp (filename, "-")))
347
 
                filename = NULL;
348
 
 
349
 
        /* Output path must be specified when we're using standard input */
350
 
        if ((! filename) && (! output_path)) {
351
 
                fprintf (stderr, _("%s: --output must be specified when using standard input\n"),
352
 
                         program_name);
353
 
                nih_main_suggest_help ();
354
 
                exit (1);
355
 
        }
356
 
 
357
 
        /* Calculate output paths */
358
 
        source_path = source_file_path (NULL, output_path, filename);
359
 
        if (! source_path) {
360
 
                nih_error ("%s", strerror (ENOMEM));
361
 
                exit (1);
362
 
        }
363
 
 
364
 
        header_path = header_file_path (NULL, output_path, filename);
365
 
        if (! header_path) {
366
 
                nih_error ("%s", strerror (ENOMEM));
367
 
                exit (1);
368
 
        }
369
 
 
370
 
        /* Set default prefix if not set */
371
 
        if (! prefix)
372
 
                prefix = "dbus";
373
 
 
374
 
 
375
 
        /* Parse the input file, which may be standard input */
376
 
        if (filename) {
377
 
                int fd;
378
 
 
379
 
                fd = open (filename, O_RDONLY);
380
 
                if (fd < 0) {
381
 
                        nih_error ("%s: %s", filename, strerror (errno));
382
 
                        exit (1);
383
 
                }
384
 
 
385
 
                node = parse_xml (NULL, fd, filename);
386
 
                if (! node)
387
 
                        exit (1);
388
 
 
389
 
                if (close (fd) < 0) {
390
 
                        nih_error ("%s: %s", filename, strerror (errno));
391
 
                        exit (1);
392
 
                }
393
 
        } else {
394
 
                node = parse_xml (NULL, STDIN_FILENO, "(standard input)");
395
 
                if (! node)
396
 
                        exit (1);
397
 
        }
398
 
 
399
 
        /* Remove the symbol from the default interface */
400
 
        if (default_interface) {
401
 
                int found = FALSE;
402
 
 
403
 
                NIH_LIST_FOREACH (&node->interfaces, iter) {
404
 
                        Interface *interface = (Interface *)iter;
405
 
 
406
 
                        if (! strcmp (interface->name, default_interface)) {
407
 
                                nih_unref (interface->symbol, interface);
408
 
                                interface->symbol = NULL;
409
 
                                found = TRUE;
410
 
                        }
411
 
                }
412
 
 
413
 
                if (! found) {
414
 
                        nih_error ("%s: %s", _("No such interface"),
415
 
                                   default_interface);
416
 
                        exit (1);
417
 
                }
418
 
        }
419
 
 
420
 
        /* Write the output files */
421
 
        source_fd = open (source_path, O_WRONLY | O_CREAT | O_TRUNC, 0666);
422
 
        if (source_fd < 0) {
423
 
                nih_error ("%s: %s", source_path, strerror (errno));
424
 
                exit (1);
425
 
        }
426
 
 
427
 
        header_fd = open (header_path, O_WRONLY | O_CREAT | O_TRUNC, 0666);
428
 
        if (header_fd < 0) {
429
 
                nih_error ("%s: %s", header_path, strerror (errno));
430
 
                exit (1);
431
 
        }
432
 
 
433
 
        if (output (source_path, source_fd, header_path, header_fd,
434
 
                    prefix, node, object) < 0) {
435
 
                NihError *err;
436
 
 
437
 
                err = nih_error_get ();
438
 
                nih_error ("%s", err->message);
439
 
                nih_free (err);
440
 
 
441
 
                exit (1);
442
 
        }
443
 
 
444
 
        if ((fsync (source_fd) < 0)
445
 
            || (close (source_fd) < 0)) {
446
 
                nih_error ("%s: %s", source_path, strerror (errno));
447
 
                exit (1);
448
 
        }
449
 
 
450
 
        if ((fsync (header_fd) < 0)
451
 
            || (close (header_fd) < 0)) {
452
 
                nih_error ("%s: %s", header_path, strerror (errno));
453
 
                exit (1);
454
 
        }
455
 
 
456
 
        return 0;
457
 
}
458
 
#endif