/* * General squeak functions and interpreter entrypoint for Plan9. * * Author: Alex Franchuk (alex.franchuk@gmail.com) */ #include #include #include #include #include #include #include "sq.h" #include "p9iface.h" #define DefaultHeapSize 20 /* megabytes BEYOND actual image size */ int argCnt= 0; /* global copies for access from plugins */ char **argVec= 0; char **envVec= 0; static int vmArgCnt= 0; /* for getAttributeIntoLength() */ static char **vmArgVec= 0; static int squeakArgCnt= 0; static char **squeakArgVec= 0; static long extraMemory= 0; char imageName[MAXPATHLEN+1]; /* full path to image */ char shortImageName[MAXPATHLEN+1]; /* image name */ char vmName[MAXPATHLEN+1]; /* full path to VM */ char vmPath[MAXPATHLEN+1]; /* full path to image directory */ /*** errors ***/ static void outOfMemory(void) { fprintf(stderr, "out of memory\n"); exit(1); } static void sigsegv(int ignore) { printf("\nSegmentation fault\n\n"); } static void parseArguments(int argc, char **argv) { # define skipArg() (--argc, argv++) # define saveArg() (vmArgVec[vmArgCnt++]= *skipArg()) saveArg(); /* vm name */ while ((argc > 0) && (**argv == '-')) { /* more options to parse */ if (!strcmp(*argv, "--")) break; /* escape from option processing */ /* Skip all options for now */ skipArg(); } if (!argc) return; if (!strcmp(*argv, "--")) skipArg(); else { /* image name */ strcpy(shortImageName, saveArg()); if (!strstr(shortImageName, ".image")) strcat(shortImageName, ".image"); } getcwd(imageName,sizeof(imageName)); strcat(imageName, "/"); strcat(imageName, shortImageName); strcpy(vmPath, imageName); int lastslash = -1; for (int i = 0; i < sizeof(vmPath) && vmPath[i] != '\0'; i++) { if (vmPath[i] == '/') { lastslash = i; } } if (lastslash != -1) { vmPath[lastslash+1] = '\0'; } /*cleanname(imageName);*/ /* save remaining arguments as Squeak arguments */ while (argc > 0) squeakArgVec[squeakArgCnt++]= *skipArg(); # undef saveArg # undef skipArg } void imgInit(void) { /* read the image file and allocate memory for Squeak heap */ FILE *f = 0; struct stat sb; char imageName[MAXPATHLEN]; strcpy(imageName, shortImageName); if ((-1 == stat(imageName, &sb)) || (0 == (f = fopen(imageName, "r")))) { fprintf(stderr, "Image file could not be opened: %s", imageName); exit(1); } extraMemory = DefaultHeapSize * 1024 *1024; extraMemory += (long)sb.st_size; readImageFromFileHeapSize(f, extraMemory); sqImageFileClose(f); } /*** interpreter entrypoint ***/ int main(int argc, char **argv, char **envp) { /* Make parameters global for access from plugins */ argCnt= argc; argVec= argv; envVec= envp; /* Allocate arrays to store copies of pointers to command line arguments. Used by getAttributeIntoLength(). */ if ((vmArgVec= calloc(argc + 1, sizeof(char *))) == 0) outOfMemory(); if ((squeakArgVec= calloc(argc + 1, sizeof(char *))) == 0) outOfMemory(); signal(SIGSEGV, sigsegv); #if defined(HAVE_TZSET) tzset(); /* should _not_ be necessary! */ #endif parseArguments(argc, argv); /* fill in vm path */ getcwd(vmName, sizeof(vmName)); strcat(vmName,"/"); strcat(vmName, argVec[0]); /* init system */ if (displayInit() == -1) { printf("Failed to initialize display\n"); return EXIT_FAILURE; } if (ioInit() == -1) { printf("Failed to initialize keyboard/mouse\n"); return EXIT_FAILURE; } imgInit(); timeInit(); /* run Squeak */ interpret(); /* destroy data from initialization */ ioDestroy(); displayDestroy(); return EXIT_SUCCESS; } /* Copy aFilenameString to aCharBuffer and optionally resolveAlias (or symbolic link) to the real path of the target. Answer 0 if successful of -1 to indicate an error. Assume aCharBuffer is at least MAXPATHLEN bytes long. Note that MAXSYMLINKS is a lower bound on the (potentially unlimited) number of symlinks allowed in a path, but calling sysconf() seems like overkill. */ sqInt sqGetFilenameFromString(char *aCharBuffer, char *aFilenameString, sqInt filenameLength, sqInt resolveAlias) { int numLinks= 0; struct stat st; if ((filenameLength < 0) || (filenameLength > MAXPATHLEN)) { return -1; } strncpy(aCharBuffer, aFilenameString, filenameLength); return 0; } /* Attribute functions */ static char *getAttribute(sqInt id) { if (id < 0) { if (-id < vmArgCnt) return vmArgVec[-id]; } else switch (id) { case 0: return vmName[0] ? vmName : vmArgVec[0]; case 1: return imageName; case 1001: /* OS type: "unix", "win32", "mac", ... */ return OS_TYPE; case 1002: /* OS name: "solaris2.5" on unix, "win95" on win32, ... */ return VM_HOST_OS; case 1003: /* processor architecture: "68k", "x86", "PowerPC", ... */ return VM_HOST_CPU; case 1004: /* Interpreter version string */ return (char *)interpreterVersion; case 1005: /* window system name */ return WINDOW_SYS_NAME; case 1006: /* vm build string */ return VM_BUILD_STRING; default: if ((id - 2) < squeakArgCnt) return squeakArgVec[id - 2]; } success(false); return ""; } sqInt attributeSize(sqInt indexNumber) { return strlen(getAttribute(indexNumber)); } sqInt getAttributeIntoLength(sqInt indexNumber, sqInt byteArrayIndex, sqInt length) { if (length > 0) { strncpy((char*)pointerForOop(byteArrayIndex), getAttribute(indexNumber), length); } return 0; } /* Image functions */ char *getImageName(void) { return imageName; } sqInt imageNameGetLength(sqInt sqImageNameIndex, sqInt length) { char* buf = (char*)pointerForOop(sqImageNameIndex); int count = length < strlen(imageName) ? length : strlen(imageName); strncpy(buf, imageName, count); return count; } sqInt imageNamePutLength(sqInt sqImageNameIndex, sqInt length) { char* buf = (char*)pointerForOop(sqImageNameIndex); int count = length < sizeof(imageName) ? length : sizeof(imageName) - 1; strncpy(imageName, buf, count); imageName[length] = '\0'; return count; } sqInt imageNameSize(void) { return strlen(imageName); } sqInt vmPathSize(void) { return strlen(vmPath); } sqInt vmPathGetLength(sqInt sqVMPathIndex, sqInt length) { char* buf = (char*)pointerForOop(sqVMPathIndex); int count = length < strlen(vmPath) ? length : strlen(vmPath); strncpy(buf, vmPath, count); return count; } /* Image security traps */ sqInt ioCanRenameImage(void) { return true; } sqInt ioCanWriteImage(void) { return true; } sqInt ioDisableImageWrite(void) { return false; }