home *** CD-ROM | disk | FTP | other *** search
-
- /*
- * SmartInstaller.m: the heart of the Smart Installer application.
- *
- * Copyright (C) 1994, Yves Arrouye <Yves.Arrouye@imag.fr>
- *
- */
-
- /*
- * The Smart Installer application and the Smart Package utility suite may be
- * copied and distributed freely, as long as an acknowledgement of the author's
- * work, with its name and address, is kept. The code may not be distributed if
- * it has been modified. Modified code propositions should be directed to the
- * author who will made them if necessary and redistribute the packages.
- *
- */
-
- #import <ctype.h>
- #import <stdio.h>
- #import <string.h>
-
- #import <sys/file.h>
- #import <sys/param.h>
-
- #import "SmartInstaller.h"
-
- /*
- * The DiskName string in the info file
- *
- */
-
- #define DISK_NAME "SmartDiskName"
- #define DISK_NAME_LEN 13
-
- /*
- * Exit codes
- *
- */
-
- enum exit_codes {
- EXIT_OK, // No error
-
- EXIT_NO_INFO, // No info file
- EXIT_NO_DISK_NAME, // No disk name in info file
- EXIT_NO_MEDIA_LIST, // Cannot get removeable media list
- EXIT_NO_SUCH_DISK, // Cancel when asking for a disk
- EXIT_NO_EJECT, // Cannot eject the disk
-
- EXIT_UNKNOWN // Default exit code
- };
-
- @implementation SmartInstaller
-
- + (BOOL)isLocationRoot
- {
- return NO;
- }
-
- - setOnRoot:(BOOL)flag
- {
- if (flag || (!flag && ![[self class] isLocationRoot])) {
- isOnRoot = flag;
- }
-
- return self;
- }
-
- - (BOOL)isOnRoot
- {
- return isOnRoot;
- }
-
- - init
- {
- [super init];
-
- isOnRoot = [[self class] isLocationRoot];
-
- return self;
- }
-
- - initPackage:(const char*)from andDestination:(const char*)to
- {
- return [[self init] setPackage:from andDestination:to];
- }
-
- - setPackage:(const char*)from andDestination:(const char*)to
- {
- char* cptr; // Useful char pointer
- const char* ccptr; // Useful const char pointer
-
- // Remember these ones
-
- fromDir = from;
- destDir = to;
-
- [self setOnRoot:!*destDir];
-
- // Now get the basename (we assume that the extension is .pkg)
-
- if (ccptr = strrchr(fromDir, '/')) {
- ++ccptr;
- } else {
- ccptr = fromDir;
- }
-
- cptr = rootName;
- while (*ccptr && strcmp(ccptr, ".pkg")) {
- *cptr++ = *ccptr++;
- }
- *cptr = '\0';
-
- return self;
- }
- - (int)obtainDisk:(char*)wantedDiskName number:(int)diskVolume
- from:(const char*)diskName
- {
- BOOL ret;
-
- sprintf(wantedDiskName, diskName, diskVolume);
-
- for (;;) {
- char* medias;
-
- if ([[Application workspace]
- getMountedRemovableMedia:&medias]) {
- char* aMedia = strtok(medias, "\t");
- char* dMedia = NULL;
- int diskNumber = 0;
-
- while (aMedia &&
- sscanf(aMedia, diskName, &diskNumber) > 0 &&
- diskNumber != diskVolume) {
- if (diskNumber && !dMedia) {
- dMedia = aMedia;
- }
- aMedia = strtok(NULL, "\t");
- }
-
- if (diskNumber == diskVolume) {
- break;
- } else {
- active = [NXApp activeApp]; [NXApp activateSelf:YES];
-
- if (diskNumber == 0) {
- ret = (NXRunLocalizedAlertPanel("Localizable",
- "Disk Request",
- "Please insert disk %s and click Continue (or click Cancel if the disk is unavailable).",
- "Continue", "Cancel", NULL,
- wantedDiskName + 1) != NX_ALERTDEFAULT);
-
- [NXApp activate:active];
-
- if (ret) {
- return EXIT_NO_SUCH_DISK;
- }
- } else {
- for (;;) {
- if ([[Application workspace]
- unmountAndEjectDeviceAt:dMedia]) {
- break;
- } else {
- active = [NXApp activeApp]; [NXApp activateSelf:YES];
-
- ret = (NXRunLocalizedAlertPanel("Localizable",
- "Disk Problem",
- "Cannot eject disk %s. Click Retry to have another try (or click Cancel to end the installation).",
- "Retry", "Cancel", NULL, dMedia + 1) !=
- NX_ALERTDEFAULT);
-
- [NXApp activate:active];
-
- if (ret) {
- return EXIT_NO_EJECT;
- }
- }
- }
-
- active = [NXApp activeApp]; [NXApp activateSelf:YES];
-
- ret = (NXRunLocalizedAlertPanel("Localizable",
- "Disk Request",
- "You have inserted disk %s. Please insert disk %s and click Continue (or click Cancel if the disk is unavailable).",
- "Continue", "Cancel", NULL, dMedia + 1,
- wantedDiskName + 1) != NX_ALERTDEFAULT);
-
- [NXApp activate:active];
-
- if (ret) {
- return EXIT_NO_SUCH_DISK;
- }
- }
- }
- } else {
- active = [NXApp activeApp]; [NXApp activateSelf:YES];
-
- NXRunLocalizedAlertPanel("Localizable",
- "Disk Problem",
- "Unable to find the name of the disks currently mounted. Please retry later...",
- "Quit", NULL, NULL);
-
- [NXApp activate:active];
-
- return EXIT_NO_MEDIA_LIST;
- }
-
- [[Application workspace] mountNewRemovableMedia:&medias];
- }
-
- return EXIT_OK;
- }
-
- - (int)installMultipleGzipped:(const char*)compName
- {
- char infoName[MAXPATHLEN + 1];
- FILE* info; // Info file handle
-
- int exitCode = EXIT_OK;
-
- if (![NXBundle getPath:infoName forResource:rootName
- ofType:(isOnRoot ? "info.smart" : "info")
- inDirectory:fromDir withVersion:0] || !(info = fopen(infoName, "r"))) {
- NXRunLocalizedAlertPanel("Localizable", "Package Problem",
- "Cannot open package %s (There was an error reading the info file.)",
- "Quit", NULL, NULL, fromDir);
- exitCode = EXIT_NO_INFO;
- } else {
- char diskName[MAXPATHLEN + 1];
-
- char infoLine[512];
- char* line;
-
- // Look for the line with the disk name.
-
- while (line = fgets(infoLine, sizeof(infoLine) / sizeof(char), info)) {
- if (!strncmp(infoLine, DISK_NAME, DISK_NAME_LEN)) {
- break;
- }
- }
-
- fclose(info);
-
- // Get this name.
-
- if (line != NULL) {
- for (line += DISK_NAME_LEN; isspace(*line); ++line) {
- ;
- }
-
- if (*line) {
- char* cptr = diskName;
-
- *cptr++ = '/'; // Assume the disk will be mounted there
-
- do {
- *cptr++ = *line++;
- } while (*line && *line != '\n');
-
- if (*line == '\n') {
- *cptr = '\0';
- }
- } else {
- line = NULL;
- }
- }
-
- if (line == NULL) {
- NXRunLocalizedAlertPanel("Localizable", "Package Problem",
- "Cannot open package %s (There was an error reading the info file.)",
- "Quit", NULL, NULL, fromDir);
- exitCode = EXIT_NO_DISK_NAME;
- } else {
- char wantedDiskName[MAXPATHLEN + 1]; // The current disk
- char compTmpName[MAXPATHLEN + 1]; // Building there (without ext)
-
- BOOL again = YES; // Do we have another volume?
-
- int origDiskVolume = 0; // Our current disk volume
- int diskVolume = 1; // First volume to ask for
-
- char cmdLine[1024];
-
- sprintf(cmdLine, "%s/%s.pkg", diskName, rootName);
- sscanf(fromDir, cmdLine, &origDiskVolume);
-
- sprintf(compTmpName, "/tmp/%s.tar", rootName);
-
- sprintf(cmdLine, "%s.Z", compTmpName);
- unlink(cmdLine);
- sprintf(cmdLine, "%s.gz", compTmpName);
- unlink(cmdLine);
-
- while (again) {
- char cmdLine[1024];
-
- // We have the right to use sprintf here because NeXT's doc.
- // says that the only % is for the %d in the volume name.
-
- if (exitCode = [self obtainDisk:wantedDiskName
- number:diskVolume from:diskName]) {
- return exitCode;
- }
-
- // Now! We shoud be in a situation where the correct disk is
- // mounted under slash. Now please get the gzipped part.
-
- sprintf(cmdLine, "/bin/cat \"%s/%s.pkg/%s.tar.gz.%d\" >>%s.gz",
- wantedDiskName, rootName, rootName, diskVolume,
- compTmpName);
-
- if (exitCode = system(cmdLine)) {
- break;
- } else {
- char lastName[MAXPATHLEN + 1];
-
- sprintf(lastName, "%s/%s.pkg/.last",
- wantedDiskName, rootName);
- again = access(lastName, F_OK);
-
- if (!again && diskVolume == origDiskVolume) {
- break;
- }
-
- // Eject the disk
-
- for (;;) {
- if ([[Application workspace]
- unmountAndEjectDeviceAt:wantedDiskName]) {
- break;
- } else {
- BOOL ret;
-
- active = [NXApp activeApp]; [NXApp activateSelf:YES];
-
- ret = (NXRunLocalizedAlertPanel("Localizable",
- "Disk Problem",
- "Cannot eject disk %s. Click Retry to have another try (or click Cancel to end the installation).",
- "Retry", "Cancel", NULL, wantedDiskName + 1) !=
- NX_ALERTDEFAULT);
-
- [NXApp activate:active];
-
- if (ret) {
- return EXIT_NO_EJECT;
- }
- }
- }
-
- // Next disk, please!
-
- ++diskVolume;
- }
- }
-
- // Now funzip the whole archive, and remove it after that
-
- sprintf(cmdLine,
- "%s/funzip %s.gz | compress -c >%s.Z; /bin/rm -rf %s.gz; /bin/rm -f /tmp/%s.info; /bin/ln -s \"%s\" /tmp/%s.info",
- [[NXBundle mainBundle] directory],
- compTmpName, compTmpName, compTmpName, infoName,
- rootName, rootName);
-
- if (!(exitCode = system(cmdLine))) {
-
- // Get the original disk back
-
- exitCode = [self obtainDisk:wantedDiskName
- number:origDiskVolume from:diskName];
-
- if (isOnRoot) {
- active = [NXApp activeApp]; [NXApp activateSelf:YES];
-
- if (NXRunLocalizedAlertPanel("Localizable",
- "Smart Installer",
- "Smart installation done. Click Install to launch Installer and install the package (or click Quit if you want to quit now).",
- "Install", "Quit", NULL) != NX_ALERTDEFAULT) {
- return EXIT_OK;
- }
- }
-
- [[Application workspace] openFile:fromDir];
- }
- }
- }
-
- return exitCode; // Be careful: some return hide above!
- }
-
- - (int)installPackage
- {
- char compName[MAXPATHLEN + 1];
-
- int exitCode = EXIT_UNKNOWN;
-
- sprintf(compName, "%s/%s.gz", fromDir, rootName);
- if (access(compName, R_OK) == 0) {
- char cmdLine[1024];
-
- sprintf(cmdLine, "%s/funzip %s | /usr/ucb/compress -c >/tmp/%s.tar.Z",
- [[NXBundle mainBundle] directory], compName, rootName);
- exitCode = system(cmdLine);
- } else {
- exitCode = [self installMultipleGzipped:compName];
- }
-
- return exitCode;
- }
-
- @end
-