This is ExecMonitor.m in view mode; [Download] [Up]
// ------------------------------------------------------------------------------------- // ExecMonitor // ------------------------------------------------------------------------------------- // Permission is granted to freely redistribute this source code, and to use fragments // of this code in your own applications if you find them to be useful. This class, // along with the source code, come with no warranty of any kind, and the user assumes // all responsibility for its use. // ------------------------------------------------------------------------------------- #import <appkit/appkit.h> #import <libc.h> #import <stdlib.h> #import <c.h> #import <errno.h> #import <ctype.h> #import <math.h> #import <sys/param.h> #import <sys/types.h> #import <sys/time.h> #import <sys/wait.h> #import <sys/resource.h> #import "RemoteCommand.h" #import "userInfo.h" #import "ExecServer.h" #import "ExecScrollText.h" #import "ExecMonitor.h" // ------------------------------------------------------------------------------------- // misc defines #define REMOTE_SERVER_CMD "RemoteRunServer" // ------------------------------------------------------------------------------------- // misc defines #define X origin.x #define Y origin.y #define W size.width #define H size.height #define freeString(X) { if (X) { free((char*)X); X = 0; } } #define freeCopy(T,F) { freeString(T); if (F) T = NXCopyStringBuffer(F); } #define cpnil (char*)nil #define exeBtnTITLE "Execute\nCommand" // ------------------------------------------------------------------------------------- // ExecMonitor list of instances static id instanceList = (id)nil; // ------------------------------------------------------------------------------------- // list of cached user passwords typedef struct userPassword_s { char *user; // user name char *password; // password void *next; // pointer to next user } userPassword_t; static userPassword_t *userList = (userPassword_t*)nil; // ------------------------------------------------------------------------------------- @implementation ExecMonitor // ------------------------------------------------------------------------------------- // user password // ------------------------------------------------------------------------------------- /* find user password */ + (userPassword_t*)_findUserRcd:(const char*)user { userPassword_t *u; for (u = userList; u && strcmp(user, u->user); u = (userPassword_t*)u->next); return u; } /* update user password */ + (userPassword_t*)_addUser:(const char*)userName password:(const char*)password { userPassword_t *u; if (!XUserVerifyPassword(userName, password)) return (userPassword_t*)nil; u = (userPassword_t*)malloc(sizeof(userPassword_t)); u->user = NXCopyStringBuffer(userName); u->password = NXCopyStringBuffer(password?password:""); u->next = (void*)userList; userList = u; return u; } /* find user password */ + (const char*)findUserPassword:(const char*)user { userPassword_t *u = [self _findUserRcd:user]; return u? u->password : (char*)nil; } /* update user password */ + updateUser:(const char*)user password:(const char*)password { userPassword_t *u = [self _findUserRcd:user]; if (u) { if (strcmp(u->password, password)) freeCopy(u->password, password); } else [self _addUser:user password:password]; return self; } /* update user password */ + removeUserPassword:(const char*)user { userPassword_t *u = userList, *l = (userPassword_t*)nil; for (;u && strcmp(user,u->user); l = u, u = (userPassword_t*)u->next); if (u) { (l? l->next : userList) = u->next; freeString(u->user); freeString(u->password); free(u); } return self; } // ------------------------------------------------------------------------------------- // object initialization // ------------------------------------------------------------------------------------- /* new exec monitor */ + newExecHost:(const char*)host server:(const char*)server { self = [[self alloc] init]; if (![self setRemoteHost:host server:server]) { [self free]; return (id)nil; } [self showPanel:self]; return self; } /* init */ - init { NXRect wFrame; /* instanceList initialization */ if (!instanceList) instanceList = [[[List alloc] initCount:1] empty]; [instanceList addObject:self]; /* init super */ [super init]; exeUser = (id)nil; exePassword = (id)nil; exeWindow = (id)nil; exeCommandScroll = (id)nil; /* load nib */ if (![NXApp loadNibSection:"ExecMonitor.nib" owner:self]) { NXLogError("[ExecMonitor] Could not load nib file 'ExecMonitor.nib'"); [NXApp delayedFree:self]; return self; } /* spot-check nib loading */ if (!exeWindow || !exeCommandScroll) { NXLogError("[ExecMonitor] 'ExecMonitor.nib' did not load properly"); [NXApp delayedFree:self]; return self; } /* init vars */ saveFileName = (char*)nil; useRunServer = YES; cmdInProcess = NO; shutDown = NO; exeRunServer = (id)nil; /* set user values if specified */ if (exeUser) [exeUser setStringValue:""]; if (exePassword) [exePassword setStringValue:""]; /* init panel */ [exeExecute setTitle:exeBtnTITLE]; [exeCommandScroll clearScrollText]; [exeControlBox setBorderType:NX_NOBORDER]; [exeWindow setDelegate:self]; [exeWindow setFreeWhenClosed:NO]; [exeWindow getFrame:&wFrame]; minWinSize = wFrame.size; return self; } /* free */ - _free:sender { return [self free]; } - free { shutDown = YES; if (cmdInProcess) { // loop until command has completed [self exeExecute:(id)nil]; [self perform:@selector(_free:) with:self afterDelay:500 cancelPrevious:YES]; return (id)nil; } [exeWindow free]; [instanceList removeObject:self]; // make sure 'self' is removed return [super free]; } // ------------------------------------------------------------------------------------- // run arguments /* set remote host (start server if necessary) */ - setRemoteHost:(const char*)host server:(const char*)server { char cmd[MAXPATHLEN + 1], title[256]; /* check for already set */ if (exeRunServer) { NXLogError("[ExecMonitor] ExecServer is already running"); return (id)nil; } /* instantiate ExecServer object */ exeRunServer = (host && *host)? [[ExecServer alloc] init] : (id)nil; if (!exeRunServer) { NXLogError("[ExecMonitor] Could not create ExecServer (no host specified)"); return (id)nil; } /* set attributes */ [exeRunServer setMainAppPath:XAppPath()]; [exeRunServer setMainAppServerName:[NXApp appServerName] host:[NXApp appServerHost]]; [exeRunServer setRemoteHost:host]; if (server && *server) [exeRunServer setRemoteServerName:server]; sprintf(cmd, "%s/%s", XAppPath(), REMOTE_SERVER_CMD); if (![exeRunServer setServerCommandName:cmd]) { NXLogError("[ExecMonitor] Unable to set ExecServer command to %s", cmd); exeRunServer = (id)nil; return (id)nil; } /* start server */ if (![exeRunServer startServer]) { NXLogError("[ExecMonitor] Could not connect to RemoteRunServer"); exeRunServer = (id)nil; return (id)nil; } /* set window title */ sprintf(title, "ExecMonitor: %s (%s)", [exeRunServer remoteHost], [exeRunServer remoteServerName]); [exeWindow setTitle:title]; return self; } /* show ExecMonitor panel */ - showPanel:sender { return [exeWindow makeKeyAndOrderFront:(id)nil]; } // ------------------------------------------------------------------------------------- // command execution // ------------------------------------------------------------------------------------- /* print messages */ - _printCompletion:(BOOL)isError:(char*)fmt, ... { char *h = isError?">>>>>>>>>>":"----------", *t = isError?"<<<<<<<<<<":"----------"; va_list args; /* message color and header */ if (isError) [exeShellScroll setTextAttributeColor:NX_COLORRED]; else [exeShellScroll setTextAttributeGray:NX_DKGRAY]; [exeShellScroll textPrintf:"\n%s ", h]; /* message */ va_start(args, fmt); [exeShellScroll textPrintf:fmt args:args]; va_end(args); /* message trailer and reset gray */ [exeShellScroll textPrintf:" %s\n\n", t]; [exeShellScroll setTextAttributeGray:textGray]; /* return error condition */ return isError? (id)nil : self; } /* execute Server command */ - exeExecute:sender { int commandLen; char *cmdStr, *user, *pass; /* check for no run server */ if (!exeRunServer) { NXBeep(); return (id)nil; } /* check for "STOP" */ if (cmdInProcess) { if (!strcmp([exeExecute icon], "Stop")) { if (useRunServer) [exeRunServer terminateCommand:execId]; else [exeShellScroll terminateCommand]; [exeExecute setIcon:"Kill"]; } else { if (useRunServer) [exeRunServer killCommand:execId]; else [exeShellScroll killCommand]; } return self; } if (!sender) return (id)nil; /* exit if shutdown in progress */ if (shutDown) return (id)nil; /* get user */ user = exeUser? (char*)[exeUser stringValue] : (char*)nil; if (!user || !*user) user = (char*)[NXApp appUserName]; /* get password (if needed) */ if (!XIsCurrentUser(user)) { pass = exePassword? (char*)[exePassword stringValue] : ""; if ([exeRunServer needUserPassword:user] && !XUserVerifyPassword(user, pass)) { [[self class] removeUserPassword:user]; return [self _printCompletion:1:"User password not valid"]; } [[self class] updateUser:user password:pass]; } /* setup command */ commandLen = [[exeCommandScroll docView] textLength] + 1; cmdStr = (char*)malloc(commandLen + 1); [[exeCommandScroll docView] getSubstring:cmdStr start:0 length:commandLen]; strcat(cmdStr, "\n"); /* print command info */ [exeShellScroll setTextAttributeGray:NX_DKGRAY]; [exeShellScroll textPrintf:"\n---------- Executing Command ----------\n"]; [exeShellScroll textPrintf:"%s", cmdStr]; [exeShellScroll textPrintf: "---------------------------------------\n\n"]; [exeShellScroll setTextAttributeGray:textGray]; /* run command */ if (useRunServer) { execId = [exeRunServer runCommand:cmdStr withUser:user:[[self class] findUserPassword:user] forClient:exeShellScroll killOnError:YES]; } else { execId = (execHandle_t)[exeShellScroll runCommand:cmdStr]; } /* free command */ free(cmdStr); /* check to see if command actually started running */ if (!execId) return [self _printCompletion:1:"Command failed to start"]; /* change button */ cmdInProcess = YES; [exeExecute setIconPosition:NX_ICONONLY]; [exeExecute setIcon:"Stop"]; return self; } /* call-back from shell command (main thread) */ - commandDidComplete:shellId withError:(int)theError { /* check for completion status */ if (!theError) { // successful [self _printCompletion:0:"completed normally"]; } else { char *desc = [ExecServer errorDesc:theError]; if (desc) [self _printCompletion:1:"%s",desc]; else [self _printCompletion:1:"Terminated with exit(%d)",theError]; } /* remove user if password is bad */ if ((theError == RSRV_BADPASSWD) && exeUser) { [ExecMonitor removeUserPassword:[exeUser stringValue]]; } /* reset execution button */ [exeExecute setEnabled:YES]; [exeExecute setIconPosition:NX_TITLEONLY]; [exeExecute setTitle:exeBtnTITLE]; cmdInProcess = NO; execId = (execHandle_t)nil; return self; } // ------------------------------------------------------------------------------------- // Terminal invoke // ------------------------------------------------------------------------------------- /* invoke command in Terminal window */ + terminalCommand:(const char*)cmd title:(const char*)title { Speaker *speaker; port_t terminalPort; /* can't find Terminal */ if (!(terminalPort = NXPortFromName("Terminal", NULL))) return (id)nil; /* launch Terminal */ [NXApp deactivateSelf]; creat("/tmp/.reallyignorethis.term", 0444); [[Application workspace] openFile:"/tmp/.reallyignorethis.term" fromImage:(id)nil at:(NXPoint*)nil inView:(id)nil]; /* run command */ speaker = [NXApp appSpeaker]; [speaker setSendPort: terminalPort]; [speaker selectorRPC:"runCommand:usingShell:inFolder:windowTitle:closeOnExit:" paramTypes: "cccci", cmd, "", "", title, NO]; return self; } // ------------------------------------------------------------------------------------- // outlets // ------------------------------------------------------------------------------------- - setExeShellScroll:anObject { exeShellScroll = [[ExecScrollText newExecScrollText:anObject] clearScrollText]; [exeShellScroll setDelegate:self]; textFont = [[exeShellScroll docView] font]; textGray = [[exeShellScroll docView] textGray]; [exeShellScroll setTab:[textFont getWidthOf:" "] count:10]; [exeShellScroll textPrintf:"\n"]; // this forces the scroll view to initialize [exeShellScroll clearScrollText]; return self; } - setExeCommandScroll:anObject { exeCommandScroll = [[ExecScrollText newExecScrollText:anObject] clearScrollText]; return self; } // ------------------------------------------------------------------------------------- // first responder methods // ------------------------------------------------------------------------------------- /* save error handler */ - (BOOL)attemptOverwrite:(const char*)fileName { NXLogError("[ExecMonitor] Unable to save %s", fileName); return NO; } /* save contents of text view */ - saveAs:sender { char *temp; id savePanel = [SavePanel new]; /* set up save panel */ [savePanel setTitle:"Save Command Output"]; [savePanel setPrompt:"File:"]; [savePanel setRequiredFileType:""]; [savePanel setDirectory:(saveFileName?saveFileName:[NXApp appUserHome])]; /* get file name to save */ if (![savePanel runModalForDirectory:[NXApp appUserHome] file:""]) return self; if (!(temp = (char*)[savePanel filename])) return self; freeString(saveFileName); saveFileName = NXCopyStringBuffer(temp); return [self save:sender]; } /* save contents of text view */ - save:sender { if (!saveFileName) return [self saveAs:sender]; [[exeShellScroll docView] saveRTFDTo:saveFileName removeBackup:NO errorHandler:self]; return self; } // ------------------------------------------------------------------------------------- // window close // ------------------------------------------------------------------------------------- /* close all windows */ + closeAllWindows { if (instanceList) [instanceList makeObjectsPerform:@selector(closeWindow:) with:self]; return self; } /* shut down */ - closeWindow:sender { return [exeWindow performClose:self]; } // ------------------------------------------------------------------------------------- // window delegate methods // ------------------------------------------------------------------------------------- - windowWillClose:windowId { if (cmdInProcess) return (id)nil; [instanceList removeObject:self]; return [NXApp delayedFree:self]; } - windowWillResize:windowId toSize:(NXSize*)newSize { if (newSize->width < minWinSize.width ) newSize->width = minWinSize.width; if (newSize->height < minWinSize.height) newSize->height = minWinSize.height; return self; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.