'From Squeak3.1alpha of 4 February 2001 [latest update: #3526] on 6 February 2001 at 3:00:08 pm'! "Change Set: VMSecurity-ar Date: 5 February 2001 Author: Andreas Raab The change set includes various additions wrt VM security issues. Included are security checks for files, sockets and the ability to write the image. A SecurityPlugin is provided for obtaining some important pieces of information (see the class comment). These facilities are by no means complete and they are provided here as a first take on the issue. However, revoking the abilities mentioned above is obviously crucial. NOTE TO VM IMPLEMENTORS: All the newly required security support functions can be disabled by defining DISABLE_SECURITY. "! InterpreterPlugin subclass: #SecurityPlugin instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'VMConstruction-Plugins'! !SecurityPlugin commentStamp: '' prior: 0! IMPLEMENTATION NOTES: The support should assume a trusted directory based on which access to files is granted when running in restricted mode. If necessary, links need to be resolved before granting access (currently, this applies only to platforms on which links can be created by simply creating the right kind of file). The untrusted user directory returned MUST be different from the image and VM location. Otherwise a Badlet could attempt to overwrite these by using simple file primitives. The secure directory location returned by the primitive is a place to store per-user security information. Again, this place needs to be outside the untrusted space. Examples: [Windows] * VM+image location: "C:\Program Files\Squeak\" * secure directory location: "C:\Program Files\Squeak\username\" * untrusted user directory: "C:\My Squeak\username\" [Unix] * VM+image location: "/user/local/squeak" * secure directory location: "~username/.squeak/ * untrusted user directory: "~username/squeak/" [Mac] * plugin VM location: "MacHD:Netscape:Plugins:" * standalone VM and image location: "MacHD:Squeak:" * secure directory location: "MacHD:Squeak:username:" * untrusted user directory: "MacHD:My Squeak:username:" Restoring the rights revoked by an image might be possible by some interaction with the VM directly. Any such action should be preceeded by a BIG FAT WARNING - the average user will never need that ability (if she does, we did something wrong) so this is a last resort in cases where something fundamtally tricky happened. Note that ioInitSecurity needs to be called from the VM directly (after the image has loaded but before running it). It needs to establish both, the untrusted and the secure user directory. Later we might think about manually changing it (which is possible if the VM is still in trusted mode) but for now we don't. ! !AsynchFilePlugin methodsFor: 'primitives' stamp: 'ar 2/6/2001 14:03'! primitiveAsyncFileOpen: fileName forWrite: writeFlag semaIndex: semaIndex | fileNameSize fOop f | self var: #f declareC: 'AsyncFile *f'. self primitive: 'primitiveAsyncFileOpen' parameters: #(String Boolean SmallInteger ). fileNameSize _ interpreterProxy slotSizeOf: (fileName asOop: String). (self ioCanOpenAsyncFile: fileName OfSize: fileNameSize Writable: writeFlag) ifFalse:[^interpreterProxy primitiveFail]. fOop _ interpreterProxy instantiateClass: interpreterProxy classByteArray indexableSize: (self cCode: 'sizeof(AsyncFile)'). f _ self asyncFileValueOf: fOop. interpreterProxy failed ifFalse: [self cCode: 'asyncFileOpen(f, (int)fileName, fileNameSize, writeFlag, semaIndex)']. ^ fOop! ! !AsynchFilePlugin class methodsFor: 'translation' stamp: 'ar 2/6/2001 14:04'! headerFile ^'/* Header file for AsynchFile plugin */ /* module initialization/shutdown */ int asyncFileInit(void); int asyncFileShutdown(void); /*** Experimental Asynchronous File I/O ***/ typedef struct { int sessionID; void *state; } AsyncFile; int asyncFileClose(AsyncFile *f); int asyncFileOpen(AsyncFile *f, int fileNamePtr, int fileNameSize, int writeFlag, int semaIndex); int asyncFileRecordSize(); int asyncFileReadResult(AsyncFile *f, int bufferPtr, int bufferSize); int asyncFileReadStart(AsyncFile *f, int fPosition, int count); int asyncFileWriteResult(AsyncFile *f); int asyncFileWriteStart(AsyncFile *f, int fPosition, int bufferPtr, int bufferSize); /*** security traps ***/ /* following is equivalent ioCanOpenFileOfSize() and should really be handled from there */ int ioCanOpenAsyncFileOfSizeWritable(char* fileNameIndex, int fileNameSize, int writeFlag); #ifdef DISABLE_SECURITY #define ioCanOpenAsyncFileOfSizeWritable(index, size, flag) 1 #endif '! ! !FilePlugin methodsFor: 'file primitives' stamp: 'ar 2/5/2001 18:09'! primitiveFileDelete | namePointer nameIndex nameSize | self var: 'nameIndex' type: 'char *'. self export: true. namePointer _ interpreterProxy stackValue: 0. (interpreterProxy isBytes: namePointer) ifFalse:[^interpreterProxy primitiveFail]. nameIndex _ interpreterProxy firstIndexableField: namePointer. nameSize _ interpreterProxy byteSizeOf: namePointer. (self ioCanDeleteFile: nameIndex OfSize: nameSize) ifFalse:[^interpreterProxy primitiveFail]. self sqFileDeleteName: (self cCoerce: nameIndex to: 'int') Size: nameSize. interpreterProxy failed ifFalse:[interpreterProxy pop: 1. "pop name, leave rcvr on stack" ]. ! ! !FilePlugin methodsFor: 'file primitives' stamp: 'ar 2/5/2001 18:09'! primitiveFileOpen | writeFlag namePointer filePointer file nameIndex nameSize | self var: 'file' declareC: 'SQFile *file'. self var: 'nameIndex' type:'char *'. self export: true. writeFlag _ interpreterProxy booleanValueOf: (interpreterProxy stackValue: 0). namePointer _ interpreterProxy stackValue: 1. (interpreterProxy isBytes: namePointer) ifFalse:[^interpreterProxy primitiveFail]. filePointer _ interpreterProxy instantiateClass: (interpreterProxy classByteArray) indexableSize: self fileRecordSize. file _ self fileValueOf: filePointer. nameIndex _ interpreterProxy firstIndexableField: namePointer. nameSize _ interpreterProxy byteSizeOf: namePointer. (self ioCanOpenFile: nameIndex OfSize: nameSize Writable: writeFlag) ifFalse:[^interpreterProxy primitiveFail]. interpreterProxy failed ifFalse:[ self cCode: 'sqFileOpen(file, (int)nameIndex, nameSize, writeFlag)'. ]. interpreterProxy failed ifFalse:[ interpreterProxy pop: 3. "rcvr, name, writeFlag" interpreterProxy push: filePointer. ].! ! !FilePlugin methodsFor: 'file primitives' stamp: 'ar 2/5/2001 18:10'! primitiveFileRename | oldNamePointer newNamePointer oldNameIndex oldNameSize newNameIndex newNameSize | self var: 'oldNameIndex' type: 'char *'. self var: 'newNameIndex' type: 'char *'. self export: true. newNamePointer _ interpreterProxy stackValue: 0. oldNamePointer _ interpreterProxy stackValue: 1. ((interpreterProxy isBytes: newNamePointer) and:[ (interpreterProxy isBytes: oldNamePointer)]) ifFalse:[^interpreterProxy primitiveFail]. newNameIndex _ interpreterProxy firstIndexableField: newNamePointer. newNameSize _ interpreterProxy byteSizeOf: newNamePointer. oldNameIndex _ interpreterProxy firstIndexableField: oldNamePointer. oldNameSize _ interpreterProxy byteSizeOf: oldNamePointer. (self ioCanRenameFile: oldNameIndex OfSize: oldNameSize) ifFalse:[^interpreterProxy primitiveFail]. self sqFileRenameOld: (self cCoerce: oldNameIndex to: 'int') Size: oldNameSize New: (self cCoerce: newNameIndex to: 'int') Size: newNameSize. interpreterProxy failed ifFalse:[ interpreterProxy pop: 2. "pop new and old names, leave rcvr on stack" ].! ! !FilePlugin methodsFor: 'directory primitives' stamp: 'ar 2/6/2001 12:55'! primitiveDirectoryCreate | dirName dirNameIndex dirNameSize | self var: #dirNameIndex type: 'char *'. self export: true. dirName _ interpreterProxy stackValue: 0. (interpreterProxy isBytes: dirName) ifFalse:[^interpreterProxy primitiveFail]. dirNameIndex _ interpreterProxy firstIndexableField: dirName. dirNameSize _ interpreterProxy byteSizeOf: dirName. (self ioCanCreatePath: dirNameIndex OfSize: dirNameSize) ifFalse:[^interpreterProxy primitiveFail]. (self cCode: 'dir_Create((char *) dirNameIndex, dirNameSize)' inSmalltalk:[false]) ifFalse:[^interpreterProxy primitiveFail]. interpreterProxy pop: 1. "pop dirName; leave rcvr on stack"! ! !FilePlugin methodsFor: 'directory primitives' stamp: 'ar 2/5/2001 18:04'! primitiveDirectoryDelete | dirName dirNameIndex dirNameSize | self var: #dirNameIndex type: 'char *'. self export: true. dirName _ interpreterProxy stackValue: 0. (interpreterProxy isBytes: dirName) ifFalse:[^interpreterProxy primitiveFail]. dirNameIndex _ interpreterProxy firstIndexableField: dirName. dirNameSize _ interpreterProxy byteSizeOf: dirName. (self ioCanDeletePath: dirNameIndex OfSize: dirNameSize) ifFalse:[^interpreterProxy primitiveFail]. (self cCode: 'dir_Delete((char *) dirNameIndex, dirNameSize)' inSmalltalk:[false]) ifFalse:[^interpreterProxy primitiveFail]. interpreterProxy pop: 1. "pop dirName; leave rcvr on stack"! ! !FilePlugin methodsFor: 'directory primitives' stamp: 'ar 2/5/2001 18:14'! primitiveDirectoryGetMacTypeAndCreator | creatorString typeString fileName creatorStringIndex typeStringIndex fileNameIndex fileNameSize | self var: 'creatorStringIndex' type: 'char *'. self var: 'typeStringIndex' type: 'char *'. self var: 'fileNameIndex' type: 'char *'. self export: true. creatorString _ interpreterProxy stackValue: 0. typeString _ interpreterProxy stackValue: 1. fileName _ interpreterProxy stackValue: 2. ((interpreterProxy isBytes: creatorString) and: [(interpreterProxy byteSizeOf: creatorString) = 4]) ifFalse:[^interpreterProxy primitiveFail]. ((interpreterProxy isBytes: typeString) and: [(interpreterProxy byteSizeOf: typeString) = 4]) ifFalse:[^interpreterProxy primitiveFail]. (interpreterProxy isBytes: fileName) ifFalse:[^interpreterProxy primitiveFail]. creatorStringIndex _ interpreterProxy firstIndexableField: creatorString. typeStringIndex _ interpreterProxy firstIndexableField: typeString. fileNameIndex _ interpreterProxy firstIndexableField: fileName. fileNameSize _ interpreterProxy byteSizeOf: fileName. (self ioCanGetFileType: fileNameIndex OfSize: fileNameSize) ifFalse:[^interpreterProxy primitiveFail]. (self cCode: 'dir_GetMacFileTypeAndCreator( (char *) fileNameIndex, fileNameSize, (char *) typeStringIndex, (char *) creatorStringIndex)' inSmalltalk:[true]) ifFalse:[^interpreterProxy primitiveFail]. interpreterProxy pop: 3. "pop filename, type, creator; leave rcvr on stack" ! ! !FilePlugin methodsFor: 'directory primitives' stamp: 'ar 2/5/2001 18:07'! primitiveDirectoryLookup | index pathName pathNameIndex pathNameSize status entryName entryNameSize createDate modifiedDate dirFlag fileSize | self var: 'entryName' declareC: 'char entryName[256]'. self var: 'pathNameIndex' type: 'char *'. self export: true. index _ interpreterProxy stackIntegerValue: 0. pathName _ interpreterProxy stackValue: 1. (interpreterProxy isBytes: pathName) ifFalse:[^interpreterProxy primitiveFail]. pathNameIndex _ interpreterProxy firstIndexableField: pathName. pathNameSize _ interpreterProxy byteSizeOf: pathName. (self ioCanListPath: pathNameIndex OfSize: pathNameSize) ifTrue:[ status _ self cCode: 'dir_Lookup( (char *) pathNameIndex, pathNameSize, index, entryName, &entryNameSize, &createDate, &modifiedDate, &dirFlag, &fileSize)'. ] ifFalse:[ status _ DirNoMoreEntries. ]. interpreterProxy failed ifTrue:[^nil]. status = DirNoMoreEntries ifTrue: [ "no more entries; return nil" interpreterProxy pop: 3. "pop pathName, index, rcvr" interpreterProxy push: interpreterProxy nilObject. ^ nil ]. status = DirBadPath ifTrue: [ ^ interpreterProxy primitiveFail ]. "bad path" interpreterProxy pop: 3. "pop pathName, index, rcvr" interpreterProxy push: (self makeDirEntryName: entryName size: entryNameSize createDate: createDate modDate: modifiedDate isDir: dirFlag fileSize: fileSize).! ! !FilePlugin methodsFor: 'directory primitives' stamp: 'ar 2/5/2001 18:08'! primitiveDirectorySetMacTypeAndCreator | creatorString typeString fileName creatorStringIndex typeStringIndex fileNameIndex fileNameSize | self var: 'creatorStringIndex' type: 'char *'. self var: 'typeStringIndex' type: 'char *'. self var: 'fileNameIndex' type: 'char *'. self export: true. creatorString _ interpreterProxy stackValue: 0. typeString _ interpreterProxy stackValue: 1. fileName _ interpreterProxy stackValue: 2. ((interpreterProxy isBytes: creatorString) and: [(interpreterProxy byteSizeOf: creatorString) = 4]) ifFalse:[^interpreterProxy primitiveFail]. ((interpreterProxy isBytes: typeString) and: [(interpreterProxy byteSizeOf: typeString) = 4]) ifFalse:[^interpreterProxy primitiveFail]. (interpreterProxy isBytes: fileName) ifFalse:[^interpreterProxy primitiveFail]. creatorStringIndex _ interpreterProxy firstIndexableField: creatorString. typeStringIndex _ interpreterProxy firstIndexableField: typeString. fileNameIndex _ interpreterProxy firstIndexableField: fileName. fileNameSize _ interpreterProxy byteSizeOf: fileName. (self ioCanSetFileType: fileNameIndex OfSize: fileNameSize) ifFalse:[^interpreterProxy primitiveFail]. (self cCode: 'dir_SetMacFileTypeAndCreator( (char *) fileNameIndex, fileNameSize, (char *) typeStringIndex, (char *) creatorStringIndex)' inSmalltalk:[true]) ifFalse:[^interpreterProxy primitiveFail]. interpreterProxy pop: 3. "pop filename, type, creator; leave rcvr on stack" ! ! !FilePlugin methodsFor: 'security primitives' stamp: 'ar 2/6/2001 14:00'! primitiveDisableFileAccess self export: true. self ioDisableFileAccess. interpreterProxy failed ifFalse:[interpreterProxy pop: 1].! ! !FilePlugin methodsFor: 'security primitives' stamp: 'ar 2/6/2001 14:01'! primitiveHasFileAccess self export: true. interpreterProxy pop: 1. interpreterProxy pushBool: self ioHasFileAccess.! ! !FilePlugin class methodsFor: 'translation' stamp: 'ar 2/6/2001 14:00'! headerFile ^'/* File support definitions */ /* squeak file record; see sqFilePrims.c for details */ typedef struct { FILE *file; int sessionID; int writable; int fileSize; int lastOp; /* 0 = uncommitted, 1 = read, 2 = write */ } SQFile; /* file i/o */ int sqFileAtEnd(SQFile *f); int sqFileClose(SQFile *f); int sqFileDeleteNameSize(int sqFileNameIndex, int sqFileNameSize); int sqFileGetPosition(SQFile *f); int sqFileInit(void); int sqFileShutdown(void); int sqFileOpen(SQFile *f, int sqFileNameIndex, int sqFileNameSize, int writeFlag); int sqFileReadIntoAt(SQFile *f, int count, int byteArrayIndex, int startIndex); int sqFileRenameOldSizeNewSize(int oldNameIndex, int oldNameSize, int newNameIndex, int newNameSize); int sqFileSetPosition(SQFile *f, int position); int sqFileSize(SQFile *f); int sqFileValid(SQFile *f); int sqFileWriteFromAt(SQFile *f, int count, int byteArrayIndex, int startIndex); /* directories */ int dir_Create(char *pathString, int pathStringLength); int dir_Delete(char *pathString, int pathStringLength); int dir_Delimitor(void); int dir_Lookup(char *pathString, int pathStringLength, int index, /* outputs: */ char *name, int *nameLength, int *creationDate, int *modificationDate, int *isDirectory, int *sizeIfFile); int dir_PathToWorkingDir(char *pathName, int pathNameMax); int dir_SetMacFileTypeAndCreator(char *filename, int filenameSize, char *fType, char *fCreator); int dir_GetMacFileTypeAndCreator(char *filename, int filenameSize, char *fType, char *fCreator); /*** security traps ***/ /* directory access */ int ioCanCreatePathOfSize(char* dirNameIndex, int dirNameSize); int ioCanListPathOfSize(char* dirNameIndex, int dirNameSize); int ioCanDeletePathOfSize(char* dirNameIndex, int dirNameSize); /* file access */ int ioCanOpenFileOfSizeWritable(char* fileNameIndex, int fileNameSize, int writeFlag); int ioCanDeleteFileOfSize(char* fileNameIndex, int fileNameSize); int ioCanRenameFileOfSize(char* fileNameIndex, int fileNameSize); int ioCanGetFileTypeOfSize(char* fileNameIndex, int fileNameSize); int ioCanSetFileTypeOfSize(char* fileNameIndex, int fileNameSize); /* top level functions */ int ioDisableFileAccess(void); int ioHasFileAccess(void); #ifdef DISABLE_SECURITY #define ioCanCreatePathOfSize(name, size) 1 #define ioCanListPathOfSize(name, size) 1 #define ioCanDeletePathOfSize(name, size) 1 #define ioCanOpenFileOfSizeWritable(name, size, writeFlag) 1 #define ioCanDeleteFileOfSize(name, size) 1 #define ioCanRenameFileOfSize(name, size) 1 #define ioCanGetFileTypeOfSize(name, size) 1 #define ioCanSetFileTypeOfSize(name, size) 1 #define ioDisableFileAccess() 1 #define ioHasFileAccess() 1 #endif /* DISABLE_SECURITY */ '.! ! !FilePluginSimulator methodsFor: 'file security' stamp: 'ar 2/5/2001 19:23'! ioCanCreatePath: dirNameIndex OfSize: dirNameSize "Return true if we're allowed to create a directory with the given name" ^true! ! !FilePluginSimulator methodsFor: 'file security' stamp: 'ar 2/5/2001 18:16'! ioCanDeleteFile: nameIndex OfSize: nameSize "Return true if we're allowed to delete the file with the given name" ^true! ! !FilePluginSimulator methodsFor: 'file security' stamp: 'ar 2/5/2001 18:16'! ioCanDeletePath: dirNameIndex OfSize: dirNameSize "Return true if we're allowed to delete the directory with the given name" ^true! ! !FilePluginSimulator methodsFor: 'file security' stamp: 'ar 2/5/2001 18:16'! ioCanGetFileType: fileNameIndex OfSize: fileNameSize "Return true if we're allowed to retrieve the (mac) file type of the given file." ^true! ! !FilePluginSimulator methodsFor: 'file security' stamp: 'ar 2/5/2001 18:17'! ioCanListPath: pathNameIndex OfSize: pathNameSize "Return true if we're allowed to list the contents of the given directory" ^true! ! !FilePluginSimulator methodsFor: 'file security' stamp: 'ar 2/5/2001 18:17'! ioCanOpenFile: nameIndex OfSize: nameSize Writable: writeFlag "Return true if we're allowed to open the given file (possibly in write mode)" ^true! ! !FilePluginSimulator methodsFor: 'file security' stamp: 'ar 2/5/2001 18:17'! ioCanRenameFile: oldNameIndex OfSize: oldNameSize "Return true if we're allowed to rename the given file" ^true! ! !FilePluginSimulator methodsFor: 'file security' stamp: 'ar 2/5/2001 18:18'! ioCanSetFileType: fileNameIndex OfSize: fileNameSize "Return true if we're allowed to set the (mac) file type and creator on the given file" ^true! ! !Interpreter methodsFor: 'I/O primitives' stamp: 'ar 2/5/2001 17:24'! primitiveScreenDepth "Return a SmallInteger indicating the current depth of the OS screen" | depth | self export: true. depth _ self ioScreenDepth. (self failed or:[depth <= 0]) ifTrue:[^self primitiveFail]. self pop: 1. self pushInteger: depth.! ! !Interpreter methodsFor: 'other primitives' stamp: 'ar 2/5/2001 18:31'! primitiveImageName "When called with a single string argument, record the string as the current image file name. When called with zero arguments, return a string containing the current image file name." | s sz | argumentCount = 1 ifTrue: [ self ioCanRenameImage ifFalse:[^self primitiveFail]. s _ self stackTop. self assertClassOf: s is: (self splObj: ClassString). successFlag ifTrue: [ sz _ self stSizeOf: s. self imageNamePut: (s + BaseHeaderSize) Length: sz. self pop: 1. "pop s, leave rcvr on stack" ]. ] ifFalse: [ sz _ self imageNameSize. s _ self instantiateClass: (self splObj: ClassString) indexableSize: sz. self imageNameGet: (s + BaseHeaderSize) Length: sz. self pop: 1. "rcvr" self push: s. ]. ! ! !Interpreter methodsFor: 'image save/restore' stamp: 'ar 2/5/2001 19:21'! writeImageFileIO: imageBytes | headerStart headerSize f bytesWritten | self var: #f declareC: 'sqImageFile f'. self ioCanWriteImage ifFalse:[^self primitiveFail]. "local constants" headerStart _ 0. headerSize _ 64. "header size in bytes; do not change!!" f _ self cCode: 'sqImageFileOpen(imageName, "wb")'. f = nil ifTrue: [ "could not open the image file for writing" self success: false. ^ nil]. headerStart _ self cCode: 'sqImageFileStartLocation(f,imageName,headerSize+imageBytes)'. self cCode: '/* Note: on Unix systems one could put an exec command here, padded to 512 bytes */'. "position file to start of header" self sqImageFile: f Seek: headerStart. self putLong: (self imageFormatVersion) toFile: f. self putLong: headerSize toFile: f. self putLong: imageBytes toFile: f. self putLong: (self startOfMemory) toFile: f. self putLong: specialObjectsOop toFile: f. self putLong: lastHash toFile: f. self putLong: (self ioScreenSize) toFile: f. self putLong: fullScreenFlag toFile: f. self putLong: extraVMMemory toFile: f. 1 to: 7 do: [:i | self putLong: 0 toFile: f]. "fill remaining header words with zeros" successFlag ifFalse: [ "file write or seek failure" self cCode: 'sqImageFileClose(f)'. ^ nil]. "position file after the header" self sqImageFile: f Seek: headerStart + headerSize. "write the image data" bytesWritten _ self cCode: 'sqImageFileWrite(memory, sizeof(unsigned char), imageBytes, f)'. self success: bytesWritten = imageBytes. self cCode: 'sqImageFileClose(f)'. ! ! !Interpreter class methodsFor: 'translation' stamp: 'ar 2/5/2001 22:18'! translate: fileName doInlining: inlineFlag forBrowserPlugin: pluginFlag "Note: The pluginFlag is meaningless on Windows and Unix. On these platforms Squeak runs as it's own process and doesn't need any special attention from the VMs point of view. Meaning that NONE of the required additional functions will be supported. In other words, the pluginFlag is not needed and not supported." "Translate the Smalltalk description of the virtual machine into C. If inlineFlag is true, small method bodies are inlined to reduce procedure call overhead. On the PPC, this results in a factor of three speedup with only 30% increase in code size. If pluginFlag is true, generate code for an interpreter that runs as a browser plugin (Netscape or IE)." | doInlining cg exports | doInlining _ inlineFlag. pluginFlag ifTrue: [doInlining _ true]. "must inline when generating browser plugin" Interpreter initialize. ObjectMemory initialize. GenerateBrowserPlugin _ pluginFlag. cg _ CCodeGenerator new initialize. cg addClass: Interpreter. cg addClass: ObjectMemory. Interpreter declareCVarsIn: cg. ObjectMemory declareCVarsIn: cg. "Get all the named prims from the VM. Note: the format of exports is: pluginName -> Array of: primitiveName. so we can generate a nice table from it." exports _ Array with: '' -> cg exportedPrimitiveNames asArray. cg storeCodeOnFile: fileName doInlining: doInlining. "Add our plugins" { "Graphics" "Note: BitBltSimulation should go first, because three of it's entries might be looked up quite often (due to refs from InterpreterProxy). This will go away at some point but for now it's a good idea to have those entries early in the table." BitBltSimulation. BalloonEnginePlugin. SurfacePlugin. "To support OS surfaces through FXBlt" "I/O subsystems" FilePlugin. SocketPlugin. MIDIPlugin. SerialPlugin. JoystickTabletPlugin. AsynchFilePlugin. "Sound" SoundPlugin. SoundGenerationPlugin. ADPCMCodecPlugin. KlattSynthesizerPlugin. SoundCodecPlugin. "Numerics" LargeIntegersPlugin. FFTPlugin. FloatArrayPlugin. Matrix2x3Plugin. "Compression" DeflatePlugin. "Others" B3DEnginePlugin. DSAPlugin. DropPlugin. MiscPrimitivePlugin. SecurityPlugin. "Note: Optionally, you can translate the following as builtins. As of Squeak 2.7 they are not builtins by default: FFIPlugin. " } do:[:plugin| cg _ plugin translate: plugin moduleName, '.c' doInlining: doInlining locally: true. exports _ exports copyWith: (plugin moduleName -> cg exportedPrimitiveNames asArray). ]. self storeExports: exports on: 'sqNamedPrims.h'.! ! !InterpreterSimulator methodsFor: 'security' stamp: 'ar 2/5/2001 18:33'! ioCanRenameImage ^true! ! !InterpreterSimulator methodsFor: 'security' stamp: 'ar 2/5/2001 20:42'! ioCanWriteImage ^true! ! !InterpreterSupportCode class methodsFor: 'source file exporting' stamp: 'ar 2/6/2001 14:07'! writeSupportFiles "Store into this image's folder the C sources files required to support the interpreter on all platforms. This method also generates the code for the sound synthesis and other primitives translated from Smalltalk to C. However, because generating code for the interpreter itself takes several minutes, that is not done automatically by this method. To generate that code, use the method 'translate:doInlining:' in Interpreter class." "InterpreterSupportCode writeSupportFiles" self storeString: self readmeFile onFileNamed: 'readme'. self storeString: self squeakHeaderFile onFileNamed: 'sq.h'. self storeString: self squeakConfigFile onFileNamed: 'sqConfig.h'. self storeString: self squeakPlatformExportsFile onFileNamed: 'platform.exports'. self storeString: self squeakPlatSpecFile onFileNamed: 'sqPlatformSpecific.h'. self storeString: self squeakVirtualMachineHeaderFile onFileNamed: 'sqVirtualMachine.h'. self storeString: self squeakVirtualMachineFile onFileNamed: 'sqVirtualMachine.c'. self storeString: self squeakNamedPrimsFile onFileNamed:'sqNamedPrims.c'. self storeString: self squeakFilePrimsFile onFileNamed: 'sqFilePrims.c'.! ! !InterpreterSupportCode class methodsFor: 'source files' stamp: 'ar 2/6/2001 14:21'! squeakHeaderFile ^'#include #include #include #include #include #include "sqConfig.h" #include "sqVirtualMachine.h" #define true 1 #define false 0 #define null 0 /* using "null" because nil is predefined in Think C */ /* pluggable primitives macros */ /* Note: All pluggable primitives are defined as EXPORT(int) somePrimitive(void) If the platform requires special declaration modifiers the EXPORT macro can be redefined */ #define EXPORT(returnType) returnType /* image save/restore macros */ /* Note: The image file save and restore code uses these macros; they can be redefined in sqPlatformSpecific.h if desired. These default versions are defined in terms of the ANSI Standard C libraries. */ #define sqImageFile FILE * #define sqImageFileClose(f) fclose(f) #define sqImageFileOpen(fileName, mode) fopen(fileName, mode) #define sqImageFilePosition(f) ftell(f) #define sqImageFileRead(ptr, sz, count, f) fread(ptr, sz, count, f) #define sqImageFileSeek(f, pos) fseek(f, pos, SEEK_SET) #define sqImageFileWrite(ptr, sz, count, f) fwrite(ptr, sz, count, f) #define sqImageFileStartLocation(fileRef, fileName, size) 0 #define sqAllocateMemory(minHeapSize, desiredHeapSize) malloc(desiredHeapSize) /* platform-dependent float conversion macros */ /* Note: Second argument must be a variable name, not an expression!! */ /* Note: Floats in image are always in PowerPC word order; change these macros to swap words if necessary. This costs no extra and obviates sometimes having to word-swap floats when reading an image. */ #if defined(DOUBLE_WORD_ALIGNMENT) || defined(DOUBLE_WORD_ORDER) # ifdef DOUBLE_WORD_ORDER /* word-based copy with swapping for non-PowerPC order */ # define storeFloatAtfrom(i, floatVarName) \ *((int *) (i) + 0) = *((int *) &(floatVarName) + 1); \ *((int *) (i) + 1) = *((int *) &(floatVarName) + 0); # define fetchFloatAtinto(i, floatVarName) \ *((int *) &(floatVarName) + 0) = *((int *) (i) + 1); \ *((int *) &(floatVarName) + 1) = *((int *) (i) + 0); # else /*!!DOUBLE_WORD_ORDER*/ /* word-based copy for machines with alignment restrictions */ # define storeFloatAtfrom(i, floatVarName) \ *((int *) (i) + 0) = *((int *) &(floatVarName) + 0); \ *((int *) (i) + 1) = *((int *) &(floatVarName) + 1); # define fetchFloatAtinto(i, floatVarName) \ *((int *) &(floatVarName) + 0) = *((int *) (i) + 0); \ *((int *) &(floatVarName) + 1) = *((int *) (i) + 1); # endif /*!!DOUBLE_WORD_ORDER*/ #else /*!!(DOUBLE_WORD_ORDER||DOUBLE_WORD_ALIGNMENT)*/ /* for machines that allow doubles to be on any word boundary */ # define storeFloatAtfrom(i, floatVarName) \ *((double *) (i)) = (floatVarName); # define fetchFloatAtinto(i, floatVarName) \ (floatVarName) = *((double *) (i)); #endif /* platform-dependent memory size adjustment macro */ /* Note: This macro can be redefined to allows platforms with a fixed application memory partition (notably, the Macintosh) to reserve extra C heap memory for special applications that need it (e.g., for a 3D graphics library). Since most platforms can extend their application memory partition at run time if needed, this macro is defined as a noop here and redefined if necessary in sqPlatformSpecific.h. */ #define reserveExtraCHeapBytes(origHeapSize, bytesToReserve) origHeapSize /* platform-dependent millisecond clock macros */ /* Note: The Squeak VM uses three different clocks functions for timing. The primary one, ioMSecs(), is used to implement Delay and Time millisecondClockValue. The resolution of this clock determines the resolution of these basic timing functions. For doing real-time control of music and MIDI, a clock with resolution down to one millisecond is preferred, but a coarser clock (say, 1/60th second) can be used in a pinch. The VM calls a different clock function, ioLowResMSecs(), in order to detect long-running primitives. This function must be inexpensive to call because when a Delay is active it is polled twice per primitive call. On several platforms (Mac, Win32), the high-resolution system clock used in ioMSecs() would incur enough overhead in this case to slow down the the VM significantly. Thus, a cheaper clock with low resolution is used to implement ioLowResMSecs() on these platforms. Finally, the function ioMicroMSecs() is used only to collect timing statistics for the garbage collector and other VM facilities. (The function name is meant to suggest that the function is based on a clock with microsecond accuracy, even though the times it returns are in units of milliseconds.) This clock must have enough precision to provide accurate timings, and normally isn''t called frequently enough to slow down the VM. Thus, it can use a more expensive clock that ioMSecs(). By default, all three clock functions are defined here as macros based on the standard C library function clock(). Any of these macros can be overridden in sqPlatformSpecific.h. */ int ioMSecs(void); int ioLowResMSecs(void); int ioMicroMSecs(void); #define ioMSecs() ((1000 * clock()) / CLOCKS_PER_SEC) #define ioLowResMSecs() ((1000 * clock()) / CLOCKS_PER_SEC) #define ioMicroMSecs() ((1000 * clock()) / CLOCKS_PER_SEC) /* filename copy/transform macro. An opportunity to transform the filenames for platforms with strange needs, anda simple encapsulation for everyone else */ #define sqFilenameFromString(dst, src, num) \ if (1) { \ int i; \ for (i = 0; i < num; i++) { \ dst[i] = *((char *) (src + i)); \ } \ dst[num] = 0;\ } /* this include file may redefine earlier definitions and macros: */ #include "sqPlatformSpecific.h" /* interpreter entry points */ void error(char *s); int checkedByteAt(int byteAddress); int checkedByteAtput(int byteAddress, int byte); int checkedLongAt(int byteAddress); int checkedLongAtput(int byteAddress, int a32BitInteger); int fullDisplayUpdate(void); int initializeInterpreter(int bytesToShift); int interpret(void); int primitiveFail(void); int signalSemaphoreWithIndex(int index); int success(int); /* display, mouse, keyboard, time i/o */ int ioBeep(void); int ioExit(void); int ioForceDisplayUpdate(void); int ioFormPrint( int bitsAddr, int width, int height, int depth, double hScale, double vScale, int landscapeFlag); int ioSetFullScreen(int fullScreen); int ioRelinquishProcessorForMicroseconds(int microSeconds); int ioScreenSize(void); int ioScreenDepth(void); int ioSeconds(void); int ioSetCursor(int cursorBitsIndex, int offsetX, int offsetY); int ioSetCursorWithMask(int cursorBitsIndex, int cursorMaskIndex, int offsetX, int offsetY); int ioShowDisplay( int dispBitsIndex, int width, int height, int depth, int affectedL, int affectedR, int affectedT, int affectedB); int ioHasDisplayDepth(int depth); int ioSetDisplayMode(int width, int height, int depth, int fullscreenFlag); /* Power Management */ int ioDisablePowerManager(int disableIfNonZero); /* User input recording I: In general, either set of input function can be supported, depending on the platform. This (first) set is state based and should be supported even on platforms that make use of the newer event driven API to support older images without event support. */ int ioGetButtonState(void); int ioGetKeystroke(void); int ioMousePoint(void); int ioPeekKeystroke(void); /* Note: In an event driven architecture, ioProcessEvents is obsolete. It can be implemented as a no-op since the image will check for events in regular intervals. */ int ioProcessEvents(void); /* User input recording II: The following functions and definition can be used on platform supporting events directly. */ /* types of events */ #define EventTypeNone 0 #define EventTypeMouse 1 #define EventTypeKeyboard 2 #define EventTypeDragDropFiles 3 /* keypress state for keyboard events */ #define EventKeyChar 0 #define EventKeyDown 1 #define EventKeyUp 2 /* button definitions */ #define RedButtonBit 4 #define BlueButtonBit 2 #define YellowButtonBit 1 /* modifier definitions */ #define ShiftKeyBit 1 #define CtrlKeyBit 2 #define OptionKeyBit 4 #define CommandKeyBit 8 /* generic input event definition */ typedef struct sqInputEvent { int type; /* type of event; either one of EventTypeXXX */ unsigned int timeStamp; /* time stamp */ /* the interpretation of the following fields depend on the type of the event */ int unused1; int unused2; int unused3; int unused4; int unused5; int unused6; } sqInputEvent; /* mouse input event definition */ typedef struct sqMouseEvent { int type; /* EventTypeMouse */ unsigned int timeStamp; /* time stamp */ int x; /* mouse position x */ int y; /* mouse position y */ int buttons; /* combination of xxxButtonBit */ int modifiers; /* combination of xxxKeyBit */ int reserved1; /* reserved for future use */ int reserved2; /* reserved for future use */ } sqMouseEvent; /* keyboard input event definition */ typedef struct sqKeyboardEvent { int type; /* EventTypeKeyboard */ unsigned int timeStamp; /* time stamp */ int charCode; /* character code in Mac Roman encoding */ int pressCode; /* press code; any of EventKeyXXX */ int modifiers; /* combination of xxxKeyBit */ int reserved1; /* reserved for future use */ int reserved2; /* reserved for future use */ int reserved3; /* reserved for future use */ } sqKeyboardEvent; /* drop files event definition: DragEnter - drag operation from OS entered Squeak window DragMove - drag operation from OS moved within Squeak window DragLeave - drag operation from OS left Squeak window DragDrop - drag operation dropped contents onto Squeak. */ #define DragEnter 1 #define DragMove 2 #define DragLeave 3 #define DragDrop 4 typedef struct sqDragDropFilesEvent { int type; /* EventTypeDropFiles */ unsigned int timeStamp; /* time stamp */ int dragType; /* one of the DragXXX constants */ int x; /* mouse position x */ int y; /* mouse position y */ int modifiers; /* combination of xxxKeyBit */ int numFiles; /* number of files in transaction */ int reserved1; /* reserved for future use */ } sqDragDropFilesEvent; /* set an asynchronous input semaphore index for events */ int ioSetInputSemaphore(int semaIndex); /* retrieve the next input event from the OS */ int ioGetNextEvent(sqInputEvent *evt); /* image file and VM path names */ extern char imageName[]; int imageNameGetLength(int sqImageNameIndex, int length); int imageNamePutLength(int sqImageNameIndex, int length); int imageNameSize(void); int vmPathSize(void); int vmPathGetLength(int sqVMPathIndex, int length); /* image security traps */ int ioCanRenameImage(void); int ioCanWriteImage(void); int ioDisableImageWrite(void); #ifdef DISABLE_SECURITY # define ioCanRenameImage() 1 # define ioCanWriteImage() 1 # define ioDisableImageWrite() 1 #endif /* save/restore */ /* Read the image from the given file starting at the given image offset */ int readImageFromFileHeapSizeStartingAt(sqImageFile f, int desiredHeapSize, int imageOffset); /* NOTE: The following is obsolete - it is only provided for compatibility */ #define readImageFromFileHeapSize(f, s) readImageFromFileHeapSizeStartingAt(f,s,0) /* clipboard (cut/copy/paste) */ int clipboardSize(void); int clipboardReadIntoAt(int count, int byteArrayIndex, int startIndex); int clipboardWriteFromAt(int count, int byteArrayIndex, int startIndex); /* browser plug-in support */ int plugInAllowAccessToFilePath(char *pathString, int pathStringLength); void plugInForceTimeToReturn(void); int plugInInit(char *imageName); int plugInNotifyUser(char *msg); void plugInSetStartTime(void); int plugInShutdown(void); int plugInTimeToReturn(void); /* interpreter entry points needed by compiled primitives */ void * arrayValueOf(int arrayOop); int checkedIntegerValueOf(int intOop); void * fetchArrayofObject(int fieldIndex, int objectPointer); double fetchFloatofObject(int fieldIndex, int objectPointer); int fetchIntegerofObject(int fieldIndex, int objectPointer); double floatValueOf(int floatOop); int pop(int nItems); int pushInteger(int integerValue); int sizeOfSTArrayFromCPrimitive(void *cPtr); int storeIntegerofObjectwithValue(int fieldIndex, int objectPointer, int integerValue); /* profiling */ int clearProfile(void); int dumpProfile(void); int startProfiling(void); int stopProfiling(void); /* system attributes */ int attributeSize(int id); int getAttributeIntoLength(int id, int byteArrayIndex, int length); /*** pluggable primitive support ***/ /* NOTE: The following functions are those implemented by sqNamedPrims.c */ int ioLoadExternalFunctionOfLengthFromModuleOfLength( int functionNameIndex, int functionNameLength, int moduleNameIndex, int moduleNameLength); int ioUnloadModuleOfLength(int moduleNameIndex, int moduleNameLength); int ioLoadFunctionFrom(char *functionName, char *pluginName); int ioShutdownAllModules(void); int ioUnloadModule(char *); int ioUnloadModuleOfLength(int moduleNameIndex, int moduleNameLength); char *ioListBuiltinModule(int moduleIndex); char *ioListLoadedModule(int moduleIndex); /* The next two are FFI entries!! (implemented in sqNamedPrims.c as well) */ int ioLoadModuleOfLength(int moduleNameIndex, int moduleNameLength); int ioLoadSymbolOfLengthFromModule(int functionNameIndex, int functionNameLength, int moduleHandle); /* The next three functions must be implemented by sqXYZExternalPrims.c */ /* ioLoadModule: Load a module from disk. WARNING: this always loads a *new* module. Don''t even attempt to find a loaded one. WARNING: never primitiveFail() within, just return 0 */ int ioLoadModule(char *pluginName); /* ioFindExternalFunctionIn: Find the function with the given name in the moduleHandle. WARNING: never primitiveFail() within, just return 0. */ int ioFindExternalFunctionIn(char *lookupName, int moduleHandle); /* ioFreeModule: Free the module with the associated handle. WARNING: never primitiveFail() within, just return 0. */ int ioFreeModule(int moduleHandle); /* The Squeak version this interpreter was generated from */ extern const char *interpreterVersion; '! ! !SecurityPlugin methodsFor: 'primitives' stamp: 'ar 2/5/2001 20:56'! primitiveCanWriteImage self export: true. interpreterProxy pop: 1. interpreterProxy pushBool: self ioCanWriteImage.! ! !SecurityPlugin methodsFor: 'primitives' stamp: 'ar 2/6/2001 14:11'! primitiveDisableImageWrite self export: true. self ioDisableImageWrite. interpreterProxy failed ifFalse:[interpreterProxy pop: 1].! ! !SecurityPlugin methodsFor: 'primitives' stamp: 'ar 2/6/2001 00:33'! primitiveGetSecureUserDirectory "Primitive. Return the secure directory for the current user." | dirName dirLen dirOop dirPtr | self export: true. self var: #dirName type: 'char *'. self var: #dirPtr type: 'char *'. dirName _ self ioGetSecureUserDirectory. (dirName == nil or:[interpreterProxy failed]) ifTrue:[^interpreterProxy primitiveFail]. dirLen _ self strlen: dirName. dirOop _ interpreterProxy instantiateClass: interpreterProxy classString indexableSize: dirLen. interpreterProxy failed ifTrue:[^nil]. dirPtr _ interpreterProxy firstIndexableField: dirOop. 0 to: dirLen-1 do:[:i| dirPtr at: i put: (dirName at: i)]. interpreterProxy pop: 1. interpreterProxy push: dirOop.! ! !SecurityPlugin methodsFor: 'primitives' stamp: 'ar 2/6/2001 00:33'! primitiveGetUntrustedUserDirectory "Primitive. Return the untrusted user directory name." | dirName dirLen dirOop dirPtr | self export: true. self var: #dirName type: 'char *'. self var: #dirPtr type: 'char *'. dirName _ self ioGetUntrustedUserDirectory. (dirName == nil or:[interpreterProxy failed]) ifTrue:[^interpreterProxy primitiveFail]. dirLen _ self strlen: dirName. dirOop _ interpreterProxy instantiateClass: interpreterProxy classString indexableSize: dirLen. interpreterProxy failed ifTrue:[^nil]. dirPtr _ interpreterProxy firstIndexableField: dirOop. 0 to: dirLen-1 do:[:i| dirPtr at: i put: (dirName at: i)]. interpreterProxy pop: 1. interpreterProxy push: dirOop.! ! !SecurityPlugin class methodsFor: 'translation' stamp: 'ar 2/6/2001 14:14'! headerFile ^'/* security plugin header file */ /* image writing */ int ioDisableImageWrite(void); int ioCanWriteImage(void); /* untrusted and secure directory locations */ char *ioGetSecureUserDirectory(void); char *ioGetUntrustedUserDirectory(void); /* following must be called by the VM before interpret() */ int ioInitSecurity(void); '! ! !SocketPlugin methodsFor: 'primitives' stamp: 'ar 2/6/2001 13:43'! primitiveSocket: socket connectTo: address port: port | addr s | self var: #s declareC: 'SocketPtr s'. self primitive: 'primitiveSocketConnectToPort' parameters: #(Oop ByteArray SmallInteger). addr _ self netAddressToInt: (self cCoerce: address to: 'unsigned char *'). (self ioCanConnectTo: addr Port: port) ifFalse:[^interpreterProxy primitiveFail]. s _ self socketValueOf: socket. interpreterProxy failed ifFalse: [ self sqSocket: s ConnectTo: addr Port: port]! ! !SocketPlugin methodsFor: 'primitives' stamp: 'ar 2/6/2001 13:50'! primitiveSocket: socket listenOnPort: port "one part of the wierdass dual prim primitiveSocketListenOnPort which was warped by some demented evil person determined to twist the very nature of reality" | s | self var: #s declareC: 'SocketPtr s'. self primitive: 'primitiveSocketListenOnPort' parameters: #(Oop SmallInteger). s _ self socketValueOf: socket. (self ioCanListen: s OnPort: port) ifFalse:[^interpreterProxy primitiveFail]. self sqSocket: s ListenOnPort: port.! ! !SocketPlugin methodsFor: 'primitives' stamp: 'ar 2/6/2001 13:50'! primitiveSocket: socket listenOnPort: port backlogSize: backlog "second part of the wierdass dual prim primitiveSocketListenOnPort which was warped by some demented evil person determined to twist the very nature of reality" | s | self var: #s declareC: 'SocketPtr s'. self primitive: 'primitiveSocketListenOnPortBacklog' parameters: #(Oop SmallInteger SmallInteger). s _ self socketValueOf: socket. (self ioCanListen: s OnPort: port) ifFalse:[^interpreterProxy primitiveFail]. self sqSocket: s ListenOnPort: port BacklogSize: backlog.! ! !SocketPlugin methodsFor: 'primitives' stamp: 'ar 2/6/2001 13:47'! primitiveSocketCreateNetwork: netType type: socketType receiveBufferSize: recvBufSize sendBufSize: sendBufSize semaIndex: semaIndex | socketOop s | self var: #s declareC: 'SocketPtr s'. self primitive: 'primitiveSocketCreate' parameters: #(SmallInteger SmallInteger SmallInteger SmallInteger SmallInteger). (self ioCanCreateSocket: netType OfType: socketType) ifFalse:[^interpreterProxy primitiveFail]. socketOop _ interpreterProxy instantiateClass: interpreterProxy classByteArray indexableSize: self socketRecordSize. s _ self socketValueOf: socketOop. self sqSocket: s CreateNetType: netType SocketType: socketType RecvBytes: recvBufSize SendBytes: sendBufSize SemaID: semaIndex. ^socketOop! ! !SocketPlugin methodsFor: 'primitives' stamp: 'ar 2/6/2001 13:47'! primitiveSocketCreateNetwork: netType type: socketType receiveBufferSize: recvBufSize sendBufSize: sendBufSize semaIndex: semaIndex readSemaIndex: aReadSema writeSemaIndex: aWriteSema | socketOop s | self var: #s declareC: 'SocketPtr s'. self primitive: 'primitiveSocketCreate3Semaphores' parameters: #(SmallInteger SmallInteger SmallInteger SmallInteger SmallInteger SmallInteger SmallInteger). (self ioCanCreateSocket: netType OfType: socketType) ifFalse:[^interpreterProxy primitiveFail]. socketOop _ interpreterProxy instantiateClass: interpreterProxy classByteArray indexableSize: self socketRecordSize. s _ self socketValueOf: socketOop. self sqSocket: s CreateNetType: netType SocketType: socketType RecvBytes: recvBufSize SendBytes: sendBufSize SemaID: semaIndex ReadSemaID: aReadSema WriteSemaID: aWriteSema. ^socketOop! ! !SocketPlugin methodsFor: 'security primitives' stamp: 'ar 2/6/2001 14:09'! primitiveDisableSocketAccess self export: true. self ioDisableSocketAccess. interpreterProxy failed ifFalse:[interpreterProxy pop: 1].! ! !SocketPlugin methodsFor: 'security primitives' stamp: 'ar 2/6/2001 13:56'! primitiveHasSocketAccess self export: true. interpreterProxy pop: 1. interpreterProxy pushBool: self ioHasSocketAccess.! ! !SocketPlugin class methodsFor: 'translation' stamp: 'ar 2/6/2001 14:21'! headerFile ^'/* squeak socket record; see sqMacNetwork.c for details */ /* module initialization/shutdown */ int socketInit(void); int socketShutdown(void); typedef struct { int sessionID; int socketType; /* 0 = TCP, 1 = UDP */ void *privateSocketPtr; } SQSocket, *SocketPtr; /* networking primitives */ int sqNetworkInit(int resolverSemaIndex); void sqNetworkShutdown(void); void sqResolverAbort(void); void sqResolverAddrLookupResult(char *nameForAddress, int nameSize); int sqResolverAddrLookupResultSize(void); int sqResolverError(void); int sqResolverLocalAddress(void); int sqResolverNameLookupResult(void); void sqResolverStartAddrLookup(int address); void sqResolverStartNameLookup(char *hostName, int nameSize); int sqResolverStatus(void); void sqSocketAbortConnection(SocketPtr s); void sqSocketCloseConnection(SocketPtr s); int sqSocketConnectionStatus(SocketPtr s); void sqSocketConnectToPort(SocketPtr s, int addr, int port); void sqSocketCreateNetTypeSocketTypeRecvBytesSendBytesSemaID( SocketPtr s, int netType, int socketType, int recvBufSize, int sendBufSize, int semaIndex); void sqSocketCreateNetTypeSocketTypeRecvBytesSendBytesSemaIDReadSemaIDWriteSemaID( SocketPtr s, int netType, int socketType, int recvBufSize, int sendBufSize, int semaIndex, int readSemaIndex, int writeSemaIndex); void sqSocketDestroy(SocketPtr s); int sqSocketError(SocketPtr s); void sqSocketListenOnPort(SocketPtr s, int port); int sqSocketLocalAddress(SocketPtr s); int sqSocketLocalPort(SocketPtr s); int sqSocketReceiveDataAvailable(SocketPtr s); int sqSocketReceiveDataBufCount(SocketPtr s, int buf, int bufSize); int sqSocketRemoteAddress(SocketPtr s); int sqSocketRemotePort(SocketPtr s); int sqSocketSendDataBufCount(SocketPtr s, int buf, int bufSize); int sqSocketSendDone(SocketPtr s); /* ar 7/16/1999: New primitives for accept(). Note: If accept() calls are not supported simply make the calls fail and the old connection style will be used */ void sqSocketListenOnPortBacklogSize(SocketPtr s, int port, int backlogSize); void sqSocketAcceptFromRecvBytesSendBytesSemaID( SocketPtr s, SocketPtr serverSocket, int recvBufSize, int sendBufSize, int semaIndex); void sqSocketAcceptFromRecvBytesSendBytesSemaIDReadSemaIDWriteSemaID( SocketPtr s, SocketPtr serverSocket, int recvBufSize, int sendBufSize, int semaIndex, int readSemaIndex, int writeSemaIndex); int sqSocketReceiveUDPDataBufCountaddressportmoreFlag(SocketPtr s, int buf, int bufSize, int *address, int *port, int *moreFlag); int sqSockettoHostportSendDataBufCount(SocketPtr s, int address, int port, int buf, int bufSize); int sqSocketSetOptionsoptionNameStartoptionNameSizeoptionValueStartoptionValueSizereturnedValue( SocketPtr s,int optionName, int optionNameSize, int optionValue, int optionValueSize, int *result); int sqSocketGetOptionsoptionNameStartoptionNameSizereturnedValue( SocketPtr s,int optionName, int optionNameSize, int *result); /*** security traps ***/ /* check if we are allowed to create the given socket */ int ioCanCreateSocketOfType(int netType, int socketType); /* check if we are allowed to connect to the given port */ int ioCanConnectToPort(int netAddr, int port); /* check if we are allowed to listen on the given port Note: ability to listen applies also to setting ports of UDP sockets. For TCP sockets, the ability to listen implies the ability to accept(). */ int ioCanListenOnPort(SocketPtr s, int port); /* disable all use of sockets */ int ioDisableSocketAccess(void); /* query for socket availability */ int ioHasSocketAccess(void); #ifdef DISABLE_SECURITY #define ioCanCreateSocketOfType(netType, socketType) 1 #define ioCanConnectToPort(netAddr, port) 1 #define ioCanListenOnPort(s, port) 1 #define ioDisableSocketAccess() 1 #define ioHasSocketAccess() 1 #endif ' ! ! !SystemDictionary methodsFor: 'security' stamp: 'ar 2/6/2001 00:46'! primitiveCanWriteImage "Smalltalk primitiveCanWriteImage" "Primitive. Return true if the right to write an image hasn't been revoked." ^true "assume so unless otherwise proven"! ! !SystemDictionary methodsFor: 'security' stamp: 'ar 2/6/2001 14:10'! primitiveDisableFileAccess "Smalltalk primitiveDisableFileAccess" "Primitive. Disable unlimited access to files. Cannot be revoked from the image." ^self primitiveFailed! ! !SystemDictionary methodsFor: 'security' stamp: 'ar 2/6/2001 00:47'! primitiveDisableImageWrite "Smalltalk primitiveDisableImageWrite" "Primitive. Disable writing to an image file. Cannot be revoked from the image." ^self primitiveFailed! ! !SystemDictionary methodsFor: 'security' stamp: 'ar 2/6/2001 14:12'! primitiveDisableSocketAccess "Smalltalk primitiveDisableSocketAccess" "Primitive. Disable access to sockets. Cannot be revoked from the image." ^self primitiveFailed! ! !SystemDictionary methodsFor: 'security' stamp: 'ar 2/6/2001 00:47'! primitiveGetSecureUserDirectory "Smalltalk primitiveGetSecureUserDirectory" "Primitive. Return the directory where we can securely store data that is not accessible in restricted mode." ^self primitiveFailed! ! !SystemDictionary methodsFor: 'security' stamp: 'ar 2/6/2001 00:47'! primitiveGetUntrustedUserDirectory "Smalltalk primitiveGetUntrustedUserDirectory" "Primitive. Return the untrusted user directory that is the root directory for files that are visible even in restricted mode." ^self primitiveFailed! ! !SystemDictionary methodsFor: 'security' stamp: 'ar 2/6/2001 14:10'! primitiveHasFileAccess "Smalltalk primitiveHasFileAccess" "Return true if the right to access arbitrary files hasn't been revoked" ^true "assume so unless otherwise proven"! ! !SystemDictionary methodsFor: 'security' stamp: 'ar 2/6/2001 14:12'! primitiveHasSocketAccess "Smalltalk primitiveHasSocketAccess" "Return true if the right to access sockets hasn't been revoked" ^true "assume so unless otherwise proven"! !