This is SmartInstaller.m in view mode; [Download] [Up]
/*
* 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
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.