This is Coordinator.m in view mode; [Download] [Up]
//***************************************************************************** // // Coordinator.m // // NXApp delegate, central control object for GateKeeper // // by Felipe A. Rodriguez // // The base for this file was: // // Coordinator.m // by Joe Freeman, David LaVallee // Subprocess Example, Release 2.0 // NeXT Computer, Inc. // // This code is supplied "as is" the author makes no warranty as to its // suitability for any purpose. This code is free and may be distributed // in accordance with the terms of the: // // GNU GENERAL PUBLIC LICENSE // Version 2, June 1991 // copyright (C) 1989, 1991 Free Software Foundation, Inc. // 675 Mass Ave, Cambridge, MA 02139, USA // //***************************************************************************** #import "GKdefs.h" #import "Animator.h" #import "Parse.h" #import "OptionsEditor.h" #import "options.h" #import "IconView.h" #import "ToolBar.h" #import "DOserver.h" #import "Timer.h" #import "InactivityTimer.h" #import "Coordinator.h" #import "CommandScroll.h" #import "Subprocess.h" #import "GateDocEditor.h" #import "HLRecord.h" #import "HLDelegate.h" #import <appkit/nextstd.h> #import <appkit/Application.h> #import <dpsclient/dpsNeXT.h> #import <objc/NXStringTable.h> #import <defaults/defaults.h> #import <bsd/c.h> #import <sys/dir.h> /* POSIX applications #include <dirent.h> */ @interface Coordinator(Private) // preferences controls extern char *cList[]; extern char *rfList[]; extern char *rsList[]; // private functions - miscPrep2; // dial on demand server #import <mach/mach_error.h> #import <servers/netname.h> #import "nsRPC_types.h" any_t server_loop(any_t port); // defined by MiG: boolean_t nsRPC_server(msg_header_t *in, msg_header_t *out); // from Request types in nsRPCUser.c struct message { msg_header_t head; /* standard header field */ msg_type_t arg1_type; /* first arg type */ int arg1; /* first arg */ msg_type_t arg2_type; /* second arg type */ int arg2; /* second arg */ }; @end @implementation Coordinator(Private) //***************************************************************************** // // misc to do before coordinator starts a subprocess // //***************************************************************************** - miscPrep2 { int i = 0; [[theAnimator startAnimTimer] setStandbyGate:NO]; [linkMenuButton setEnabled:NO]; // disable link button [dial setEnabled:NO]; // disable dial button [theOpenButton setEnabled:NO]; // disable the open doc button while(i < 3) { // erase captured str's array if(capturedStr[i]) free(capturedStr[i]); capturedStr[i++] = NULL; // blank, for next invocation } linkStg = 0; // prevent stages in link process from getting called twice // setup and load our keyword's hashtable if(strHashTable) free(strHashTable); strHashTable = [[HashTable alloc] initKeyDesc:"*" valueDesc:"i"]; for(i = 0; i < 2; i++) { numEntries[i] = i; [strHashTable insertKey:NXGetDefaultValue([NXApp appName], cList[i+1]) value:&numEntries[i]]; } for(i = 0; i < 4; i++) { numEntries[i + 2] = i + 2; [strHashTable insertKey:NXGetDefaultValue([NXApp appName], rfList[i]) value:&numEntries[i + 2]]; } numEntries[6] = 6; [strHashTable insertKey:"address" value:&numEntries[6]]; numEntries[7] = 7; [strHashTable insertKey:"remote" value:&numEntries[7]]; return self; } @end @implementation Coordinator //************************ Subprocess Delegation ****************************** //***************************************************************************** // // recieves output from subprocess // canonicalizes output stream into lines // //***************************************************************************** - subprocessOutput:(char *)buffer { static char strbuf[132]; static int strpos = 0; while(*buffer) { // cr/lf delimit lines and we do not exceed strbuf size if((*buffer != '\n' && *buffer != '\r') && strpos < 128) { strbuf[strpos++] = *buffer++; strbuf[strpos] = '\0'; } else { while((*buffer == '\n' || *buffer == '\r') && (strpos < 130)) strbuf[strpos++] = *buffer++; strbuf[strpos] = '\0'; [self analyzeBuffer:strbuf]; strpos = 0; } } return self; } //***************************************************************************** // // - captures certain keywords as status and info markers // - calls gotIt, displayLinkStatus methods when link is established // - sends data stream to diagnostics window and comments to status // //***************************************************************************** - analyzeBuffer:(char *)buffer { char *str, delim[] = {" \n\r^/"}, delim2[] = {"\n\r^"}, *argString = NULL; int *cntr; if(argString != NULL) free(argString); argString = NXCopyStringBuffer(buffer); [commandView appendString:buffer]; // send buffer to diag win str = strtok(argString, delim); // Parse string and test it while(str != NULL) { if(*str == '#') // comments will be displayed in status panel { if(str = strtok(NULL, delim2)) { if(strlen(str) > 3) [statusView setStringValue:[self localString:str]]; } } else { if ([strHashTable isKey:str] == YES) // if str is in hash table { // we have caught a keyword cntr = [strHashTable valueForKey:str]; switch(*cntr) { case 2: // redial? case 3: // Persistent connect case 4: // Fail connect case 5: // LCP terminate if((strcmp(NXGetDefaultValue([NXApp appName], rsList[*cntr - 2]),"YES") == 0) // sw "ON"? && (lastCall[0] != '\0')) [self perform:@selector(redial:) with:self afterDelay:backOffDelay cancelPrevious:YES]; else [self UnLink:nil]; // if redial off, unlink break; case 0: // baud str caught if((str = strtok(NULL, delim)) && (capturedStr[0] == NULL)) [self connectedAt:str]; break; case 1: // the link is up if(linkStg < 4) // if ivar is >, ppp { [self gotIt]; // may be sending linkStg = 4; // keyword twice } break; case 6: // local address str caught if((str = strtok(NULL, delim)) && (linkStg < 5)) { capturedStr[1] = NXCopyStringBuffer(str); linkStg = 5; } break; case 7: // display addresses if(linkStg < 6) { if((str = strtok(NULL, delim)) != NULL) { if((str = strtok(NULL, delim)) != NULL) { if((str = strtok(NULL, delim)) != NULL) { capturedStr[2] = NXCopyStringBuffer(str); [self displayLinkStatus]; } } } } break; default: break; } } } str = strtok(NULL, delim); } return self; } //************************************************************************ // // Called when subprocess has terminated // //************************************************************************ - subprocessDone { [theTimer stopTimer]; if(theGateServer) [theGateServer free]; theGateServer = nil; [theSubprocess free]; theSubprocess = nil; if(userWantsTermination) // end only if user chose too (not subP fail) [NXApp terminate:self]; else // if not exiting [theAnimator startAnimTimer]; // cycle thru animation return self; } //***************************************************************************** // // return our string table (contains key->value localization pairs) // //***************************************************************************** - stringTable; { return stringTable; } //***************************************************************************** // // localize error messages using stringTable as appropriate, displays // the message in an alert panel // //***************************************************************************** - showAlert:(const char *)errorString { NXRunAlertPanel(0, [self localString:errorString], [stringTable valueForStringKey:"OK"], NULL, NULL); return self; } //***************************************************************************** // // localize string messages using stringTable as appropriate // //***************************************************************************** - (const char *)localString:(const char *)aString { const char *returnedString; if (returnedString = [stringTable valueForStringKey:aString]) return returnedString; return aString; } //***************************************************************************** // // Called when link is established // //***************************************************************************** - gotIt { [theAnimator removeTimedEntry]; // ppp is up, play snd for me if(strcmp(NXGetDefaultValue([NXApp appName],"sound"), "YES") == 0) [[[Sound findSoundFor: "majestic"] play: nil] free]; [theTimer Fire:self]; if(!onImage) onImage = [NXImage findImageNamed:"g4"]; [theIconView setImage:onImage]; [statusView setStringValue:[self localString:"pppup"]]; // if auto hide switch is set wait 5 sec before hiding if(strcmp(NXGetDefaultValue([NXApp appName], "autoHide"),"YES") == 0) [NXApp perform:@selector(hide:) with:self afterDelay:5000 cancelPrevious:NO]; return self; } //***************************************************************************** // // registers connection speed // //***************************************************************************** - connectedAt:(const char *)speed { strncpy(Path, [stringTable valueForStringKey:"connectAt"], MAXPATHLEN); strncat(Path, speed, MAXPATHLEN - strlen(Path)); capturedStr[0] = NXCopyStringBuffer(Path); [connectionSpeedField setStringValue:capturedStr[0]]; return self; } //***************************************************************************** // // displays captured info regarding current ppp session // //***************************************************************************** - displayLinkStatus { if(capturedStr[0] != NULL) // in case we man dialed { // we will not know connect speed [commandView appendString:"\n#################################\n"]; [commandView appendString:"####\n"]; [commandView appendString:"#### "]; [commandView appendString:capturedStr[0]]; } else [commandView appendString:"\n#################################"]; [commandView appendString:"\n####\n"]; [commandView appendString:[stringTable valueForStringKey:"localIP"]]; [commandView appendString:capturedStr[1]]; [localIPField setStringValue:capturedStr[1]]; [commandView appendString:"\n####\n"]; [commandView appendString:[stringTable valueForStringKey:"remoteIP"]]; [commandView appendString:capturedStr[2]]; [commandView appendString:"\n####"]; [remoteIPField setStringValue:capturedStr[2]]; [commandView appendString:"\n#################################\n"]; linkStg = 6; // ppp link is up, set ivar [iTimer pppstats:commandView]; // run pppstats w/view return self; } //*********************** Application Object Delegation *********************** //***************************************************************************** // // setup defaults data base cache before app is init'd // //***************************************************************************** - appWillInit:sender { static NXDefaultsVector myDefaults = { // setup defaults database {DISPLAYD, "YES"}, // display diagnostics window {DISPLAYS, "YES"}, // display status window {"autoLaunch", "NO"}, {"autoHide", "YES"}, // auto hide upon link {"autoRedial", "YES"}, {"PersistCon", "YES"}, {"FailRedial", "YES"}, // redial if a Fail occurs {"LCPterminate", "YES"}, // redial if lcp termination occurs {"Fail", "Exit."}, {"reDial", "Failed"}, {"Persist", "down"}, // persistent connect trigger {"LCPterm", "terminated."}, // lcp termination trigger {"DispPPP", "YES"}, // display pppstats {DISPLAYT, "YES"}, // display toolbar {"DoD", "NO"}, // dial on demand {USEFIFO, "YES"}, // use a FIFO for IPC w/pppd? {"sound", "YES"}, // play sound {AITIMER, "YES"}, // icon displayed online time {REDBOFF, "YES"}, // backoff on failed redials? {"iTimeout", "Off"}, // inactivity unlink's us {"preTimeout", "YES"}, // inactivity unlink's us {"iTimeThreshold", "0"}, // inactivity threshold {SELCELL, "0"}, // cell selected in hotList {BROWSERHT, "999.0"}, // ht of browser in hotList {ADDRESSHT, "999.0"}, // ht of address in hotList {FIRSTTIME, "YES"}, // first time thru? {"options", "/etc/ppp/options"}, {"ip-down", "/etc/ppp/ip-down"}, {"ip-up", "/etc/ppp/ip-up"}, {"resolv", "/etc/resolv.conf"}, {"syslog", "/etc/syslog.conf"}, {"messages", "/usr/adm/messages"}, {"rc", "/etc/rc.local"}, {"remote", "/etc/remote"}, {"locFIFO", "/usr/adm/GateKeeper.fifo"}, // pref form start {"comLine", "/usr/local/bin/pppd -detach"}, {HLLIST, "/"}, {"BaudStr", "CARRIER"}, // pref form end {"LinkUp", "local"}, // Link is up trigger {DIALINIT, "ATZ&D0L3"}, // modem init str for manual Dial {"dialPrefix", "ATD"}, // modem AT command prefix for dialing {MODEMPORT, "cufa"}, // modem port, used in releasing locks {"path", "/"}, // path for .Gate documents {"lastNumDialed", "8675309"}, // default man dial number {"savedTime", "000000000000"}, // save time used this mo {"monthTime", "000000000000"}, // save mo,yr of this ses'n {"preMonthTime", "000000000000"}, // save previous mo,yr {NULL}}; // make local cache of ddb NXRegisterDefaults([NXApp appName], myDefaults); return self; } //***************************************************************************** // // standard init // //***************************************************************************** - appDidInit:sender { time_t waitTime; // time to delay time(<ime); // Get time and place in time_t if(strcmp(NXGetDefaultValue([NXApp appName], USEFIFO), "YES") == 0) [self syslogdReset]; // reset the syslogd daemon // setup appIcon for animation theAnimator = [[Animator alloc] init]; // get appIcon window theIconView = [theAnimator iconView]; timeCell = [theIconView getTextCell]; // return the iconView's textCell if(strcmp(NXGetDefaultValue([NXApp appName], FIRSTTIME),"YES") == 0) { // if first time this version was launched [self showInfo:self]; if(!NXWriteDefault([NXApp appName], FIRSTTIME, "NO")) NXRunAlertPanel(0, [stringTable valueForStringKey:"ddbWriteError"], [stringTable valueForStringKey:"OK"], NULL, NULL); } [NXApp loadNibSection:"StatusWindow.nib" owner:self withNames:NO]; if(strcmp("YES", NXGetDefaultValue([NXApp appName], DISPLAYS)) == 0) [statusWin makeKeyAndOrderFront:self]; // show status panel [NXApp loadNibSection:"DiagWindow.nib" owner:self withNames:NO]; [diagWin setFrameUsingName:[diagWin title]]; // remem sz,loc [diagWin setFrameAutosaveName:[diagWin title]]; if(strcmp("YES", NXGetDefaultValue([NXApp appName], DISPLAYT)) == 0) [self toolBar:self]; // show toolbar if set if(strcmp("YES", NXGetDefaultValue([NXApp appName], AITIMER)) == 0) appIconTime = YES; // show online time in app icon if(strcmp("YES", NXGetDefaultValue([NXApp appName], REDBOFF)) == 0) backOffDefault = backOffDelay = BDEF; // redial delay backoff on // setup Inactivity timeout and pppstats controller iTimer = [[InactivityTimer allocFromZone:[self zone]] init]; if(strcmp(NXGetDefaultValue([NXApp appName],"NXAutoLaunch"),"YES") == 0) { // if app was dock autoLaunched waitTime = ltime + 2; // delay for X sec so that syslogd can sync while(ltime < waitTime) // ltime ivar is set in syslogReset method {time(<ime);} } theTimer = [[Timer allocFromZone:[self zone]] init]; // If we weren't asked to open any documents at launch time, then // we were launched by double clicking on the application instead // of a document. If so check whether we should auto-launch w/def's if(!NXGetDefaultValue([NXApp appName], "NXOpen") && !NXGetDefaultValue([NXApp appName], "NXOpenTemp") && !NXGetDefaultValue([NXApp appName], "NXServiceLaunch")) { if(strcmp(NXGetDefaultValue([NXApp appName], "autoLaunch"),"YES") == 0) [self Link:self]; } [self DialOnDemand]; // prepare for dial on demand if set return self; } //***************************************************************************** // // redial // //***************************************************************************** - redial:sender { // only allow a redial if user has not stopped linking if((strcmp([[[NXApp mainMenu] findCellWithTag:2] title], [[NXApp delegate] localString:"Disconnect"]) == 0) && [[[NXApp mainMenu] findCellWithTag:2] isEnabled] && (sender)) { [self UnLink:nil]; if([self runScript:"preLink"]) { // back off in multiples of 2 backOffDelay *= 2; [self perform:@selector(resetDelay:) with:self afterDelay:(backOffDelay + 1000) cancelPrevious:YES]; [self linkWithFile:lastCall]; } } return self; } //***************************************************************************** // // reset the backoff delay // //***************************************************************************** - resetDelay:sender { // eliminate any pending redials [self perform:@selector(redial:) with:nil afterDelay:0 cancelPrevious:YES]; if ([sender isKindOf:[Matrix class]]) { if((BOOL)[[sender selectedCell] intValue]) backOffDefault = BDEF; // redial delay backoff on else backOffDefault = 0; } backOffDelay = backOffDefault; return self; } //***************************************************************************** // // This method is performed whenever a user double-clicks on an icon in // the Workspace Manager representing a Gate program document. // // Brings up the gate doc editor which can edit or link using the doc // //***************************************************************************** - (int)app:sender openFile:(const char *)path type:(const char *)type { [theGateDocEditor editGateDoc:path]; return 1; } //***************************************************************************** // // invoked immediately after app is hidden and unhidden respectively // // the following two methods are implemented to produce // normal main window/menu app behavior when toolBar is open // //****************************************************************************** - appDidHide:sender { [[NXApp mainMenu] close]; // close the main menu return self; } - appDidUnhide:sender { [[NXApp mainMenu] makeKeyAndOrderFront:self]; return self; } //***************************************************************************** // // Instantantiates the subprocess object which exec's pppd // //***************************************************************************** - linkWithFile:(const char *)path { char commandLine[MAXPATHLEN + 1]; [self miscPrep2]; // misc initialization's if(strcmp(NXGetDefaultValue([NXApp appName], DISPLAYD),"YES") == 0) [diagWin makeKeyAndOrderFront:self]; // show diagnostics win strncpy(commandLine, NXGetDefaultValue([NXApp appName], "comLine"), MAXPATHLEN); commandLine[MAXPATHLEN-1] = 0; if(path == NULL) { lastCall[0] = '\0'; if([hotListDelegate selGateDocOptionsPath] == NULL) commandLine[0] = '\0'; else // if hotlist points to valid { strncat(commandLine, " file ", MAXPATHLEN - strlen(commandLine)); strncat(commandLine, [hotListDelegate selGateDocOptionsPath], MAXPATHLEN - strlen(commandLine)); strncpy(BPath,[hotListDelegate selGateDocOptionsPath], MAXPATHLEN); [providerField setStringValue:[self localString:"manDial"]]; } } else { strcpy(lastCall, path); // stores path of last invocation if(strstr(path, "GateKeeper.app") == NULL) [providerField setStringValue:[self extractName:path]]; else [providerField setStringValue:[self localString:"gkDefault"]]; [statusView setStringValue:[self localString:"connecting"]]; if((strlen([[NXBundle mainBundle] directory]) + 45 + (2 * strlen(path)) + strlen(commandLine)) < MAXPATHLEN) { // if we won't overrun buffer strcat(commandLine, " file "); strcat(commandLine, path); strcat(commandLine, OPTION); // options file name wrapper strcat(commandLine, " connect \""); strcat(commandLine, [[NXBundle mainBundle] directory]); strcat(commandLine, "/chat -v -f "); strcat(commandLine, path); strcat(commandLine, PPPUP); // pppup file name wrapper strcat(commandLine, "\""); } else perror("command line is longer than MAXPATHLEN"); strncpy(BPath, path , MAXPATHLEN); strncat(BPath, OPTION, MAXPATHLEN - strlen(BPath)); // options } if(commandLine[0] != '\0') // if we have a valid commline { [linkMenuButton setEnabled:YES]; // enable unlink button [linkMenuButton setTitle:[self localString:"Disconnect"]]; [linkMenuButton setAction:@selector(UnLink:)]; [statusButton setTitle:[self localString:"Disconnect"]]; [statusButton setAction:@selector(UnLink:)]; if([iTimer posNonInter]) [commandView appendString: "Dial on demand triggered ppp session\n"]; if([self debugFlag:BPath]) { // if debug sw set in options disg commandline [commandView appendString:commandLine]; [commandView appendString:"\n\r"]; } theSubprocess = [[Subprocess alloc] init:commandLine withDelegate:self andStdErr:YES]; } return self; } //***************************************************************************** // // Use terminal to do a manual link // //***************************************************************************** - Dial:sender { if((strcmp([linkMenuButton title], [self localString:"Connect"]) == 0) && [linkMenuButton isEnabled] && [self runScript:"preLink"]) { [self miscPrep2]; // misc initialization's [iTimer setPosNonInter:NO]; // user interactive session if(!theGateServer) // create distributed Obj server theGateServer = [[DOserver alloc] init]; [theGateServer setDelegate:self]; GateConnection = [NXConnection registerRoot: theGateServer withName:"GateKeeperServer"]; // DO name of server [GateConnection runFromAppKit]; // listen for DO messages from appKit if(![[NXBundle mainBundle] getPath:Path forResource:"MODEM" ofType:NULL]) [self showAlert:"Error getting path for MODEM file"]; [[Application workspace] openFile:Path withApplication:"Terminal"]; } return self; } //***************************************************************************** // // Called: when menu item link is pressed, when DNS triggers us. // Calls app:sender // //***************************************************************************** - Link:sender { if((strcmp([linkMenuButton title], [self localString:"Connect"]) == 0) && [linkMenuButton isEnabled] && [self runScript:"preLink"]) { if(!sender) // DNS triggered session, [iTimer setPosNonInter:YES]; // possibly non-interactive else [iTimer setPosNonInter:NO]; // user interactive session [hotListDelegate playLink]; // selected in the HotList to launch pppd } return self; } //***************************************************************************** // // Called when menu item Unlink is pressed. // //***************************************************************************** - UnLink:sender { if([self runScript:"preUnLink"]) { if(theSubprocess && [theSubprocess respondsTo:@selector(terminate:)]) [theSubprocess terminate:sender]; [[theAnimator setOpenGate:YES] setStandbyGate:YES]; [iTimer pppstatsReset]; // disable pppstats [timeCell setStringValue:" "]; [linkMenuButton setEnabled:YES]; // enable unlink button [linkMenuButton setTitle:[self localString:"Connect"]]; [linkMenuButton setAction:@selector(Link:)]; [statusButton setTitle:[self localString:"Connect"]]; [statusButton setAction:@selector(Link:)]; [theOpenButton setEnabled:YES]; // enable the open doc button [dial setEnabled:YES]; // enable dial button [statusView setStringValue:[self localString:"pppdn"]]; [connectionSpeedField setStringValue:" "]; [timeField setStringValue:" "]; [providerField setStringValue:" "]; [localIPField setStringValue:" "]; [remoteIPField setStringValue:" "]; [self namedDod]; // kill/restart named to dump cache } if(sender) [self resetDelay:self]; return self; } //***************************************************************************** // // run the preLink or preUnLink scripts, proceed if exit status true // //***************************************************************************** - runScript:(const char *)type { id exitStatus = self; int fd; strncpy(Path, [[NXBundle mainBundle] directory], MAXPATHLEN); strncat(Path, "/", MAXPATHLEN - strlen(Path)); strncat(Path, type, MAXPATHLEN - strlen(Path)); if(fd = open(Path, O_RDONLY) != -1) // if script exists { close(fd); if(system(Path) != 0) // exec script, test exit exitStatus = nil; strcpy(Path, type); if(!exitStatus) strcat(Path," script exit status prevents requested action\n"); else strcat(Path, " script executed sucessfully\n"); [commandView appendStringUseFixedFont:Path]; } return exitStatus; } //***************************************************************************** // // we can always edit another gate doc // //***************************************************************************** - (BOOL)appAcceptsAnotherFile:sender { return YES; } //**************************************************************************** // // termination is allowed only if the user has selected it, subprocess // failure should not cause GateKeeper to terminate // //**************************************************************************** - terminate:sender { userWantsTermination = YES; return self; } //**************************************************************************** // // termination is imminent // //**************************************************************************** - appWillTerminate:sender { [theSubprocess terminate:sender]; [theAnimator removeTimedEntry]; [self namedReset:"/usr/etc/named"]; // replace our named with system's [hotListDelegate appWillTerminate]; return self; } //***************************************************************************** // // show the info panel // //***************************************************************************** - showInfo:sender { if(!infoPanel) [NXApp loadNibSection:"InfoPanel.nib" owner:self withNames:NO]; [infoPanel center]; [infoPanel makeKeyAndOrderFront:self]; return self; } //**************************************************************************** // // show preferences panel // //**************************************************************************** - preferences:sender { if(!prefPanel) [NXApp loadNibSection:"Preferences.nib" owner:self withNames:NO]; [prefPanel makeKeyAndOrderFront:self]; return self; } //************************************************************************ // // show NXHelpPanel // //************************************************************************ - showHelpPanel:sender { if(!helpPanel) helpPanel = [NXHelpPanel new]; [helpPanel display]; [helpPanel makeKeyAndOrderFront:self]; return self; } //************************************************************************ // // display the Status panel // //************************************************************************ - showStatusPanel:sender { if(!NXWriteDefault([NXApp appName], DISPLAYS, "YES")) [self showAlert:"ddbWriteError"]; return [statusWin makeKeyAndOrderFront:self]; } //***************************************************************************** // // display the Diagnostics window // //***************************************************************************** - showDiagWin:sender { if(!NXWriteDefault([NXApp appName], DISPLAYD, "YES")) [self showAlert:"ddbWriteError"]; return [diagWin makeKeyAndOrderFront:self]; } //************************************************************************ // // show the timer // //************************************************************************ - showTimerPanel:sender { return [theTimer showTimerPanel:self]; } //***************************************************************************** // // called by timer in order to pass us appIcon time string // // also used in determining inactivity timeout (since this is called // once per minute during ppp sessions). // //***************************************************************************** - showMenuTimer:(char *)buffer { if(appIconTime) [timeCell setStringValue:buffer]; [timeField setStringValue:buffer]; [theIconView setImage:onImage]; [iTimer inactivityTimeout]; return self; } //***************************************************************************** // // set inactivity timer's timeout Ivar and write its value to ddb // //***************************************************************************** - setTimeout:(int)minTillTimeout { [iTimer setTimeout:minTillTimeout]; return self; } //***************************************************************************** // // enable/disable display of online time in app icon // //***************************************************************************** - setAppIconTimer:(BOOL)onOff { appIconTime = onOff; return self; } //***************************************************************************** // // return a pointer to the hotlist window's delegate // //***************************************************************************** - hotListDelegate { return hotListDelegate; } //***************************************************************************** // // tell browser to update its data from its delegate // //***************************************************************************** - updateBrowser:sender { return [hotListDelegate loadBrowser]; } //************************************************************************ // // extracts the Gate doc name from its path // //************************************************************************ - (const char *)extractName:(const char *)aPath { char *ptr; strcpy(Path, aPath); ptr = Path + strlen(Path) - 1; while(*ptr != '.' && *ptr) ptr--; *ptr-- = '\0'; while(*ptr != '/' && *ptr) ptr--; ++ptr; return ptr; } //************************************************************************ // // returns whether a Gate doc may be opened or edited by real user // //************************************************************************ - readable:(const char *)nameOfFile { FILE *fp; if ((fp = fopen(nameOfFile, "r+")) == NULL) [self showAlert:"Unable to open Gate doc"]; else { if(readable(fileno(fp))) { fclose(fp); return self; // we have permission } [self showAlert:"Access to Gate doc denied"]; fclose(fp); } return nil; // we do not have permission } //***************************************************************************** // // returns the Gate doc options editor // //***************************************************************************** - optionsEditor { if(!theOptionsEditor) theOptionsEditor = [[OptionsEditor alloc] init]; return theOptionsEditor; } //***************************************************************************** // // returns the state of the debug flag in an options file // //***************************************************************************** - (BOOL)debugFlag:(const char *)optionFile { return [[[self optionsEditor] parseOptions:optionFile] debug]; } //***************************************************************************** // // show the Tool Bar // //***************************************************************************** - toolBar:sender { if(!NXWriteDefault([NXApp appName], DISPLAYT, "YES")) [self showAlert:"ddbWriteError"]; if(!toolBar) [NXApp loadNibSection:"ToolBar.nib" owner:self withNames:NO]; [toolBar makeKeyAndOrderFront:self]; return toolBar; } //************************************************************************ // // return the app icons view // //************************************************************************ - appIconView { return theIconView; // enable link button } //************************************************************************ // // called by DO server when remote manual Dial Tool's ports are // invalidated // //************************************************************************ - DOFinished { return [self UnLink:self]; // enable link button } //************************************************************************ // // free simply gets rid of everything we created // This is how nice objects clean up. // //************************************************************************ - free { [timeCell free]; if(onImage) [onImage free]; if(toolBar) [toolBar free]; if(iTimer) [iTimer free]; return [super free]; } //***************************************************************************** // // Attempt to reset syslogd daemon. Failing that, try starting it. // //***************************************************************************** - syslogdReset { FILE *ff; int pid, fd; if((ff = fopen( "/etc/syslog.pid", "r")) != NULL) { if( fscanf( ff, "%d", &pid) < 1) perror("Unable to read pid from etc/syslog.pid\n"); else { if( kill( pid, SIGHUP) != -1) // tell syslogd to reconfigure { fclose( ff); // open FIFO so that syslogd is not blocked if((fd=open(NXGetDefaultValue([NXApp appName], "locFIFO"),O_RDONLY))<0) { perror("Error opening FIFO\n"); return self; } sleep(1); close(fd); return self; // report success } else // if app was not dock autoLaunched if(strcmp(NXGetDefaultValue( [NXApp appName],"NXAutoLaunch"),"NO") == 0) perror("error reconfiguring syslogd"); } } else perror("Unable to open /etc/syslog.pid\n"); return [self syslogdRun]; // failed to reconfig so restart syslogd } //***************************************************************************** // // Terminante and then run the syslogd daemon // //***************************************************************************** - syslogdRun { FILE *ff; int pid, fd; if((ff = fopen( "/etc/syslog.pid", "r")) != NULL) { if( fscanf( ff, "%d", &pid) < 1) perror("Unable to read pid from etc/syslog.pid\n"); else if( kill( pid, SIGTERM) == -1) { if(strcmp(NXGetDefaultValue( [NXApp appName],"NXAutoLaunch"),"NO") == 0) perror("error killing syslogd"); } } switch (pid = vfork()) // create new process { case -1: // error perror("Error during vfork syslogdReset."); return self; case 0: // child -- Vfork returns 0 in the child's context execl("/usr/etc/syslogd", "syslogd", 0); perror("vfork error restarting syslogd"); exit(1); default: // parent -- vfork returns pid of the child break; } // open FIFO so that syslogd is not blocked if((fd=open(NXGetDefaultValue([NXApp appName], "locFIFO"),O_RDONLY))<0) { perror("Error opening FIFO\n"); return self; } sleep(1); close(fd); return self; } //***************************************************************************** // // prepare ourself to be triggered by named when dial on demand is // necessary // //***************************************************************************** - DialOnDemand { port_t server_port; kern_return_t r; // if dial on demand is "ON" if(strcmp("YES", NXGetDefaultValue([NXApp appName], "DoD")) == 0) { // allocate a port for this task, ret in arg 2 r = port_allocate(task_self(), &server_port); if (r != KERN_SUCCESS) { mach_error("port_allocate failed", r); exit(1); } // Register with the Network Name Server. r = netname_check_in(name_server_port, GK_DNS_SERVER, PORT_NULL, server_port); if (r != KERN_SUCCESS) { mach_error("netname_check_in failed", r); exit(1); } // create dial on demand server thread and detach it cthread_detach(cthread_fork((cthread_fn_t)server_loop, (any_t)server_port)); [self namedDod]; // replace named with dial on demand trigger named } return self; } //***************************************************************************** // // Attempt to kill and restart named daemon. Resets RR's cache. // //***************************************************************************** - namedReset:(const char *)buffer { FILE *ff; int pid; // if dial on demand is "ON" if(strcmp("YES", NXGetDefaultValue([NXApp appName], "DoD")) == 0) { if((ff = fopen( "/etc/named.pid", "r")) != NULL) { if( fscanf( ff, "%d", &pid) < 1) perror("Unable to read pid from etc/named.pid\n"); else { if( kill( pid, SIGTERM) == -1) // kill named perror("error killing named"); } } else perror("Unable to open /etc/named.pid\n"); fclose( ff); system(buffer); // start GateKeeper named } return self; } //***************************************************************************** // // replace the system named with our own which will inform us when a // dial on demand is necessary // //***************************************************************************** - namedDod { if(!strcpy(Path, [[NXBundle mainBundle] directory])) // app's home dir [self showAlert:"Error getting mainbundle path"]; else { strcat(Path,"/named"); [self namedReset:Path]; // kill named and replace with our own } return self; } //***************************************************************************** // // search /etc/syslog.conf to find the location of the named pipe used // in recieving the output from pppd/syslog // //***************************************************************************** - fifo { static char del1[] = {". =:|\t\r\n"}, del2[] = {" \t\r\n"}; char *fifoName = NULL; if(!Parser) Parser = [[Parse alloc] init]; // create parser to find port [[Parser setKey1:"local2"] setKey2:"debug"]; // set search pattern [[Parser setDelim1:del1] setDelim2:del2]; // and delimiters if(fifoName = [Parser parseFile:"/etc/syslog.conf"]) { if(!NXWriteDefault([NXApp appName], "locFIFO", fifoName)) NXRunAlertPanel(0, [stringTable valueForStringKey:"ddbWriteError"], [stringTable valueForStringKey:"OK"], NULL, NULL); free(fifoName); } else [self showAlert:"FIFO Path Error"]; return self; } //***************************************************************************** // // checks the mail queue for mail awaiting delivery // //***************************************************************************** - (BOOL)mailInQueue { int eCntr = 0; struct direct *dirp; DIR *dp; BOOL mail = NO; if ((dp = opendir("/usr/spool/mqueue")) != NULL) { while ((dirp = readdir(dp)) && eCntr < 3) // read dir and cnt entries { if(*dirp->d_name != '.') // don't count if sys file eCntr++; } if(eCntr > 2) mail = YES; closedir(dp); } else [self showAlert:"Error opening Mail queue directory"]; return mail; } //************** Diagnostics Window delegate methods ************************** //***************************************************************************** // // called whenever the user minituriazes our Diagnostics window. // //***************************************************************************** - windowWillMiniaturize:sender toMiniwindow:miniwindow { return [sender setMiniwindowIcon:"miniWinIcon"]; } //***************************************************************************** // // called whenever the user closes our Diagnostics window. // //***************************************************************************** - windowWillClose:sender { if(![sender isKindOf:[Panel class]]) // simple test to see if diag { // win is what is being closed if(!NXWriteDefault([NXApp appName], DISPLAYD, "NO")) [self showAlert:"ddbWriteError"]; } return self; } @end //***************************************************************************** // // c thread loop which listens for RPC telling us to link // //***************************************************************************** any_t server_loop(any_t port) { struct message msg, reply; kern_return_t ret; while (TRUE) { /* Receive a request from a client. */ msg.head.msg_local_port = (port_t)port; msg.head.msg_size = sizeof(struct message); ret = msg_receive(&msg.head, MSG_OPTION_NONE, 0); if (ret != RCV_SUCCESS) /* ignore errors */ continue; /* Feed the request into the server. */ (void)nsRPC_server((msg_header_t *)&msg, (msg_header_t *)&reply); /* Send a reply to the client. */ reply.head.msg_local_port = (port_t)port; ret = msg_send(&reply.head, MSG_OPTION_NONE, 0); if (ret != SEND_SUCCESS) /* ignore errors */ continue; } return 0; } //***************************************************************************** // // This function is called by nsRPC_server, which was created by MiG. // It is NOT directly called by any client process. // //***************************************************************************** kern_return_t pppUp(port_t server) { [[NXApp delegate] Link:nil]; return KERN_SUCCESS; }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.