/*
* kickstart.c - kickstart file handling
*
* Copyright (C) 1999, 2000, 2001, 2002, 2003 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
* Author(s): Erik Troan
* Matt Wilson
* Michael Fulbright
* Jeremy Katz
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "loader.h"
#include "loadermisc.h"
#include "lang.h"
#include "kickstart.h"
#include "modules.h"
#include "kbd.h"
#include "driverdisk.h"
#include "net.h"
#include "method.h"
#include "nfsinstall.h"
#include "urlinstall.h"
#include "cdinstall.h"
#include "hdinstall.h"
#include "../pyanaconda/isys/eddsupport.h"
#include "../pyanaconda/isys/imount.h"
#include "../pyanaconda/isys/isys.h"
#include "../pyanaconda/isys/log.h"
/* Too bad, but we need constants visible everywhere. */
static PyObject *constantsMod;
/* boot flags */
extern uint64_t flags;
static void setDisplayMode(struct loaderData_s * loaderData, PyObject *handler);
static void setSELinux(struct loaderData_s * loaderData, PyObject *handler);
static void setShutdown(struct loaderData_s * loaderData, PyObject *handler);
static void setMediaCheck(struct loaderData_s * loaderData, PyObject *handler);
static void setUpdates(struct loaderData_s * loaderData, PyObject *handler);
static void setVnc(struct loaderData_s * loaderData, PyObject *handler);
static void useKickstartDD(struct loaderData_s * loaderData, PyObject *handler);
static void setKickstartKeyboard(struct loaderData_s * loaderData, PyObject *handler);
static void setKickstartLanguage(struct loaderData_s * loaderData, PyObject *handler);
static void setKickstartNetwork(struct loaderData_s * loaderData, PyObject *handler);
static void setKickstartCD(struct loaderData_s * loaderData, PyObject *handler);
static void setKickstartHD(struct loaderData_s * loaderData, PyObject *handler);
static void setKickstartNfs(struct loaderData_s * loaderData, PyObject *handler);
static void setKickstartUrl(struct loaderData_s * loaderData, PyObject *handler);
static void loadKickstartModule(struct loaderData_s * loaderData, PyObject *handler);
typedef void (*commandFunc_t)(struct loaderData_s *loaderData, PyObject *handler);
commandFunc_t ksTable[] = {
&loadKickstartModule,
&setDisplayMode,
&setKickstartCD,
&setKickstartHD,
&setKickstartKeyboard,
&setKickstartLanguage,
&setKickstartNetwork,
&setKickstartNfs,
&setKickstartUrl,
&setMediaCheck,
&setSELinux,
&setShutdown,
&setUpdates,
&setVnc,
&useKickstartDD,
NULL
};
/* INTERNAL PYTHON INTERFACE FUNCTIONS */
static PyObject *getObject(PyObject *module, const char *name, unsigned int isCallable) {
PyObject *obj = NULL;
obj = PyObject_GetAttrString(module, name);
if (!obj)
return NULL;
if (isCallable && !PyCallable_Check(obj)) {
Py_XDECREF(obj);
return NULL;
}
return obj;
}
static PyObject *import(const char *moduleName) {
PyObject *module = NULL;
module = PyImport_ImportModule(moduleName);
return module;
}
static PyObject *makeHandler(PyObject *module) {
PyObject *func, *handler;
func = getObject(module, "makeVersion", 1);
if (!func)
return NULL;
handler = PyObject_CallObject(func, NULL);
if (!handler) {
Py_DECREF(func);
return NULL;
}
Py_DECREF(func);
return handler;
}
static PyObject *makeParser(PyObject *parserClass, PyObject *handler) {
PyObject *parser = NULL, *args, *kwargs;
args = PyTuple_New(1);
PyTuple_SetItem(args, 0, handler);
kwargs = PyDict_New();
Py_INCREF(Py_True);
PyDict_SetItemString(kwargs, "followIncludes", Py_True);
Py_INCREF(Py_True);
PyDict_SetItemString(kwargs, "errorsAreFatal", Py_True);
Py_INCREF(Py_False);
PyDict_SetItemString(kwargs, "missingIncludeIsFatal", Py_False);
parser = PyObject_Call(parserClass, args, kwargs);
Py_DECREF(kwargs);
Py_DECREF(args);
return parser;
}
static void handleException() {
PyObject *ptype, *pvalue, *ptraceback;
if (!PyErr_Occurred())
return;
PyErr_Fetch(&ptype, &pvalue, &ptraceback);
startNewt();
newtWinMessage(_("Kickstart Error"), _("OK"),
PyString_AsString(PyObject_Str(pvalue)));
Py_XDECREF(ptype);
Py_XDECREF(pvalue);
Py_XDECREF(ptraceback);
}
/* Returns the handler.. object if it exists, or NULL on error. */
static PyObject *getattr(PyObject *handler, const char *command, const char *attr) {
PyObject *commandObj = NULL, *attrObj = NULL;
commandObj = PyObject_GetAttrString(handler, command);
if (!commandObj)
goto cleanup;
attrObj = PyObject_GetAttrString(commandObj, attr);
if (!attrObj)
goto cleanup;
cleanup:
Py_XDECREF(commandObj);
return attrObj;
}
static PyObject *getDataList(PyObject *handler, const char *command) {
PyObject *attrObj = getattr(handler, command, "dataList");
PyObject *retval = NULL;
if (!attrObj || !PyCallable_Check(attrObj))
goto cleanup;
retval = PyObject_CallObject(attrObj, NULL);
cleanup:
Py_XDECREF(attrObj);
return retval;
}
/* Perform the same tasks as pykickstart.parser.preprocessKickstart. Currently
* this is just fetching and expanding %ksappend lines.
*/
static PyObject *preprocessKickstart(PyObject *module, const char *inputFile) {
PyObject *output = NULL, *func;
func = getObject(module, "preprocessKickstart", 1);
if (!func)
return NULL;
output = PyObject_CallFunctionObjArgs(func, PyString_FromString(inputFile), NULL);
if (!output) {
handleException();
return NULL;
}
return output;
}
/* Process a kickstart file given by the filename f, as a PyObject. This sets
* attributes on the parser object as a side effect, returning that object or
* NULL on exception.
*/
static PyObject *readKickstart(PyObject *parser, PyObject *f) {
PyObject *retval;
retval = PyObject_CallMethodObjArgs(parser, PyString_FromString("readKickstart"), f, NULL);
if (!retval) {
handleException();
return NULL;
}
return retval;
}
/* PYTHON HELPERS */
static unsigned int isNotEmpty(PyObject *obj) {
return obj && PyString_Check(obj) && strcmp("", PyString_AsString(obj));
}
static unsigned int objIsStr(PyObject *obj, const char *str) {
return obj && PyString_Check(obj) && !strcmp(str, PyString_AsString(obj));
}
static unsigned int isTrue(PyObject *obj) {
return obj && PyBool_Check(obj) && obj == Py_True;
}
int kickstartFromRemovable(char *kssrc) {
struct device ** devices;
char *p, *kspath;
int i, rc;
logMessage(INFO, "doing kickstart from removable media");
devices = getDevices(DEVICE_DISK);
/* usb can take some time to settle, even with the various hacks we
* have in place. some systems use portable USB CD-ROM drives, try to
* make sure there really isn't one before bailing. */
for (i = 0; !devices && i < 10; ++i) {
logMessage(INFO, "sleeping to wait for a USB disk");
sleep(2);
devices = getDevices(DEVICE_DISK);
}
if (!devices) {
logMessage(ERROR, "no disks");
return 1;
}
for (i = 0; devices[i]; i++) {
if (devices[i]->priv.removable == 1) {
logMessage(INFO, "first removable media is %s", devices[i]->device);
break;
}
}
if (!devices[i] || (devices[i]->priv.removable == 0)) {
logMessage(ERROR, "no removable devices");
return 1;
}
/* format is floppy:[/path/to/ks.cfg] */
kspath = "";
p = strchr(kssrc, ':');
if (p)
kspath = p + 1;
if (!p || strlen(kspath) < 1)
kspath = "/ks.cfg";
if ((rc=getKickstartFromBlockDevice(devices[i]->device, kspath))) {
if (rc == 3) {
startNewt();
newtWinMessage(_("Error"), _("OK"),
_("Cannot find ks.cfg on removable media."));
}
return 1;
}
return 0;
}
/* given a device name (w/o '/dev' on it), try to get ks file */
/* Error codes:
1 - could not create device node
2 - could not mount device as ext2, vfat, or iso9660
3 - kickstart file named path not there
*/
int getKickstartFromBlockDevice(char *device, char *path) {
return getFileFromBlockDevice(device, path, "/tmp/ks.cfg");
}
void loadKickstartModule(struct loaderData_s * loaderData, PyObject *handler) {
Py_ssize_t i;
PyObject *list = getDataList(handler, "device");
if (!list)
return;
for (i = 0; i < PyList_Size(list); i++) {
PyObject *ele = PyList_GetItem(list, i);
PyObject *moduleName, *moduleOpts;
if (!ele)
continue;
moduleName = getObject(ele, "moduleName", 0);
moduleOpts = getObject(ele, "moduleOpts", 0);
if (isNotEmpty(moduleName)) {
if (isNotEmpty(moduleOpts)) {
gchar **args = g_strsplit(PyString_AsString(moduleOpts), " ", 0);
mlLoadModule(PyString_AsString(moduleName), args);
g_strfreev(args);
} else
mlLoadModule(PyString_AsString(moduleName), NULL);
}
Py_XDECREF(moduleName);
Py_XDECREF(moduleOpts);
}
Py_XDECREF(list);
}
static char *newKickstartLocation(const char *origLocation) {
const char *location;
char *retval = NULL;
newtComponent f, okay, cancel, answer, locationEntry;
newtGrid grid, buttons;
startNewt();
locationEntry = newtEntry(-1, -1, NULL, 60, &location, NEWT_FLAG_SCROLL);
newtEntrySet(locationEntry, origLocation, 1);
/* button bar at the bottom of the window */
buttons = newtButtonBar(_("OK"), &okay, _("Cancel"), &cancel, NULL);
grid = newtCreateGrid(1, 3);
newtGridSetField(grid, 0, 0, NEWT_GRID_COMPONENT,
newtTextboxReflowed(-1, -1, _("Unable to download the kickstart file. Please modify the kickstart parameter below or press Cancel to proceed as an interactive installation."), 60, 0, 0, 0),
0, 0, 0, 0, NEWT_ANCHOR_LEFT, 0);
newtGridSetField(grid, 0, 1, NEWT_GRID_COMPONENT, locationEntry,
0, 1, 0, 0, NEWT_ANCHOR_LEFT, 0);
newtGridSetField(grid, 0, 2, NEWT_GRID_SUBGRID, buttons,
0, 1, 0, 0, 0, NEWT_GRID_FLAG_GROWX);
f = newtForm(NULL, NULL, 0);
newtGridAddComponentsToForm(grid, f, 1);
newtGridWrappedWindow(grid, _("Error downloading kickstart file"));
newtGridFree(grid, 1);
/* run the form */
answer = newtRunForm(f);
if (answer != cancel)
retval = strdup(location);
newtFormDestroy(f);
newtPopWindow();
return retval;
}
int isKickstartFileRemote(char *ksFile) {
char *location = NULL;
if (ksFile == NULL) {
return 0;
}
if (!strcmp(ksFile, "ks")) {
return 1;
} else if (!strncmp(ksFile, "ks=", 3)) {
location = ksFile + 3;
}
if (!strncmp(location, "http", 4) ||
!strncmp(location, "ftp://", 6) ||
!strncmp(location, "nfs:", 4)) {
return 1;
} else {
return 0;
}
}
void getKickstartFile(struct loaderData_s *loaderData) {
char *c;
int rc = 1;
/* Chop off the parameter name, if given. */
if (!strncmp(loaderData->ksFile, "ks=", 3))
c = loaderData->ksFile+3;
else
c = loaderData->ksFile;
while (rc != 0) {
if (!strncmp(c, "ks", 2)) {
rc = kickstartFromNfs(NULL, loaderData);
loaderData->ksFile = strdup("/tmp/ks.cfg");
} else if (!strncmp(c, "http", 4) || !strncmp(c, "ftp://", 6)) {
rc = kickstartFromUrl(c, loaderData);
loaderData->ksFile = strdup("/tmp/ks.cfg");
} else if (!strncmp(c, "nfs:", 4)) {
rc = kickstartFromNfs(c+4, loaderData);
loaderData->ksFile = strdup("/tmp/ks.cfg");
} else if (!strncmp(c, "floppy", 6)) {
rc = kickstartFromRemovable(c);
loaderData->ksFile = strdup("/tmp/ks.cfg");
} else if (!strncmp(c, "hd:", 3)) {
rc = kickstartFromHD(c);
loaderData->ksFile = strdup("/tmp/ks.cfg");
} else if (!strncmp(c, "bd:", 3)) {
rc = kickstartFromBD(c);
loaderData->ksFile = strdup("/tmp/ks.cfg");
} else if (!strncmp(c, "cdrom", 5)) {
rc = kickstartFromCD(c);
loaderData->ksFile = strdup("/tmp/ks.cfg");
} else if (!strncmp(c, "file:", 5)) {
loaderData->ksFile = c+5;
break;
}
if (rc != 0) {
char *newLocation;
if (!strcmp(c, "ks"))
newLocation = newKickstartLocation("");
else
newLocation = newKickstartLocation(c);
if (loaderData->ksFile != NULL)
free(loaderData->ksFile);
if (newLocation != NULL) {
loaderData->ksFile = strdup(newLocation);
free(newLocation);
return getKickstartFile(loaderData);
}
else
return;
}
}
flags |= LOADER_FLAGS_KICKSTART;
return;
}
static void setVnc(struct loaderData_s * loaderData, PyObject *handler) {
PyObject *vncEnabled = getattr(handler, "vnc", "enabled");
if (isTrue(vncEnabled)) {
logMessage(INFO, "kickstart forcing graphical mode over vnc");
flags |= LOADER_FLAGS_GRAPHICAL | LOADER_FLAGS_EARLY_NETWORKING;
}
Py_XDECREF(vncEnabled);
}
static void setUpdates(struct loaderData_s * loaderData, PyObject *handler) {
PyObject *url = getattr(handler, "updates", "url");
if (isNotEmpty(url)) {
if (objIsStr(url, "floppy"))
flags |= LOADER_FLAGS_UPDATES;
else
loaderData->updatessrc = strdup(PyString_AsString(url));
}
Py_XDECREF(url);
}
static void setDisplayMode(struct loaderData_s * loaderData, PyObject *handler) {
PyObject *textObj = getObject(constantsMod, "DISPLAY_MODE_TEXT", 0);
PyObject *cmdlineObj = getObject(constantsMod, "DISPLAY_MODE_CMDLINE", 0);
PyObject *settingObj = getattr(handler, "displaymode", "displayMode");
if (!settingObj)
goto cleanup;
if (settingObj == textObj) {
logMessage(INFO, "kickstart forcing text mode");
flags |= LOADER_FLAGS_TEXT;
} else if (settingObj == cmdlineObj) {
logMessage(INFO, "kickstart forcing cmdline mode");
flags |= LOADER_FLAGS_CMDLINE;
} else {
logMessage(INFO, "kickstart forcing graphical mode");
flags |= LOADER_FLAGS_GRAPHICAL;
}
cleanup:
Py_XDECREF(textObj);
Py_XDECREF(cmdlineObj);
Py_XDECREF(settingObj);
}
static void setSELinux(struct loaderData_s * loaderData, PyObject *handler) {
PyObject *disabledObj = getObject(constantsMod, "SELINUX_DISABLED", 0);
PyObject *settingObj = getattr(handler, "selinux", "selinux");
if (settingObj && settingObj != disabledObj)
flags |= LOADER_FLAGS_SELINUX;
Py_XDECREF(disabledObj);
Py_XDECREF(settingObj);
}
static void setShutdown(struct loaderData_s * loaderData, PyObject *handler) {
PyObject *shutdownObj = getObject(constantsMod, "KS_SHUTDOWN", 0);
PyObject *settingObj = getattr(handler, "reboot", "action");
if (!settingObj)
goto cleanup;
if (FL_NOKILL(flags))
flags |= LOADER_FLAGS_HALT;
else {
if (settingObj == shutdownObj)
flags |= LOADER_FLAGS_POWEROFF;
else
flags |= LOADER_FLAGS_HALT;
}
cleanup:
Py_XDECREF(shutdownObj);
Py_XDECREF(settingObj);
}
static void setMediaCheck(struct loaderData_s * loaderData, PyObject *handler) {
PyObject *mediaCheckEnabled = getattr(handler, "mediacheck", "mediacheck");
if (isTrue(mediaCheckEnabled))
flags |= LOADER_FLAGS_MEDIACHECK;
Py_XDECREF(mediaCheckEnabled);
}
static void useKickstartDD(struct loaderData_s * loaderData, PyObject *handler) {
Py_ssize_t i;
PyObject *list = getDataList(handler, "driverdisk");
if (!list)
return;
for (i = 0; i < PyList_Size(list); i++) {
PyObject *ele = PyList_GetItem(list, i);
PyObject *attr;
if (!ele)
continue;
attr = getObject(ele, "source", 0);
if (isNotEmpty(attr)) {
getDDFromSource(loaderData, PyString_AsString(attr), NULL);
goto cleanup;
}
Py_XDECREF(attr);
attr = getObject(ele, "partition", 0);
if (isNotEmpty(attr)) {
getDDFromDev(loaderData, PyString_AsString(attr), NULL);
goto cleanup;
}
Py_XDECREF(attr);
attr = getObject(ele, "biospart", 0);
if (isNotEmpty(attr)) {
char *dev = strdup(PyString_AsString(attr));
char *biospart = NULL, *p = NULL;
p = strchr(dev,'p');
if (!p){
logMessage(ERROR, "Bad argument for biospart");
goto cleanup;
}
*p = '\0';
biospart = getBiosDisk(dev);
if (biospart == NULL) {
logMessage(ERROR, "Unable to locate BIOS dev %s",dev);
goto cleanup;
}
free(dev);
dev = malloc(strlen(biospart) + strlen(p + 1) + 2);
sprintf(dev, "%s%s", biospart, p + 1);
getDDFromDev(loaderData, dev, NULL);
}
cleanup:
Py_XDECREF(attr);
}
Py_XDECREF(list);
}
static void setKickstartKeyboard(struct loaderData_s * loaderData, PyObject *handler) {
PyObject *kbdObj = getattr(handler, "keyboard", "keyboard");
if (isNotEmpty(kbdObj)) {
loaderData->kbd = strdup(PyString_AsString(kbdObj));
loaderData->kbd_set = 1;
}
Py_XDECREF(kbdObj);
}
static void setKickstartLanguage(struct loaderData_s * loaderData, PyObject *handler) {
PyObject *langObj = getattr(handler, "lang", "lang");
if (isNotEmpty(langObj)) {
loaderData->lang = strdup(PyString_AsString(langObj));
loaderData->lang_set = 1;
}
Py_XDECREF(langObj);
}
static void _setNetworkString(PyObject *obj, const char *name, char **dest, int *sentinel) {
PyObject *attr = getObject(obj, name, 0);
if (!isNotEmpty(attr))
goto cleanup;
if (*dest)
free(*dest);
*dest = strdup(PyString_AsString(attr));
Py_XDECREF(attr);
if (sentinel)
*sentinel = 1;
cleanup:
Py_XDECREF(attr);
}
static void setKickstartNetwork(struct loaderData_s * loaderData, PyObject *handler) {
PyObject *list = getDataList(handler, "network");
PyObject *ele, *attr, *noksdev;
iface_t iface;
if (!list)
return;
/* For now, just use the first network device as the one for loader. */
ele = PyList_GetItem(list, 0);
if (!ele)
goto cleanup;
iface_init_iface_t(&iface);
/* if they've specified dhcp/bootp use dhcp for the interface */
attr = getObject(ele, "bootProto", 0);
if (objIsStr(attr, "dhcp") || objIsStr(attr, "bootp")) {
loaderData->ipv4 = strdup("dhcp");
loaderData->ipinfo_set = 1;
} else if (loaderData->ipv4) {
loaderData->ipinfo_set = 1;
}
Py_XDECREF(attr);
/* --gateway is common for ipv4 and ipv6, same as in loader UI */
attr = getObject(ele, "gateway", 0);
if (isNotEmpty(attr)) {
char *gateway = strdup(PyString_AsString(attr));
int rc;
struct in_addr addr;
#ifdef ENABLE_IPV6
struct in6_addr addr6;
#endif
if ((rc = inet_pton(AF_INET, gateway, &addr)) == 1) {
loaderData->gateway = gateway;
} else if (rc == 0) {
#ifdef ENABLE_IPV6
if ((rc == inet_pton(AF_INET6, gateway, &addr6)) == 1) {
loaderData->gateway6 = gateway;
} else if (rc == 0) {
#endif
logMessage(WARNING,
"invalid address in kickstart --gateway");
#ifdef ENABLE_IPV6
} else {
logMessage(ERROR, "%s (%d): %s", __func__, __LINE__,
strerror(errno));
}
#endif
} else {
logMessage(ERROR, "%s (%d): %s", __func__, __LINE__,
strerror(errno));
}
}
Py_XDECREF(attr);
noksdev = getObject(ele, "notksdevice", 0);
if (!isTrue(noksdev)) {
attr = getObject(ele, "device", 0);
if (isNotEmpty(attr)) {
char *device = PyString_AsString(attr);
/* If --device=MAC was given, translate into a device name now. */
if (index(device, ':') != NULL)
loaderData->netDev = iface_mac2device(device);
else
loaderData->netDev = strdup(device);
loaderData->netDev_set = 1;
}
Py_XDECREF(attr);
_setNetworkString(ele, "dhcpclass", &loaderData->netCls, &loaderData->netCls_set);
_setNetworkString(ele, "ethtool", &loaderData->ethtool, NULL);
_setNetworkString(ele, "essid", &loaderData->essid, NULL);
_setNetworkString(ele, "wepkey", &loaderData->wepkey, NULL);
attr = getObject(ele, "noipv4", 0);
if (isTrue(attr))
flags |= LOADER_FLAGS_NOIPV4;
Py_XDECREF(attr);
attr = getObject(ele, "mtu", 0);
if (isNotEmpty(attr)) {
/* Don't free this string! */
char *mtu = PyString_AsString(attr);
errno = 0;
loaderData->mtu = strtol(mtu, NULL, 10);
if ((errno == ERANGE && (loaderData->mtu == LONG_MIN ||
loaderData->mtu == LONG_MAX)) ||
(errno != 0 && loaderData->mtu == 0)) {
logMessage(ERROR, "%s: %d: %m", __func__, __LINE__);
abort();
}
}
Py_XDECREF(attr);
#ifdef ENABLE_IPV6
attr = getObject(ele, "noipv6", 0);
if (isTrue(attr))
flags |= LOADER_FLAGS_NOIPV6;
if (loaderData->ipv6)
loaderData->ipv6info_set = 1;
Py_XDECREF(attr);
#endif
}
attr = getObject(ele, "nodns", 0);
if (isTrue(attr))
loaderData->noDns = 1;
Py_XDECREF(attr);
Py_XDECREF(noksdev);
/* Make sure the network is always up if there's a network line in the
* kickstart file, as %post/%pre scripts might require that.
*/
if (loaderData->method != METHOD_NFS && loaderData->method != METHOD_URL) {
if (kickstartNetworkUp(loaderData, &iface))
logMessage(ERROR, "unable to bring up network");
}
cleanup:
Py_XDECREF(list);
}
static void setKickstartCD(struct loaderData_s * loaderData, PyObject *handler) {
PyObject *methodObj = getattr(handler, "method", "method");
if (objIsStr(methodObj, "cdrom")) {
logMessage(INFO, "kickstartFromCD");
loaderData->method = METHOD_CDROM;
}
Py_XDECREF(methodObj);
}
static void setKickstartHD(struct loaderData_s * loaderData, PyObject *handler) {
PyObject *methodObj = getattr(handler, "method", "method");
PyObject *biospartObj = NULL;
char *partition = NULL, *dir = NULL;
if (!objIsStr(methodObj, "harddrive"))
goto cleanup;
logMessage(INFO, "kickstartFromHD");
biospartObj = getattr(handler, "method", "biospart");
if (isNotEmpty(biospartObj)) {
char *biospart = strdup(PyString_AsString(biospartObj));
char *dev, *p;
p = strchr(biospart,'p');
if(!p) {
logMessage(ERROR, "Bad argument for --biospart");
free(biospart);
goto cleanup;
}
*p = '\0';
dev = getBiosDisk(biospart);
if (dev == NULL) {
logMessage(ERROR, "Unable to location BIOS partition %s", biospart);
free(biospart);
goto cleanup;
}
partition = malloc(strlen(dev) + strlen(p + 1) + 2);
sprintf(partition, "%s%s", dev, p + 1);
}
loaderData->method = METHOD_HD;
if (!partition)
partition = strdup(PyString_AsString(getattr(handler, "method", "partition")));
dir = strdup(PyString_AsString(getattr(handler, "method", "dir")));
checked_asprintf(&loaderData->instRepo, "hd:%s:%s", partition, dir);
logMessage(INFO, "results of hd ks, partition is %s, dir is %s", partition,
dir);
free(partition);
free(dir);
cleanup:
Py_XDECREF(methodObj);
Py_XDECREF(biospartObj);
}
static void setKickstartNfs(struct loaderData_s * loaderData, PyObject *handler) {
PyObject *methodObj = getattr(handler, "method", "method");
PyObject *hostObj = NULL, *dirObj = NULL, *optsObj = NULL;
char *host, *dir;
if (!objIsStr(methodObj, "nfs"))
goto cleanup;
logMessage(INFO, "kickstartFromNfs");
hostObj = getattr(handler, "method", "server");
dirObj = getattr(handler, "method", "dir");
optsObj = getattr(handler, "method", "opts");
if (!isNotEmpty(hostObj) || !isNotEmpty(dirObj)) {
logMessage(ERROR, "host and directory for nfs kickstart not specified");
goto cleanup;
}
/* Don't free these strings! */
host = PyString_AsString(hostObj);
dir = PyString_AsString(dirObj);
loaderData->method = METHOD_NFS;
if (isNotEmpty(optsObj)) {
logMessage(INFO, "results of nfs, host is %s, dir is %s, opts are '%s'",
host, dir, PyString_AsString(optsObj));
checked_asprintf(&loaderData->instRepo, "nfs:%s:%s:%s",
host, PyString_AsString(optsObj), dir);
} else {
logMessage(INFO, "results of nfs, host is %s, dir is %s", host, dir);
checked_asprintf(&loaderData->instRepo, "nfs:%s:%s", host, dir);
}
cleanup:
Py_XDECREF(methodObj);
Py_XDECREF(hostObj);
Py_XDECREF(dirObj);
Py_XDECREF(optsObj);
}
static void setKickstartUrl(struct loaderData_s * loaderData, PyObject *handler) {
char *url = NULL;
PyObject *methodObj = getattr(handler, "method", "method");
PyObject *urlObj = NULL;
PyObject *noverifysslObj = NULL, *proxyObj = NULL;
if (!objIsStr(methodObj, "url"))
goto cleanup;
urlObj = getattr(handler, "method", "url");
if (!isNotEmpty(urlObj))
goto cleanup;
/* Don't free this string! */
url = PyString_AsString(urlObj);
logMessage(INFO, "kickstartFromUrl");
/* determine install type */
if (strncmp(url, "http", 4) && strncmp(url, "ftp://", 6)) {
newtWinMessage(_("Kickstart Error"), _("OK"),
_("Unknown Url method %s"), url);
goto cleanup;
}
noverifysslObj = getattr(handler, "method", "noverifyssl");
proxyObj = getattr(handler, "method", "proxy");
loaderData->instRepo = strdup(url);
loaderData->method = METHOD_URL;
if (isTrue(noverifysslObj))
loaderData->instRepo_noverifyssl = 1;
else
loaderData->instRepo_noverifyssl = 0;
if (isNotEmpty(proxyObj)) {
splitProxyParam(PyString_AsString(proxyObj), &loaderData->proxyUser,
&loaderData->proxyPassword,
&loaderData->proxy);
}
logMessage(INFO, "results of url ks, url %s", url);
cleanup:
Py_XDECREF(methodObj);
Py_XDECREF(urlObj);
Py_XDECREF(noverifysslObj);
Py_XDECREF(proxyObj);
}
char *runKickstart(struct loaderData_s * loaderData, const char *file) {
PyObject *versionMod, *parserMod = NULL;
PyObject *handler, *parser;
PyObject *processedFile;
char *retval = NULL;
PyObject *callable = NULL;
logMessage(INFO, "setting up kickstart");
Py_Initialize();
if ((versionMod = import("pykickstart.version")) == NULL)
goto quit;
if ((parserMod = import("pykickstart.parser")) == NULL)
goto quit;
if ((constantsMod = import("pykickstart.constants")) == NULL)
goto quit;
/* make the KickstartHandler object */
if ((handler = makeHandler(versionMod)) == NULL)
goto quit;
/* make the KickstartParser object */
if ((callable = getObject(parserMod, "KickstartParser", 1)) == NULL)
goto quit;
else
parser = makeParser(callable, handler);
/* call preprocessKickstart */
processedFile = preprocessKickstart(parserMod, file);
/* call readKickstart */
if (processedFile) {
commandFunc_t *cmd;
if (!readKickstart(parser, processedFile))
goto quit;
/* Now handler is set up with all the kickstart data. Run through
* every element of the ksTable and run its function. The functions
* themselves will decide if they should do anything or not.
*/
for (cmd = ksTable; *cmd != NULL; cmd++)
(*cmd)(loaderData, handler);
retval = strdup(PyString_AsString(processedFile));
}
quit:
Py_XDECREF(constantsMod);
Py_XDECREF(versionMod);
Py_XDECREF(callable);
Py_XDECREF(parserMod);
Py_Finalize();
return retval;
}
/* vim:set sw=4 sts=4 et: */