📄 nc.c
字号:
/*** Xt timer procedure for timeouts on NEdit server requests*/static void timeOutProc(Boolean *timeOutReturn, XtIntervalId *id){ /* NOTE: XtAppNextEvent() does call this routine but ** doesn't return unless there are more events. ** Hence, we generate this (synthetic) event to break the deadlock */ Window rootWindow = RootWindow(TheDisplay, DefaultScreen(TheDisplay)); if (currentWaitForAtom != noAtom) { XChangeProperty(TheDisplay, rootWindow, currentWaitForAtom, XA_STRING, 8, PropModeReplace, (unsigned char *)"", strlen("")); } /* Flag that the timeout has occurred. */ *timeOutReturn = True;}static Boolean findExistingServer(XtAppContext context, Window rootWindow, Atom serverExistsAtom){ Boolean serverExists = True; unsigned char *propValue; int getFmt; Atom dummyAtom; unsigned long dummyULong, nItems; /* See if there might be a server (not a guaranty), by translating the root window property NEDIT_SERVER_EXISTS_<user>_<host> */ if (XGetWindowProperty(TheDisplay, rootWindow, serverExistsAtom, 0, INT_MAX, False, XA_STRING, &dummyAtom, &getFmt, &nItems, &dummyULong, &propValue) != Success || nItems == 0) { serverExists = False; } else { Boolean timeOut = False; XtIntervalId timerId; XFree(propValue); /* Remove the server exists property to make sure the server is ** running. If it is running it will get recreated. */ XDeleteProperty(TheDisplay, rootWindow, serverExistsAtom); XSync(TheDisplay, False); timerId = XtAppAddTimeOut(context, PROPERTY_CHANGE_TIMEOUT, (XtTimerCallbackProc)timeOutProc, &timeOut); currentWaitForAtom = serverExistsAtom; while (!timeOut) { /* NOTE: XtAppNextEvent() does call the timeout routine but ** doesn't return unless there are more events. */ XEvent event; const XPropertyEvent *e = (const XPropertyEvent *)&event; XtAppNextEvent(context, &event); /* We will get a PropertyNewValue when the server recreates ** the server exists atom. */ if (e->type == PropertyNotify && e->window == rootWindow && e->atom == serverExistsAtom) { if (e->state == PropertyNewValue) { break; } } XtDispatchEvent(&event); } /* Start a new server if the timeout expired. The server exists ** property was not recreated. */ if (timeOut) { serverExists = False; } else { XtRemoveTimeOut(timerId); } } return(serverExists);} static void startNewServer(XtAppContext context, Window rootWindow, char* commandLine, Atom serverExistsAtom){ Boolean timeOut = False; XtIntervalId timerId; /* Add back the server name resource from the command line or resource database to the command line for starting the server. If -svrcmd appeared on the original command line, it was removed by CreatePreferencesDatabase before the command line was recorded in commandLine.shell. Moreover, if no server name was specified, it may have defaulted to the ClearCase view tag. */ if (Preferences.serverName[0] != '\0') { strcat(commandLine, " -svrname "); strcat(commandLine, Preferences.serverName); } switch (startServer("No servers available, start one? (y|n) [y]: ", commandLine)) { case -1: /* Start failed */ XtCloseDisplay(TheDisplay); exit(EXIT_FAILURE); break; case -2: /* Start canceled by user */ XtCloseDisplay(TheDisplay); exit(EXIT_SUCCESS); break; } /* Set up a timeout proc in case the server is dead. The standard selection timeout is probably a good guess at how long to wait for this style of inter-client communication as well */ timerId = XtAppAddTimeOut(context, SERVER_START_TIMEOUT, (XtTimerCallbackProc)timeOutProc, &timeOut); currentWaitForAtom = serverExistsAtom; /* Wait for the server to start */ while (!timeOut) { XEvent event; const XPropertyEvent *e = (const XPropertyEvent *)&event; /* NOTE: XtAppNextEvent() does call the timeout routine but ** doesn't return unless there are more events. */ XtAppNextEvent(context, &event); /* We will get a PropertyNewValue when the server updates ** the server exists atom. If the property is deleted the ** the server must have died. */ if (e->type == PropertyNotify && e->window == rootWindow && e->atom == serverExistsAtom) { if (e->state == PropertyNewValue) { break; } else if (e->state == PropertyDelete) { fprintf(stderr, "%s: The server failed to start.\n", APP_NAME); XtCloseDisplay(TheDisplay); exit(EXIT_FAILURE); } } XtDispatchEvent(&event); } /* Exit if the timeout expired. */ if (timeOut) { fprintf(stderr, "%s: The server failed to start (time-out).\n", APP_NAME); XtCloseDisplay(TheDisplay); exit(EXIT_FAILURE); } else { XtRemoveTimeOut(timerId); }}/*** Prompt the user about starting a server, with "message", then start server*/static int startServer(const char *message, const char *commandLineArgs){ char c, *commandLine;#ifdef VMS int spawnFlags = 1 /* + 1<<3 */; /* NOWAIT, NOKEYPAD */ int spawn_sts; struct dsc$descriptor_s *cmdDesc; char *nulDev = "NL:"; struct dsc$descriptor_s *nulDevDesc;#else int sysrc;#endif /* !VMS */ /* prompt user whether to start server */ if (!Preferences.autoStart) { puts(message); do { c = getc(stdin); } while (c == ' ' || c == '\t'); if (c != 'Y' && c != 'y' && c != '\n') return (-2); } /* start the server */#ifdef VMS commandLine = XtMalloc(strlen(Preferences.serverCmd) + strlen(commandLineArgs) + 3); sprintf(commandLine, "%s %s", Preferences.serverCmd, commandLineArgs); cmdDesc = NulStrToDesc(commandLine); /* build command descriptor */ nulDevDesc = NulStrToDesc(nulDev); /* build "NL:" descriptor */ spawn_sts = lib$spawn(cmdDesc, nulDevDesc, 0, &spawnFlags, 0,0,0,0,0,0,0,0); XtFree(commandLine); if (spawn_sts != SS$_NORMAL) { fprintf(stderr, "Error return from lib$spawn: %d\n", spawn_sts); fprintf(stderr, "Nedit server not started.\n"); return (-1); } else { FreeStrDesc(cmdDesc); return 0; }#else#if defined(__EMX__) /* OS/2 */ /* Unfortunately system() calls a shell determined by the environment variables COMSPEC and EMXSHELL. We have to figure out which one. */ { char *sh_spec, *sh, *base; char *CMD_EXE="cmd.exe"; commandLine = XtMalloc(strlen(Preferences.serverCmd) + strlen(commandLineArgs) + 15); sh = getenv ("EMXSHELL"); if (sh == NULL) sh = getenv ("COMSPEC"); if (sh == NULL) sh = CMD_EXE; sh_spec=XtNewString(sh); base=_getname(sh_spec); _remext(base); if (stricmp (base, "cmd") == 0 || stricmp (base, "4os2") == 0) { sprintf(commandLine, "start /C /MIN %s %s", Preferences.serverCmd, commandLineArgs); } else { sprintf(commandLine, "%s %s &", Preferences.serverCmd, commandLineArgs); } XtFree(sh_spec); }#else /* Unix */ commandLine = XtMalloc(strlen(Preferences.serverCmd) + strlen(commandLineArgs) + 3); sprintf(commandLine, "%s %s&", Preferences.serverCmd, commandLineArgs);#endif sysrc=system(commandLine); XtFree(commandLine); if (sysrc==0) return 0; else return (-1);#endif /* !VMS */}/* Reconstruct the command line in string commandLine in case we have to * start a server (nc command line args parallel nedit's). Include * -svrname if nc wants a named server, so nedit will match. Special * characters are protected from the shell by escaping EVERYTHING with \ */static CommandLine processCommandLine(int argc, char** argv){ CommandLine commandLine; int i; int length = 0; for (i=1; i<argc; i++) { length += 1 + strlen(argv[i])*4 + 2; } commandLine.shell = XtMalloc(length+1 + 9 + MAXPATHLEN); *commandLine.shell = '\0'; /* Convert command line arguments into a command string for the server */ parseCommandLine(argc, argv, &commandLine); if (commandLine.serverRequest == NULL) { fprintf(stderr, "nc: Invalid commandline argument\n"); exit(EXIT_FAILURE); } return(commandLine);} /*** Converts command line into a command string suitable for passing to** the server*/static void parseCommandLine(int argc, char **argv, CommandLine *commandLine){#define MAX_RECORD_HEADER_LENGTH 38 char name[MAXPATHLEN], path[MAXPATHLEN]; const char *toDoCommand = "", *langMode = "", *geometry = ""; char *commandString, *outPtr; int lineNum = 0, read = 0, create = 0, iconic = 0, length = 0; int i, lineArg, nRead, charsWritten, opts = True; int fileCount = 0; /* Allocate a string for output, for the maximum possible length. The maximum length is calculated by assuming every argument is a file, and a complete record of maximum length is created for it */ for (i=1; i<argc; i++) { length += MAX_RECORD_HEADER_LENGTH + strlen(argv[i]) + MAXPATHLEN; } /* In case of no arguments, must still allocate space for one record header */ if (length < MAX_RECORD_HEADER_LENGTH) { length = MAX_RECORD_HEADER_LENGTH; } commandString = XtMalloc(length+1); /* Parse the arguments and write the output string */ outPtr = commandString; for (i=1; i<argc; i++) { if (opts && !strcmp(argv[i], "--")) { opts = False; /* treat all remaining arguments as filenames */ continue; } else if (opts && !strcmp(argv[i], "-do")) { nextArg(argc, argv, &i); toDoCommand = argv[i]; } else if (opts && !strcmp(argv[i], "-lm")) { copyCommandLineArg(commandLine, argv[i]); nextArg(argc, argv, &i); langMode = argv[i]; copyCommandLineArg(commandLine, argv[i]); } else if (opts && (!strcmp(argv[i], "-g") || !strcmp(argv[i], "-geometry"))) { copyCommandLineArg(commandLine, argv[i]);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -