~serge-hallyn/ubuntu/oneiric/libvirt/fix-shutdown

« back to all changes in this revision

Viewing changes to .pc/9018-Make-umlConnectTapDevice-ask-brAddTap-for-a-persiste.patch/src/uml/uml_conf.c

  • Committer: Bazaar Package Importer
  • Author(s): Serge Hallyn
  • Date: 2010-11-02 16:26:51 UTC
  • mfrom: (1.2.7 upstream)
  • Revision ID: james.westby@ubuntu.com-20101102162651-aq8tnbz58mdf01bf
Tags: 0.8.5-0ubuntu1
* New upstream release.
* Removed a slew of patches which have been
  applied upstream since 0.8.3.
  - 9012-apparmor-extra-tests.patch
  - 9013-apparmor-chardev.patch
  - 9015-Add-ubd-to-the-list-of-disk-prefixes.patch
  - 9016-Close-fd-s-of-persistent-tap-devices.patch
  - 9017-Make-sure-all-command-line-arguments-get-passed-to-U.patch
  - 9018-Make-umlConnectTapDevice-ask-brAddTap-for-a-persiste.patch
  - 9019-uml-fix-logic-bug-in-checking-reply-length.patch
  - 9021-Allow-chardev-of-type-file-for-UML-domains.patch
  - 9022-Rename-qemudShrinkDisks-to-virDomainDiskRemove-and-m.patch
  - 9023-Support-virDomainAttachDevice-and-virDomainDetachDev.patch
  - 9024-Explicitly-pass-uml_dir-argument-to-user-mode-linux.patch
  - 9025-Add-nwfilter-support-to-UML-driver.patch
  - 9026-Rebuild-network-filter-for-UML-guests-on-updates.patch
  - 9027-Make-newfilter-xml-transformations-endian-safe.patch
  - 9028-lp628055.patch
* Updated 9002-better_default_uri_virsh.patch to use vshStrdup,
  as now required in that file.  (use of strdup now causes compilation
  to fail)
* Removed 9008-run-as-root-by-default.patch, which has not been
  applied for awhile now, with no ill effects.
* Simple refresh of:
  - 0001-remove-RHism.diff.patch
  - 0003-allow-libvirt-group-to-access-the-socket.patch
  - 0004-fix-Debian-specific-path-to-hvm-loader.patch
  - 0006-patch-qemuMonitorTextGetMigrationStatus-to-intercept.patch
  - 9000-delayed_iff_up_bridge.patch
  - 9001-dont_clobber_existing_bridges.patch
  - 9003-better-default-arch.patch
  - 9004-libvirtd-group-name.patch
  - 9005-increase-unix-socket-timeout.patch
  - 9006-default-config-test-case.patch
  - 9009-autodetect-nc-params.patch
  - 9010-dont-disable-ipv6.patch
  - 9011-move-ebtables-script.patch
  - 9014-skip-nodeinfotest.patch
  - 9020-lp545795.patch
* Create a patch to include stdint.h so lxc_container.h, which
  #includes linux/fs.h, doesn't trip up on undefined uint64_t.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * uml_conf.c: UML driver configuration
3
 
 *
4
 
 * Copyright (C) 2006-2009 Red Hat, Inc.
5
 
 * Copyright (C) 2006 Daniel P. Berrange
6
 
 *
7
 
 * This library is free software; you can redistribute it and/or
8
 
 * modify it under the terms of the GNU Lesser General Public
9
 
 * License as published by the Free Software Foundation; either
10
 
 * version 2.1 of the License, or (at your option) any later version.
11
 
 *
12
 
 * This library is distributed in the hope that it will be useful,
13
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
 
 * Lesser General Public License for more details.
16
 
 *
17
 
 * You should have received a copy of the GNU Lesser General Public
18
 
 * License along with this library; if not, write to the Free Software
19
 
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
20
 
 *
21
 
 * Author: Daniel P. Berrange <berrange@redhat.com>
22
 
 */
23
 
 
24
 
#include <config.h>
25
 
 
26
 
#include <dirent.h>
27
 
#include <string.h>
28
 
#include <limits.h>
29
 
#include <sys/types.h>
30
 
#include <sys/stat.h>
31
 
#include <stdlib.h>
32
 
#include <unistd.h>
33
 
#include <errno.h>
34
 
#include <fcntl.h>
35
 
#include <sys/wait.h>
36
 
#include <arpa/inet.h>
37
 
#include <sys/utsname.h>
38
 
 
39
 
#include "uml_conf.h"
40
 
#include "uuid.h"
41
 
#include "buf.h"
42
 
#include "conf.h"
43
 
#include "util.h"
44
 
#include "memory.h"
45
 
#include "nodeinfo.h"
46
 
#include "verify.h"
47
 
#include "bridge.h"
48
 
#include "logging.h"
49
 
 
50
 
#define VIR_FROM_THIS VIR_FROM_UML
51
 
 
52
 
#define umlLog(level, msg, ...)                                     \
53
 
        virLogMessage(__FILE__, level, 0, msg, __VA_ARGS__)
54
 
 
55
 
virCapsPtr umlCapsInit(void) {
56
 
    struct utsname utsname;
57
 
    virCapsPtr caps;
58
 
    virCapsGuestPtr guest;
59
 
 
60
 
    /* Really, this never fails - look at the man-page. */
61
 
    uname (&utsname);
62
 
 
63
 
    if ((caps = virCapabilitiesNew(utsname.machine,
64
 
                                   0, 0)) == NULL)
65
 
        goto error;
66
 
 
67
 
    /* Some machines have problematic NUMA toplogy causing
68
 
     * unexpected failures. We don't want to break the QEMU
69
 
     * driver in this scenario, so log errors & carry on
70
 
     */
71
 
    if (nodeCapsInitNUMA(caps) < 0) {
72
 
        virCapabilitiesFreeNUMAInfo(caps);
73
 
        VIR_WARN0("Failed to query host NUMA topology, disabling NUMA capabilities");
74
 
    }
75
 
 
76
 
    if (virGetHostUUID(caps->host.host_uuid)) {
77
 
        umlReportError(VIR_ERR_INTERNAL_ERROR,
78
 
                       "%s", _("cannot get the host uuid"));
79
 
        goto error;
80
 
    }
81
 
 
82
 
    if ((guest = virCapabilitiesAddGuest(caps,
83
 
                                         "uml",
84
 
                                         utsname.machine,
85
 
                                         STREQ(utsname.machine, "x86_64") ? 64 : 32,
86
 
                                         NULL,
87
 
                                         NULL,
88
 
                                         0,
89
 
                                         NULL)) == NULL)
90
 
        goto error;
91
 
 
92
 
    if (virCapabilitiesAddGuestDomain(guest,
93
 
                                      "uml",
94
 
                                      NULL,
95
 
                                      NULL,
96
 
                                      0,
97
 
                                      NULL) == NULL)
98
 
        goto error;
99
 
 
100
 
    caps->defaultConsoleTargetType = VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_UML;
101
 
 
102
 
    return caps;
103
 
 
104
 
 error:
105
 
    virCapabilitiesFree(caps);
106
 
    return NULL;
107
 
}
108
 
 
109
 
 
110
 
static int
111
 
umlConnectTapDevice(virDomainNetDefPtr net,
112
 
                    const char *bridge)
113
 
{
114
 
    brControl *brctl = NULL;
115
 
    int tapfd = -1;
116
 
    int template_ifname = 0;
117
 
    int err;
118
 
    unsigned char tapmac[VIR_MAC_BUFLEN];
119
 
 
120
 
    if ((err = brInit(&brctl))) {
121
 
        virReportSystemError(err, "%s",
122
 
                             _("cannot initialize bridge support"));
123
 
        goto error;
124
 
    }
125
 
 
126
 
    if (!net->ifname ||
127
 
        STRPREFIX(net->ifname, "vnet") ||
128
 
        strchr(net->ifname, '%')) {
129
 
        VIR_FREE(net->ifname);
130
 
        if (!(net->ifname = strdup("vnet%d")))
131
 
            goto no_memory;
132
 
        /* avoid exposing vnet%d in dumpxml or error outputs */
133
 
        template_ifname = 1;
134
 
    }
135
 
 
136
 
    memcpy(tapmac, net->mac, VIR_MAC_BUFLEN);
137
 
    tapmac[0] = 0xFE; /* Discourage bridge from using TAP dev MAC */
138
 
    if ((err = brAddTap(brctl,
139
 
                        bridge,
140
 
                        &net->ifname,
141
 
                        tapmac,
142
 
                        0,
143
 
                        &tapfd))) {
144
 
        if (errno == ENOTSUP) {
145
 
            /* In this particular case, give a better diagnostic. */
146
 
            umlReportError(VIR_ERR_INTERNAL_ERROR,
147
 
                           _("Failed to add tap interface to bridge. "
148
 
                             "%s is not a bridge device"), bridge);
149
 
        } else if (template_ifname) {
150
 
            virReportSystemError(err,
151
 
                                 _("Failed to add tap interface to bridge '%s'"),
152
 
                                 bridge);
153
 
        } else {
154
 
            virReportSystemError(err,
155
 
                                 _("Failed to add tap interface '%s' to bridge '%s'"),
156
 
                                 net->ifname, bridge);
157
 
        }
158
 
        if (template_ifname)
159
 
            VIR_FREE(net->ifname);
160
 
        goto error;
161
 
    }
162
 
    close(tapfd);
163
 
 
164
 
    brShutdown(brctl);
165
 
 
166
 
    return 0;
167
 
 
168
 
no_memory:
169
 
    virReportOOMError();
170
 
error:
171
 
    brShutdown(brctl);
172
 
    return -1;
173
 
}
174
 
 
175
 
static char *
176
 
umlBuildCommandLineNet(virConnectPtr conn,
177
 
                       virDomainNetDefPtr def,
178
 
                       int idx)
179
 
{
180
 
    virBuffer buf = VIR_BUFFER_INITIALIZER;
181
 
 
182
 
    /* General format:  ethNN=type,options */
183
 
 
184
 
    virBufferVSprintf(&buf, "eth%d=", idx);
185
 
 
186
 
    switch (def->type) {
187
 
    case VIR_DOMAIN_NET_TYPE_USER:
188
 
        /* ethNNN=slirp,macaddr */
189
 
        virBufferAddLit(&buf, "slirp");
190
 
        break;
191
 
 
192
 
    case VIR_DOMAIN_NET_TYPE_ETHERNET:
193
 
        /* ethNNN=tuntap,tapname,macaddr,gateway */
194
 
        virBufferAddLit(&buf, "tuntap");
195
 
        if (def->data.ethernet.ipaddr) {
196
 
            umlReportError(VIR_ERR_INTERNAL_ERROR, "%s",
197
 
                           _("IP address not supported for ethernet inteface"));
198
 
            goto error;
199
 
        }
200
 
        if (def->data.ethernet.script) {
201
 
            umlReportError(VIR_ERR_INTERNAL_ERROR, "%s",
202
 
                           _("script execution not supported for ethernet inteface"));
203
 
            goto error;
204
 
        }
205
 
        break;
206
 
 
207
 
    case VIR_DOMAIN_NET_TYPE_SERVER:
208
 
        umlReportError(VIR_ERR_INTERNAL_ERROR, "%s",
209
 
                       _("TCP server networking type not supported"));
210
 
        goto error;
211
 
 
212
 
    case VIR_DOMAIN_NET_TYPE_CLIENT:
213
 
        umlReportError(VIR_ERR_INTERNAL_ERROR, "%s",
214
 
                       _("TCP client networking type not supported"));
215
 
        goto error;
216
 
 
217
 
    case VIR_DOMAIN_NET_TYPE_MCAST:
218
 
        /* ethNNN=tuntap,macaddr,ipaddr,port */
219
 
        virBufferAddLit(&buf, "mcast");
220
 
        break;
221
 
 
222
 
    case VIR_DOMAIN_NET_TYPE_NETWORK:
223
 
    {
224
 
        char *bridge;
225
 
        virNetworkPtr network = virNetworkLookupByName(conn,
226
 
                                                       def->data.network.name);
227
 
        if (!network) {
228
 
            umlReportError(VIR_ERR_INTERNAL_ERROR,
229
 
                           _("Network '%s' not found"),
230
 
                           def->data.network.name);
231
 
            goto error;
232
 
        }
233
 
        bridge = virNetworkGetBridgeName(network);
234
 
        virNetworkFree(network);
235
 
        if (bridge == NULL) {
236
 
            goto error;
237
 
        }
238
 
 
239
 
        if (umlConnectTapDevice(def, bridge) < 0) {
240
 
            VIR_FREE(bridge);
241
 
            goto error;
242
 
        }
243
 
 
244
 
        /* ethNNN=tuntap,tapname,macaddr,gateway */
245
 
        virBufferVSprintf(&buf, "tuntap,%s", def->ifname);
246
 
        break;
247
 
    }
248
 
 
249
 
    case VIR_DOMAIN_NET_TYPE_BRIDGE:
250
 
        if (umlConnectTapDevice(def, def->data.bridge.brname) < 0)
251
 
            goto error;
252
 
 
253
 
        /* ethNNN=tuntap,tapname,macaddr,gateway */
254
 
        virBufferVSprintf(&buf, "tuntap,%s", def->ifname);
255
 
        break;
256
 
 
257
 
    case VIR_DOMAIN_NET_TYPE_INTERNAL:
258
 
        umlReportError(VIR_ERR_INTERNAL_ERROR, "%s",
259
 
                       _("internal networking type not supported"));
260
 
        goto error;
261
 
 
262
 
    case VIR_DOMAIN_NET_TYPE_DIRECT:
263
 
        umlReportError(VIR_ERR_INTERNAL_ERROR, "%s",
264
 
                       _("direct networking type not supported"));
265
 
        goto error;
266
 
 
267
 
    case VIR_DOMAIN_NET_TYPE_LAST:
268
 
        break;
269
 
    }
270
 
 
271
 
    virBufferVSprintf(&buf, ",%02x:%02x:%02x:%02x:%02x:%02x",
272
 
                      def->mac[0], def->mac[1], def->mac[2],
273
 
                      def->mac[3], def->mac[4], def->mac[5]);
274
 
 
275
 
    if (def->type == VIR_DOMAIN_NET_TYPE_MCAST) {
276
 
        virBufferVSprintf(&buf, ",%s,%d",
277
 
                          def->data.socket.address,
278
 
                          def->data.socket.port);
279
 
    }
280
 
 
281
 
    if (virBufferError(&buf)) {
282
 
        virReportOOMError();
283
 
        return NULL;
284
 
    }
285
 
 
286
 
    return virBufferContentAndReset(&buf);
287
 
 
288
 
error:
289
 
    virBufferFreeAndReset(&buf);
290
 
    return NULL;
291
 
}
292
 
 
293
 
static char *
294
 
umlBuildCommandLineChr(virDomainChrDefPtr def,
295
 
                       const char *dev)
296
 
{
297
 
    char *ret = NULL;
298
 
 
299
 
    switch (def->type) {
300
 
    case VIR_DOMAIN_CHR_TYPE_NULL:
301
 
        if (virAsprintf(&ret, "%s%d=null", dev, def->target.port) < 0) {
302
 
            virReportOOMError();
303
 
            return NULL;
304
 
        }
305
 
        break;
306
 
 
307
 
    case VIR_DOMAIN_CHR_TYPE_PTY:
308
 
        if (virAsprintf(&ret, "%s%d=pts", dev, def->target.port) < 0) {
309
 
            virReportOOMError();
310
 
            return NULL;
311
 
        }
312
 
        break;
313
 
 
314
 
    case VIR_DOMAIN_CHR_TYPE_DEV:
315
 
        if (virAsprintf(&ret, "%s%d=tty:%s", dev, def->target.port,
316
 
                        def->data.file.path) < 0) {
317
 
            virReportOOMError();
318
 
            return NULL;
319
 
        }
320
 
        break;
321
 
 
322
 
    case VIR_DOMAIN_CHR_TYPE_STDIO:
323
 
        if (virAsprintf(&ret, "%s%d=fd:0,fd:1", dev, def->target.port) < 0) {
324
 
            virReportOOMError();
325
 
            return NULL;
326
 
        }
327
 
        break;
328
 
 
329
 
    case VIR_DOMAIN_CHR_TYPE_TCP:
330
 
        if (def->data.tcp.listen != 1) {
331
 
            umlReportError(VIR_ERR_INTERNAL_ERROR, "%s",
332
 
                           _("only TCP listen is supported for chr device"));
333
 
            return NULL;
334
 
        }
335
 
 
336
 
        if (virAsprintf(&ret, "%s%d=port:%s", dev, def->target.port,
337
 
                        def->data.tcp.service) < 0) {
338
 
            virReportOOMError();
339
 
            return NULL;
340
 
        }
341
 
        break;
342
 
 
343
 
    case VIR_DOMAIN_CHR_TYPE_FILE:
344
 
    case VIR_DOMAIN_CHR_TYPE_PIPE:
345
 
        /* XXX could open the file/pipe & just pass the FDs */
346
 
 
347
 
    case VIR_DOMAIN_CHR_TYPE_VC:
348
 
    case VIR_DOMAIN_CHR_TYPE_UDP:
349
 
    case VIR_DOMAIN_CHR_TYPE_UNIX:
350
 
    default:
351
 
        umlReportError(VIR_ERR_INTERNAL_ERROR,
352
 
                       _("unsupported chr device type %d"), def->type);
353
 
        break;
354
 
    }
355
 
 
356
 
    return ret;
357
 
}
358
 
 
359
 
/*
360
 
 * Null-terminate the current argument and return a pointer to the next.
361
 
 * This should follow the same rules as the Linux kernel: arguments are
362
 
 * separated by spaces; arguments can be quoted with double quotes; double
363
 
 * quotes can't be escaped.
364
 
 */
365
 
static char *umlNextArg(char *args)
366
 
{
367
 
    int in_quote = 0;
368
 
 
369
 
    for (; *args; args++) {
370
 
        if (*args == ' ' && !in_quote) {
371
 
            *args++ = '\0';
372
 
            break;
373
 
        }
374
 
        if (*args == '"')
375
 
            in_quote = !in_quote;
376
 
    }
377
 
 
378
 
    while (*args == ' ')
379
 
        args++;
380
 
 
381
 
    return args;
382
 
}
383
 
 
384
 
/*
385
 
 * Constructs a argv suitable for launching uml with config defined
386
 
 * for a given virtual machine.
387
 
 */
388
 
int umlBuildCommandLine(virConnectPtr conn,
389
 
                        struct uml_driver *driver ATTRIBUTE_UNUSED,
390
 
                        virDomainObjPtr vm,
391
 
                        const char ***retargv,
392
 
                        const char ***retenv)
393
 
{
394
 
    int i, j;
395
 
    char memory[50];
396
 
    struct utsname ut;
397
 
    int qargc = 0, qarga = 0;
398
 
    const char **qargv = NULL;
399
 
    int qenvc = 0, qenva = 0;
400
 
    const char **qenv = NULL;
401
 
    char *cmdline = NULL;
402
 
 
403
 
    uname(&ut);
404
 
 
405
 
#define ADD_ARG_SPACE                                                   \
406
 
    do {                                                                \
407
 
        if (qargc == qarga) {                                           \
408
 
            qarga += 10;                                                \
409
 
            if (VIR_REALLOC_N(qargv, qarga) < 0)                        \
410
 
                goto no_memory;                                         \
411
 
        }                                                               \
412
 
    } while (0)
413
 
 
414
 
#define ADD_ARG(thisarg)                                                \
415
 
    do {                                                                \
416
 
        ADD_ARG_SPACE;                                                  \
417
 
        qargv[qargc++] = thisarg;                                       \
418
 
    } while (0)
419
 
 
420
 
#define ADD_ARG_LIT(thisarg)                                            \
421
 
    do {                                                                \
422
 
        ADD_ARG_SPACE;                                                  \
423
 
        if ((qargv[qargc++] = strdup(thisarg)) == NULL)                 \
424
 
            goto no_memory;                                             \
425
 
    } while (0)
426
 
 
427
 
#define ADD_ARG_PAIR(key,val)                                           \
428
 
    do {                                                                \
429
 
        char *arg;                                                      \
430
 
        ADD_ARG_SPACE;                                                  \
431
 
        if (virAsprintf(&arg, "%s=%s", key, val) < 0)                   \
432
 
            goto no_memory;                                             \
433
 
        qargv[qargc++] = arg;                                           \
434
 
    } while (0)
435
 
 
436
 
 
437
 
#define ADD_ENV_SPACE                                                   \
438
 
    do {                                                                \
439
 
        if (qenvc == qenva) {                                           \
440
 
            qenva += 10;                                                \
441
 
            if (VIR_REALLOC_N(qenv, qenva) < 0)                         \
442
 
                goto no_memory;                                         \
443
 
        }                                                               \
444
 
    } while (0)
445
 
 
446
 
#define ADD_ENV(thisarg)                                                \
447
 
    do {                                                                \
448
 
        ADD_ENV_SPACE;                                                  \
449
 
        qenv[qenvc++] = thisarg;                                        \
450
 
    } while (0)
451
 
 
452
 
#define ADD_ENV_LIT(thisarg)                                            \
453
 
    do {                                                                \
454
 
        ADD_ENV_SPACE;                                                  \
455
 
        if ((qenv[qenvc++] = strdup(thisarg)) == NULL)                  \
456
 
            goto no_memory;                                             \
457
 
    } while (0)
458
 
 
459
 
#define ADD_ENV_COPY(envname)                                           \
460
 
    do {                                                                \
461
 
        char *val = getenv(envname);                                    \
462
 
        char *envval;                                                   \
463
 
        ADD_ENV_SPACE;                                                  \
464
 
        if (val != NULL) {                                              \
465
 
            if (virAsprintf(&envval, "%s=%s", envname, val) < 0)        \
466
 
                goto no_memory;                                         \
467
 
            qenv[qenvc++] = envval;                                     \
468
 
        }                                                               \
469
 
    } while (0)
470
 
 
471
 
    snprintf(memory, sizeof(memory), "%luK", vm->def->memory);
472
 
 
473
 
    ADD_ENV_LIT("LC_ALL=C");
474
 
 
475
 
    ADD_ENV_COPY("LD_PRELOAD");
476
 
    ADD_ENV_COPY("LD_LIBRARY_PATH");
477
 
    ADD_ENV_COPY("PATH");
478
 
    ADD_ENV_COPY("HOME");
479
 
    ADD_ENV_COPY("USER");
480
 
    ADD_ENV_COPY("LOGNAME");
481
 
    ADD_ENV_COPY("TMPDIR");
482
 
 
483
 
    ADD_ARG_LIT(vm->def->os.kernel);
484
 
    //ADD_ARG_PAIR("con0", "fd:0,fd:1");
485
 
    ADD_ARG_PAIR("mem", memory);
486
 
    ADD_ARG_PAIR("umid", vm->def->name);
487
 
 
488
 
    if (vm->def->os.root)
489
 
        ADD_ARG_PAIR("root", vm->def->os.root);
490
 
 
491
 
    for (i = 0 ; i < vm->def->ndisks ; i++) {
492
 
        virDomainDiskDefPtr disk = vm->def->disks[i];
493
 
 
494
 
        if (!STRPREFIX(disk->dst, "ubd")) {
495
 
            umlReportError(VIR_ERR_INTERNAL_ERROR,
496
 
                           _("unsupported disk type '%s'"), disk->dst);
497
 
            goto error;
498
 
        }
499
 
 
500
 
        ADD_ARG_PAIR(disk->dst, disk->src);
501
 
    }
502
 
 
503
 
    for (i = 0 ; i < vm->def->nnets ; i++) {
504
 
        char *ret = umlBuildCommandLineNet(conn, vm->def->nets[i], i);
505
 
        if (!ret)
506
 
            goto error;
507
 
        ADD_ARG(ret);
508
 
    }
509
 
 
510
 
    for (i = 0 ; i < UML_MAX_CHAR_DEVICE ; i++) {
511
 
        char *ret = NULL;
512
 
        if (i == 0 && vm->def->console)
513
 
            ret = umlBuildCommandLineChr(vm->def->console, "con");
514
 
        if (!ret)
515
 
            if (virAsprintf(&ret, "con%d=none", i) < 0)
516
 
                goto no_memory;
517
 
        ADD_ARG(ret);
518
 
    }
519
 
 
520
 
    for (i = 0 ; i < UML_MAX_CHAR_DEVICE ; i++) {
521
 
        virDomainChrDefPtr chr = NULL;
522
 
        char *ret = NULL;
523
 
        for (j = 0 ; j < vm->def->nserials ; j++)
524
 
            if (vm->def->serials[j]->target.port == i)
525
 
                chr = vm->def->serials[j];
526
 
        if (chr)
527
 
            ret = umlBuildCommandLineChr(chr, "ssl");
528
 
        if (!ret)
529
 
            if (virAsprintf(&ret, "ssl%d=none", i) < 0)
530
 
                goto no_memory;
531
 
        ADD_ARG(ret);
532
 
    }
533
 
 
534
 
    if (vm->def->os.cmdline) {
535
 
        char *args, *next_arg;
536
 
        if ((cmdline = strdup(vm->def->os.cmdline)) == NULL)
537
 
            goto no_memory;
538
 
 
539
 
        args = cmdline;
540
 
        while (*args == ' ')
541
 
            args++;
542
 
 
543
 
        while (*args) {
544
 
            next_arg = umlNextArg(args);
545
 
            ADD_ARG_LIT(args);
546
 
            args = next_arg;
547
 
        }
548
 
    }
549
 
 
550
 
    ADD_ARG(NULL);
551
 
    ADD_ENV(NULL);
552
 
 
553
 
    *retargv = qargv;
554
 
    *retenv = qenv;
555
 
    return 0;
556
 
 
557
 
 no_memory:
558
 
    virReportOOMError();
559
 
 error:
560
 
 
561
 
    if (qargv) {
562
 
        for (i = 0 ; i < qargc ; i++)
563
 
            VIR_FREE((qargv)[i]);
564
 
        VIR_FREE(qargv);
565
 
    }
566
 
    if (qenv) {
567
 
        for (i = 0 ; i < qenvc ; i++)
568
 
            VIR_FREE((qenv)[i]);
569
 
        VIR_FREE(qenv);
570
 
    }
571
 
    VIR_FREE(cmdline);
572
 
    return -1;
573
 
 
574
 
#undef ADD_ARG
575
 
#undef ADD_ARG_LIT
576
 
#undef ADD_ARG_SPACE
577
 
#undef ADD_USBDISK
578
 
#undef ADD_ENV
579
 
#undef ADD_ENV_COPY
580
 
#undef ADD_ENV_LIT
581
 
#undef ADD_ENV_SPACE
582
 
}