diff options
Diffstat (limited to 'loader2')
-rw-r--r-- | loader2/cdinstall.c | 4 | ||||
-rw-r--r-- | loader2/driverdisk.c | 26 | ||||
-rw-r--r-- | loader2/hardware.c | 14 | ||||
-rw-r--r-- | loader2/hdinstall.c | 23 | ||||
-rw-r--r-- | loader2/lang.c | 8 | ||||
-rw-r--r-- | loader2/linuxrc.s390 | 2 | ||||
-rw-r--r-- | loader2/loader.c | 6 | ||||
-rw-r--r-- | loader2/modstubs.c | 38 | ||||
-rw-r--r-- | loader2/moduleinfo.h | 7 | ||||
-rw-r--r-- | loader2/modules.c | 144 | ||||
-rw-r--r-- | loader2/modules.h | 5 | ||||
-rw-r--r-- | loader2/net.c | 8 | ||||
-rw-r--r-- | loader2/otherinsmod.c | 161 |
13 files changed, 168 insertions, 278 deletions
diff --git a/loader2/cdinstall.c b/loader2/cdinstall.c index 3d633c000..7d1f4c9f2 100644 --- a/loader2/cdinstall.c +++ b/loader2/cdinstall.c @@ -299,7 +299,7 @@ char * setupCdrom(char * location, for (i = 0; i < kd->numKnown; i++) { if (kd->known[i].class != CLASS_CDROM) continue; buf = malloc(200); - sprintf(buf, "cdrom://%s/mnt/source", kd->known[i].name); + sprintf(buf, "cdrom://%s:/mnt/source", kd->known[i].name); return buf; } } @@ -328,7 +328,7 @@ char * setupCdrom(char * location, queryCDMediaCheck(kd->known[i].name, flags); buf = malloc(200); - sprintf(buf, "cdrom://%s/mnt/source", kd->known[i].name); + sprintf(buf, "cdrom://%s:/mnt/source", kd->known[i].name); return buf; } diff --git a/loader2/driverdisk.c b/loader2/driverdisk.c index 73a5ca2d4..ec063193f 100644 --- a/loader2/driverdisk.c +++ b/loader2/driverdisk.c @@ -56,7 +56,18 @@ static int verifyDriverDisk(char *mntpt, int flags) { } } - /* side effect: file is still mntpt/rhdd-6.1 */ + /* check for both versions */ + sprintf(file, "%s/rhdd", mntpt); + if (!access(file, R_OK)) { + logMessage("not a new format driver disk, checking for old"); + sprintf(file, "%s/rhdd-6.1", mntpt); + if (!access(file, R_OK)) { + logMessage("can't find either driver disk identifier, bad " + "driver disk"); + } + } + + /* side effect: file is still mntpt/ddident */ stat(file, &sb); if (!sb.st_size) return LOADER_BACK; @@ -74,9 +85,19 @@ static int loadDriverDisk(moduleInfoSet modInfo, moduleList modLoaded, struct moduleBallLocation * location; struct stat sb; static int disknum = 0; + int version = 1; int fd; - sprintf(file, "%s/rhdd-6.1", mntpt); + /* check for both versions */ + sprintf(file, "%s/rhdd", mntpt); + if (!access(file, R_OK)) { + version = 0; + sprintf(file, "%s/rhdd-6.1", mntpt); + if (!access(file, R_OK)) { + /* this can't happen, we already verified it! */ + return LOADER_BACK; + } + } stat(file, &sb); title = malloc(sb.st_size + 1); @@ -101,6 +122,7 @@ static int loadDriverDisk(moduleInfoSet modInfo, moduleList modLoaded, location = malloc(sizeof(struct moduleBallLocation)); location->title = strdup(title); location->path = sdupprintf("/tmp/ramfs/DD-%d/modules.cgz", disknum); + location->version = version; sprintf(file, "%s/modinfo", mntpt); readModuleInfo(file, modInfo, location, 1); diff --git a/loader2/hardware.c b/loader2/hardware.c index 509fd4cb5..24e6d2381 100644 --- a/loader2/hardware.c +++ b/loader2/hardware.c @@ -329,12 +329,14 @@ void dasdSetup(moduleList modLoaded, moduleDeps modDeps, strcpy(parms,"dasd="); strcat(parms, ports); dasd_parms[0] = parms; - simpleRemoveLoadedModule("dasd_eckd_mod", modLoaded, flags); - simpleRemoveLoadedModule("dasd_fba_mod", modLoaded, flags); - simpleRemoveLoadedModule("dasd_diag_mod", modLoaded, flags); - simpleRemoveLoadedModule("dasd_mod", modLoaded, flags); - reloadUnloadedModule("dasd_mod", modLoaded, dasd_parms, flags); - reloadUnloadedModule("dasd_eckd_mod", modLoaded, NULL, flags); + removeLoadedModule("dasd_eckd_mod", modLoaded, flags); + removeLoadedModule("dasd_fba_mod", modLoaded, flags); + removeLoadedModule("dasd_diag_mod", modLoaded, flags); + removeLoadedModule("dasd_mod", modLoaded, flags); + mlLoadModule("dasd_mod", modLoaded, modDeps, modInfo, + dasd_parms, flags); + mlLoadModuleSet("dasd_diag_mod:dasd_fba_mod:dasd_eckd_mod", + modLoaded, modDeps, modInfo, flags); free(dasd_parms); free(ports); } diff --git a/loader2/hdinstall.c b/loader2/hdinstall.c index fff21a518..3941c1fea 100644 --- a/loader2/hdinstall.c +++ b/loader2/hdinstall.c @@ -50,7 +50,7 @@ int isPartitionName(char *pname) { return 0; /* if it has a '/' in it then treat it specially */ - if (strchr(pname, '/')) { + if (strchr(pname, '/') && !strstr(pname, "iseries")) { /* assume its either a /dev/ida/ or /dev/cciss device */ /* these have form of c?d?p? if its a partition */ return strchr(pname, 'p') != NULL; @@ -160,6 +160,7 @@ int lenPartitionsList(char **list) { char **part; int rc; + if (!list) return 0; for (rc = 0, part = list; *part; rc++, part++); return rc; @@ -199,6 +200,15 @@ static int loadHDImages(char * prefix, char * dir, int flags, return 1; } + /* handle updates.img now before we copy stage2 over... this allows + * us to keep our ramdisk size as small as possible */ + sprintf(path, "%s/%s/RedHat/base/updates.img", prefix, dir ? dir : ""); + copyUpdatesImg(path); + + rc = copyFileAndLoopbackMount(fd, "/tmp/ramfs/hdstg2.img", flags, + device, mntpoint); + close(fd); + if (!verifyStamp(mntpoint)) { char * buf; buf = sdupprintf(_("The %s installation tree in that directory does " @@ -210,15 +220,6 @@ static int loadHDImages(char * prefix, char * dir, int flags, return 1; } - /* handle updates.img now before we copy stage2 over... this allows - * us to keep our ramdisk size as small as possible */ - sprintf(path, "%s/%s/RedHat/base/updates.img", prefix, dir ? dir : ""); - copyUpdatesImg(path); - - rc = copyFileAndLoopbackMount(fd, "/tmp/ramfs/hdstg2.img", flags, - device, mntpoint); - close(fd); - return rc; } @@ -494,7 +495,7 @@ char * mountHardDrive(struct installMethod * method, label = newtLabel(-1, -1, _("Directory holding images:")); - dirEntry = newtEntry(28, 11, dir, 28, &tmpDir, NEWT_ENTRY_SCROLL); + dirEntry = newtEntry(28, 11, dir, 28, (const char **) &tmpDir, NEWT_ENTRY_SCROLL); /* if we had ks data around use it to prime entry, then get rid of it*/ if (ksdirectory) { diff --git a/loader2/lang.c b/loader2/lang.c index 52cf0ed77..7450f7162 100644 --- a/loader2/lang.c +++ b/loader2/lang.c @@ -36,6 +36,7 @@ #include "../isys/stubs.h" #include "../isys/cpio.h" #include "../isys/lang.h" +#include "../isys/isys.h" static int startBterm(int flags); @@ -228,7 +229,7 @@ static int setupLanguage(int choice, int flags) { /* load the language only if it is displayable. if they're using * a serial console, we hope it's smart enough */ if (!strcmp(languages[choice].font, "bterm") && !FL_SERIAL(flags) && - startBterm(flags)) { + !isVioConsole() && startBterm(flags)) { if (FL_KICKSTART(flags)) return 0; newtWinMessage("Language Unavailable", "OK", @@ -385,9 +386,10 @@ int chooseLanguage(char ** lang, int flags) { if (i == numLanguages) abort(); /* load the language only if it is displayable. assume that if they're - * on a serial console that their terminal is smart. */ + * on a serial console or iSeries vioconsole that their terminal is + * smart. */ if (!strcmp(languages[choice].font, "bterm") && !FL_SERIAL(flags) && - startBterm(flags)) { + !isVioConsole() && startBterm(flags)) { newtWinMessage("Language Unavailable", "OK", "%s display is unavailable in text mode. The " "installation will continue in English until the " diff --git a/loader2/linuxrc.s390 b/loader2/linuxrc.s390 index df964865d..b20a6abcf 100644 --- a/loader2/linuxrc.s390 +++ b/loader2/linuxrc.s390 @@ -232,6 +232,8 @@ if [ ":$NETTYPE" = ":ctc" -o ":$NETTYPE" = ":escon" ]; then ifconfig $DEVICE $IPADDR $MMTU pointopoint $GATEWAY route add -host $IPADDR dev $DEVICE 2>/dev/null elif [ ":$NETTYPE" = ":iucv" ]; then + insmod fsm$LO + insmod iucv$LO insmod netiucv$LO $IUCV ifconfig $DEVICE $IPADDR $MMTU pointopoint $GATEWAY route add -host $IPADDR dev $DEVICE 2>/dev/null diff --git a/loader2/loader.c b/loader2/loader.c index 00423aba8..60c870b6a 100644 --- a/loader2/loader.c +++ b/loader2/loader.c @@ -688,6 +688,11 @@ static char *doLoaderMain(char * location, if (url && !FL_RESCUE(flags)) return url; } + /* iSeries vio console users will be telnetting in to the primary + partition, so use a terminal type that is appripriate */ + if (isVioConsole()) + setenv("TERM", "vt100", 1); + startNewt(flags); step = STEP_LANG; @@ -984,6 +989,7 @@ int main(int argc, char ** argv) { /* JKFIXME: very very bad hack */ secondStageModuleLocation = malloc(sizeof(struct moduleBallLocation)); secondStageModuleLocation->path = strdup("/mnt/runtime/modules/modules.cgz"); + secondStageModuleLocation->version = CURRENT_MODBALLVER; if (!strcmp(argv[0] + strlen(argv[0]) - 6, "insmod")) return ourInsmodCommand(argc, argv); diff --git a/loader2/modstubs.c b/loader2/modstubs.c index 9e3f71f2a..e783ced94 100644 --- a/loader2/modstubs.c +++ b/loader2/modstubs.c @@ -25,10 +25,16 @@ #include <sys/wait.h> #include "modstubs.h" +#include "modules.h" #include "../isys/cpio.h" #include "../isys/stubs.h" +static int usage() { + fprintf(stderr, "usage: insmod [-p <path>] <module>.o\n"); + return 1; +} + int ourInsmodCommand(int argc, char ** argv) { char * file; char finalName[100]; @@ -37,21 +43,28 @@ int ourInsmodCommand(int argc, char ** argv) { int rc, rmObj = 0; char * ballPath = NULL; char fullName[100]; - struct utsname u; - - uname(&u); + int version = 1; if (argc < 2) { - fprintf(stderr, "usage: insmod [-p <path>] <module>.o [params]\n"); - return 1; + return usage(); + } + + while (argc > 2) { + if (!strcmp(argv[1], "-p")) { + ballPath = malloc(strlen(argv[2]) + 30); + sprintf(ballPath, "%s/modules.cgz", argv[2]); + argv += 2; + argc -= 2; + } else if (!strcmp(argv[1], "--modballversion")) { + version = atoi(argv[2]); + argv += 2; + argc -= 2; + } else { + break; + } } - if (!strcmp(argv[1], "-p")) { - ballPath = malloc(strlen(argv[2]) + 30); - sprintf(ballPath, "%s/modules.cgz", argv[2]); - argv += 2; - argc -= 2; - } else { + if (!ballPath) { ballPath = strdup("/modules/modules.cgz"); } @@ -69,7 +82,8 @@ int ourInsmodCommand(int argc, char ** argv) { if (chptr) file = chptr + 1; sprintf(finalName, "/tmp/%s", file); - sprintf(fullName, "%s/%s", u.release, file); + /* XXX: leak */ + sprintf(fullName, "%s/%s", getModuleLocation(version), file); if (installCpioFile(fd, fullName, finalName, 0)) { free(ballPath); diff --git a/loader2/moduleinfo.h b/loader2/moduleinfo.h index becee0e74..8c6bd3966 100644 --- a/loader2/moduleinfo.h +++ b/loader2/moduleinfo.h @@ -33,7 +33,14 @@ struct moduleBallLocation { char * path; /* path to module ball that this driver is from. if NULL, * implies /modules/modules.cgz */ char * title; /* title used for driver disk -- may be NULL */ + int version; /* module ball version, used to determine layout */ }; +#define CURRENT_MODBALLVER 1 + +/* valid moduleball versions + * 0: old single-arch module ball, modules are in uname.release + * 1: multi-arch, modules are in uname.release/arch + */ typedef struct moduleInfoSet_s * moduleInfoSet; diff --git a/loader2/modules.c b/loader2/modules.c index b0df111ee..b9fad4f38 100644 --- a/loader2/modules.c +++ b/loader2/modules.c @@ -483,7 +483,7 @@ static int doLoadModules(const char * origModNames, moduleList modLoaded, } /* here we need to save the state of stage2 */ - simpleRemoveLoadedModule("usb-storage", modLoaded, flags); + removeLoadedModule("usb-storage", modLoaded, flags); /* JKFIXME: here are the big hacks... for now, just described. * 1) figure out which scsi devs are claimed by usb-storage. @@ -510,7 +510,7 @@ static int doLoadModules(const char * origModNames, moduleList modLoaded, } if (reloadUsbStorage) { - reloadUnloadedModule("usb-storage", modLoaded, NULL, flags); + mlLoadModule("usb-storage", modLoaded, modDeps, modInfo, NULL, flags); /* JKFIXME: here's the rest of the hacks. basically do the reverse * of what we did before. */ @@ -701,6 +701,40 @@ void writeScsiDisks(moduleList list) { return; } +char * getModuleLocation(int version) { + struct utsname u; + static char * arch = NULL; + const char * archfile = "/etc/arch"; + char * ret; + + uname(&u); + + if (!arch) { + struct stat sb; + int fd; + + stat(archfile, &sb); + arch = malloc(sb.st_size + 1); + + fd = open(archfile, O_RDONLY); + read(fd, arch, sb.st_size); + if (arch[sb.st_size -1 ] == '\n') + sb.st_size--; + arch[sb.st_size] = '\0'; + close(fd); + } + + if (version == 1) { + ret = malloc(strlen(u.release) + strlen(arch) + 1); + sprintf(ret, "%s/%s", u.release, arch); + return ret; + } else { + ret = malloc(strlen(u.release) + 1); + strcpy(ret, u.release); + return ret; + } +} + /* JKFIXME: needs a way to know about module locations. also, we should * extract them to a ramfs instead of /tmp */ static struct extractedModule * extractModules (char * const * modNames, @@ -715,15 +749,15 @@ static struct extractedModule * extractModules (char * const * modNames, char fn[255]; const char * failedFile; struct stat sb; - struct utsname u; - - uname(&u); + char * modpath; - /* JKFIXME: handle driver disk path somehow */ - if (!location) + if (!location) { ballPath = strdup("/modules/modules.cgz"); - else + modpath = getModuleLocation(CURRENT_MODBALLVER); + } else { ballPath = strdup(location->path); + modpath = getModuleLocation(location->version); + } fd = gunzip_open(ballPath); if (!fd) { @@ -744,9 +778,9 @@ static struct extractedModule * extractModules (char * const * modNames, for (m = modNames, i = 0, numMaps = 0; *m; m++, i++) { /* if we don't know the path of this module yet, "figure" it out */ if (!oldPaths[i].path) { - map[numMaps].archivePath = alloca(strlen(u.release) + + map[numMaps].archivePath = alloca(strlen(modpath) + strlen(*m) + 25); - sprintf(map[numMaps].archivePath, "%s/%s.o", u.release, *m); + sprintf(map[numMaps].archivePath, "%s/%s.o", modpath, *m); map[numMaps].fsPath = alloca(10 + strlen(*m)); sprintf(map[numMaps].fsPath, "/tmp/%s.o", *m); unlink(map[numMaps].fsPath); @@ -758,6 +792,7 @@ static struct extractedModule * extractModules (char * const * modNames, if (!numMaps) { gunzip_close(fd); free(ballPath); + free(modpath); return oldPaths; } @@ -787,18 +822,17 @@ static struct extractedModule * extractModules (char * const * modNames, } free(ballPath); + free(modpath); return oldPaths; } -/* simple removal of a loaded module which is going to be reloaded. - * Note that this doesn't remove the module from the modLoaded struct - * but we do update the loadedModuleInfo to reflect the fact that its using - * no devices anymore. +/* remove a module which has been loaded, including removal from the + * modLoaded struct */ -int simpleRemoveLoadedModule(const char * modName, moduleList modLoaded, - int flags) { +int removeLoadedModule(const char * modName, moduleList modLoaded, + int flags) { int status, rc = 0; pid_t child; struct loadedModuleInfo * mod; @@ -834,70 +868,25 @@ int simpleRemoveLoadedModule(const char * modName, moduleList modLoaded, if (!WIFEXITED(status) || WEXITSTATUS(status)) { rc = 1; } else { - rc = 0; - } - } - return rc; -} - -/* simple reinsertion of a module; just looks for the module and reloads it - * if we think it was already loaded. we also update firstDevNum and - * lastDevNum to be current - */ -int reloadUnloadedModule(char * modName, moduleList modLoaded, - char ** args, int flags) { - char fileName[200]; - int rc, status; - pid_t child; - struct extractedModule * path = NULL; - char * list[2]; - int i; - - for (i = 0; i < modLoaded->numModules; i++) - if (!strcmp(modLoaded->mods[i].name, modName)) - break; - - if (i >= modLoaded->numModules) - return 0; - - modLoaded->mods[i].firstDevNum = scsiDiskCount(); - - list[0] = modName; - list[1] = NULL; - - path = extractModules(list, path, NULL); - - sprintf(fileName, "%s.o", modName); - - if (FL_TESTING(flags)) { - logMessage("would have insmod %s", fileName); - rc = 0; - } else { - logMessage("going to insmod %s", fileName); - - if (!(child = fork())) { - int fd = open("/dev/tty3", O_RDWR); - - dup2(fd, 0); - dup2(fd, 1); - dup2(fd, 2); - close(fd); - - rc = insmod(fileName, NULL, args); - _exit(rc); - } - - waitpid(child, &status, 0); + int found = -1; + int i; + + /* find our module. once we've found it, shutffle everything + * else back one */ + for (i = 0; i < modLoaded->numModules; i++) { + if (found > -1) { + modLoaded->mods[i - 1] = modLoaded->mods[i]; + } else if (!strcmp(modLoaded->mods[i].name, modName)) { + found = i; + free(modLoaded->mods[i].name); + free(modLoaded->mods[i].path); + } + } + modLoaded->numModules--; - if (!WIFEXITED(status) || WEXITSTATUS(status)) { - rc = 1; - } else { - rc = 0; + rc = 0; } } - - modLoaded->mods[i].lastDevNum = scsiDiskCount(); - logMessage("reloadModule returning %d", rc); return rc; } @@ -963,3 +952,4 @@ void loadKickstartModule(struct loaderData_s * loaderData, int argc, mlLoadModule(module, loaderData->modLoaded, *(loaderData->modDepsPtr), loaderData->modInfo, args, flags); } + diff --git a/loader2/modules.h b/loader2/modules.h index 7f43457c8..616da95aa 100644 --- a/loader2/modules.h +++ b/loader2/modules.h @@ -44,9 +44,8 @@ int mlLoadModuleSetLocation(const char * modNames, int mlModuleInList(const char * modName, moduleList list); void writeScsiDisks(moduleList list); -int simpleRemoveLoadedModule(const char * modName, moduleList modLoaded, +int removeLoadedModule(const char * modName, moduleList modLoaded, int flags); -int reloadUnloadedModule(char * modName, moduleList modLoaded, - char **, int flags); +char * getModuleLocation(int version); #endif diff --git a/loader2/net.c b/loader2/net.c index d8c6d1bcb..799580a38 100644 --- a/loader2/net.c +++ b/loader2/net.c @@ -706,6 +706,7 @@ int chooseNetworkInterface(struct knownDevices * kd, int deviceNums = 0; int deviceNum; char ** devices; + int foundDev = 0; /* JKFIXME: this is a lot bigger than it has to be.. */ devices = alloca((kd->numKnown + 1) * sizeof(*devices)); @@ -715,12 +716,17 @@ int chooseNetworkInterface(struct knownDevices * kd, devices[deviceNums++] = kd->known[i].name; + /* make sure that this device is disabled */ + pumpDisableInterface(kd->known[i].name); + /* this device has been set and we don't really need to ask * about it again... */ if (loaderData->netDev && (loaderData->netDev_set == 1) && !strcmp(loaderData->netDev, kd->known[i].name)) - return LOADER_NOOP; + foundDev = 1; } + if (foundDev == 1) + return LOADER_NOOP; devices[deviceNums] = NULL; diff --git a/loader2/otherinsmod.c b/loader2/otherinsmod.c deleted file mode 100644 index 881946533..000000000 --- a/loader2/otherinsmod.c +++ /dev/null @@ -1,161 +0,0 @@ -#include <stdio.h> -#include <string.h> -#include <unistd.h> -#include <fcntl.h> -#include <stdlib.h> -#include <sys/utsname.h> -#include <sys/wait.h> - -#include "cpio.h" -#include "isys.h" -#include "stubs.h" - -/* hack */ -int combined_insmod_main(int argc, char ** argv); - -int ourInsmodCommand(int argc, char ** argv) { - char * file; - char finalName[100]; - char * chptr; - gzFile fd; - int rc, rmObj = 0; - int sparc64 = 0, i; - char * ballPath = NULL; - char fullName[100]; - struct utsname u; - - uname(&u); - -#ifdef __sparc__ - if (!strcmp(u.machine, "sparc64")) - sparc64 = 1; -#endif - - if (argc < 2) { - fprintf(stderr, "usage: insmod [-p <path>] <module>.o [params]\n"); - return 1; - } - - if (!strcmp(argv[1], "-p")) { - ballPath = malloc(strlen(argv[2]) + 30); - sprintf(ballPath, "%s/%s", argv[2], sparc64 ? - "modules64.cgz" : "modules.cgz"); - argv += 2; - argc -= 2; - } else { - ballPath = strdup(sparc64 ? - "/modules/modules64.cgz" : - "/modules/modules.cgz"); - - } - - file = argv[1]; - - if (access(file, R_OK)) { - /* Try two balls on sparc64, one elsewhere */ - for (i = 0; ; i++) { - /* it might be having a ball */ - fd = gunzip_open(ballPath); - if (!fd) { - free(ballPath); - return 1; - } - - chptr = strrchr(file, '/'); - if (chptr) file = chptr + 1; - sprintf(finalName, "/tmp/%s", file); - - sprintf(fullName, "%s/%s", u.release, file); - - if (installCpioFile(fd, fullName, finalName, 0)) { - if (i < sparc64) { - ballPath[strlen(ballPath)-5] = '5'; - continue; - } - free(ballPath); - return 1; - } - - rmObj = 1; - file = finalName; - break; - } - } - - free(ballPath); - - argv[0] = "insmod"; - argv[1] = file; - - rc = combined_insmod_main(argc, argv); - - if (rmObj) unlink(file); - - return rc; -} - -int rmmod(char * modName) { - pid_t child; - int status; - char * argv[] = { "/bin/rmmod", modName, NULL }; - int argc = 2; - int rc = 0; - - if ((child = fork()) == 0) { - exit(combined_insmod_main(argc, argv)); - } - - waitpid(child, &status, 0); - - if (WIFEXITED(status)) - rc = WEXITSTATUS(status); - else - rc = -1; - - return rc; -} - -int insmod(char * modName, char * path, char ** args) { - int argc; - char ** argv; - int rc = 0; - pid_t child; - int status; - int count; - - argc = 0; - for (argv = args; argv && *argv; argv++, argc++); - - argv = alloca(sizeof(*argv) * (argc + 5)); - argv[0] = "/bin/insmod"; - count = 1; - if (path) { - argv[1] = "-p"; - argv[2] = path; - count += 2; - } - - argv[count] = modName; - count++; - - if (args) - memcpy(argv + count, args, sizeof(*args) * argc); - - argv[argc + count] = NULL; - - argc += count; - - if ((child = fork()) == 0) { - execv("/bin/loader", argv); - exit(1); - } - - waitpid(child, &status, 0); - - if (WIFEXITED(status)) - rc = WEXITSTATUS(status); - else - rc = -1; - - return rc; -} |