/* Return the default filename for screen tracing. */ char * screentrace_default_file(ptype_t ptype) { const char *suffix; switch (ptype) { default: case P_TEXT: suffix = "txt"; break; case P_HTML: suffix = "html"; break; case P_RTF: suffix = "rtf"; break; } #if defined(_WIN32) /*[*/ return xs_buffer("%s%sx3scr.$UNIQUE.%s", appres.trace_dir? appres.trace_dir: default_trace_dir(), appres.trace_dir? "\\": "", suffix); #else /*][*/ return xs_buffer("%s/x3scr.$UNIQUE.%s", appres.trace_dir, suffix); #endif /*]*/ }
static char * ex_getenv(const char *name, unsigned long flags, int *up) { if (!strcasecmp(name, "TIMESTAMP")) { /* YYYYMMDDHHMMSSUUUUUU */ struct timeval tv; time_t t; /* on Windows, timeval.tv_sec is a long */ struct tm *tm; if (gettimeofday(&tv, NULL) < 0) { return NewString("?"); } t = tv.tv_sec; tm = localtime(&t); return xs_buffer("%04u%02u%02u%02u%02u%02u%06u", tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, (unsigned)tv.tv_usec); } else if (!strcasecmp(name, "UNIQUE")) { ++*up; if (*up == 0) { return xs_buffer("%u", (unsigned)getpid()); } else { return xs_buffer("%u-%u", (unsigned)getpid(), *up); } } else { return getenv(name); } }
/* * Validate a resource that is fetched explicitly, rather than via appres. */ static int valid_explicit(const char *resname, size_t len) { xreslist_t *x; unsigned i; int j; for (x = xreslist; x != NULL; x = x->next) { for (i = 0; i < x->count; i++) { size_t sl = strlen(x->xresources[i].name); switch (x->xresources[i].type) { case V_FLAT: /* Exact match. */ if (len == sl && !strncmp(x->xresources[i].name, resname, sl)) { return 0; } break; case V_WILD: /* xxx.* match. */ if (len > sl + 1 && resname[sl] == '.' && !strncmp(x->xresources[i].name, resname, sl)) { return 0; } break; case V_COLOR: /* xxx<host-color> or xxx<host-color-index> match. */ for (j = 0; host_color[j].name != NULL; j++) { char *xbuf; xbuf = xs_buffer("%s%s", x->xresources[i].name, host_color[j].name); if (strlen(xbuf) == len && !strncmp(xbuf, resname, len)) { Free(xbuf); return 0; } Free(xbuf); xbuf = xs_buffer("%s%d", x->xresources[i].name, host_color[j].index); if (strlen(xbuf) == len && !strncmp(xbuf, resname, len)) { Free(xbuf); return 0; } Free(xbuf); } break; } } } return -1; }
/* Check for a trace file rollover event. */ void trace_rollover_check(void) { if (tracef == NULL || tracef_max == 0) return; /* See if we've reached a rollover point. */ if (tracef_size >= tracef_max) { char *alt_filename; char *new_header; #if defined(_WIN32) /*[*/ char *period; #endif /*]*/ /* Close up this file. */ wtrace("Trace rolled over\n"); fclose(tracef); tracef = NULL; /* Unlink and rename the alternate file. */ #if defined(_WIN32) /*[*/ period = strrchr(tracefile_name, '.'); if (period != CN) alt_filename = xs_buffer("%.*s-%s", period - tracefile_name, tracefile_name, period); else #endif /*]*/ alt_filename = xs_buffer("%s-", tracefile_name); (void) unlink(alt_filename); (void) rename(tracefile_name, alt_filename); Free(alt_filename); alt_filename = CN; tracef = fopen(tracefile_name, "w"); if (tracef == (FILE *)NULL) { popup_an_errno(errno, "%s", tracefile_name); return; } /* Initialize it. */ tracef_size = 0L; (void) SETLINEBUF(tracef); new_header = create_tracefile_header("rolled over"); do_ts = True; wtrace(new_header); Free(new_header); } }
static void no_minus(const char *arg) { if (arg[0] == '-') { usage(xs_buffer("Unknown or incomplete option: %s", arg)); } }
/* * Create a Roman font. * Returns 0 for success, -1 for failure. */ static int create_roman_font(HDC dc, int fheight, int fwidth, const char **fail) { char *w, *h; w = fwidth? xs_buffer("%d", fwidth): NewString("(auto)"); h = fheight? xs_buffer("%d", fheight): NewString("(auto)"); vtrace("[gdi] requesting a font %sx%s logical units\n", w, h); Free(w); Free(h); pstate.font = CreateFont( fheight, /* height */ fwidth, /* width */ 0, /* escapement */ 0, /* orientation */ FW_NORMAL, /* weight */ FALSE, /* italic */ FALSE, /* underline */ FALSE, /* strikeout */ DEFAULT_CHARSET, /* character set */ OUT_OUTLINE_PRECIS, /* output precision */ CLIP_DEFAULT_PRECIS,/* clip precision */ DEFAULT_QUALITY, /* quality */ FIXED_PITCH|FF_DONTCARE,/* pitch and family */ uparm.font_name); /* face */ if (pstate.font == NULL) { *fail = "CreateFont failed"; return -1; } /* Measure a space to find out the size we got. */ SelectObject(dc, pstate.font); if (!GetTextExtentPoint32(dc, " ", 1, &pstate.space_size)) { *fail = "GetTextExtentPoint32 failed"; return -1; } vtrace("[gdi] space character is %dx%d logical units\n", (int)pstate.space_size.cx, (int)pstate.space_size.cy); pstate.usable_cols = pstate.usable_xpixels / pstate.space_size.cx; pstate.usable_rows = pstate.usable_ypixels / pstate.space_size.cy; vtrace("[gdi] usable area is %dx%d characters\n", pstate.usable_cols, pstate.usable_rows); return 0; }
/* Pop up a message, end the transfer. */ void ft_complete(const char *errmsg) { /* Close the local file. */ if (fts.local_file != NULL && fclose(fts.local_file) < 0) { popup_an_errno(errno, "close(%s)", ftc->local_filename); } fts.local_file = NULL; /* Clean up the state. */ ft_state = FT_NONE; if (ft_start_id != NULL_IOID) { RemoveTimeOut(ft_start_id); ft_start_id = NULL_IOID; } /* Get the idle timeout going again. */ idle_ft_complete(); /* Pop down the in-progress shell. */ ft_gui_progress_popdown(); /* Pop up the text. */ if (errmsg != NULL) { char *msg_copy = NewString(errmsg); /* Make sure the error message will fit on the pop-up. */ ft_gui_errmsg_prepare(msg_copy); /* Clear out the progress display. */ ft_gui_clear_progress(); /* Pop up the error. */ popup_an_error("%s", msg_copy); Free(msg_copy); } else { struct timeval t1; double bytes_sec; char *buf; (void) gettimeofday(&t1, NULL); bytes_sec = (double)fts.length / ((double)(t1.tv_sec - t0.tv_sec) + (double)(t1.tv_usec - t0.tv_usec) / 1.0e6); buf = xs_buffer(get_message("ftComplete"), fts.length, display_scale(bytes_sec), fts.is_cut ? "CUT" : "DFT"); ft_gui_clear_progress(); ft_gui_complete_popup(buf); Free(buf); } /* I hope I can do this unconditionally. */ sms_continue(); }
/* Open the trace file. */ static void tracefile_on(int reason, enum toggle_type tt) { char *tracefile_buf = NULL; char *tracefile; if (tracef != NULL) { return; } trace_reason = reason; if (appres.secure && tt != TT_INITIAL) { tracefile_ok("none"); return; } if (onetime_tracefile_name != NULL) { tracefile = tracefile_buf = onetime_tracefile_name; onetime_tracefile_name = NULL; } else if (appres.trace_file) { tracefile = appres.trace_file; } else { #if defined(_WIN32) /*[*/ tracefile_buf = xs_buffer("%s%sx3trc.$UNIQUE.txt", appres.trace_dir? appres.trace_dir: default_trace_dir(), appres.trace_dir? "\\": ""); #else /*][*/ tracefile_buf = xs_buffer("%s/x3trc.$UNIQUE", appres.trace_dir); #endif /*]*/ tracefile = tracefile_buf; } if (!trace_gui_on(reason, tt, tracefile)) { tracefile_ok(tracefile); } else { /* Turn the toggle _off_ until the popup succeeds. */ set_toggle(reason, false); } if (tracefile_buf != NULL) { Free(tracefile_buf); } }
/* Substitute and return. */ if (p == NULL) { r = NewString(s); } else { r = Malloc(strlen(p->pw_dir) + strlen(rest) + 1); (void) strcpy(r, p->pw_dir); (void) strcat(r, rest); } return r; } #else /*][*/ static char * tilde_subst(const char *s) { char *t; if (*s != '~' || (t = getenv("HOMEPATH")) == NULL) { return NewString(s); } switch (*(s + 1)) { case '\0': return NewString(t); case '/': case '\\': return xs_buffer("%s%s", t, s + 1); default: return NewString(s); } }
/* * Start up a window to monitor the trace file. * * @param[in] path Trace file path. On Unix, this can be NULL to indicate * that the trace is just being piped. * @param[in] pipefd Array of pipe file descriptors. */ static void start_trace_window(const char *path, int pipefd[]) { switch (tracewindow_pid = fork_child()) { case 0: /* child process */ (void) execlp("xterm", "xterm", "-title", path? path: "trace", "-sb", "-e", "/bin/sh", "-c", xs_buffer("cat <&%d", pipefd[0]), NULL); (void) perror("exec(xterm) failed"); _exit(1); break; default: /* parent */ (void) close(pipefd[0]); ++children; break; case -1: /* error */ popup_an_errno(errno, "fork() failed"); break; } }
/* Disply command-line help. */ void cmdline_help (bool as_action) { unsigned i; sort_help(); for (i = 0; i < sorted_help_count; i++) { char *h = sorted_help[i].help_opts; char *ht; char *hx = NULL; char *star; if (sorted_help[i].type == OPT_XRM && h != NULL && (star = strchr(h, '*')) != NULL) { ht = hx = xs_buffer("%.*s%s%s", (int)(star - h), h, app, star + 1); } else { ht = h; } if (as_action) { action_output(" %s%s%s", sorted_help[i].name, ht? " ": "", ht? ht: ""); action_output(" %s", sorted_help[i].help_text); } else { fprintf(stderr, " %s%s%s\n %s\n", sorted_help[i].name, ht? " ": "", ht? ht: "", sorted_help[i].help_text); } if (hx != NULL) { Free(hx); } } }
/* Open the trace file. */ static void tracefile_on(int reason, enum toggle_type tt) { char *tracefile_buf = NULL; char *tracefile; if (tracef != (FILE *)NULL) return; trace_reason = reason; if (appres.secure && tt != TT_INITIAL) { tracefile_callback((Widget)NULL, "none", PN); return; } if (onetime_tracefile_name != NULL) { tracefile = tracefile_buf = onetime_tracefile_name; onetime_tracefile_name = NULL; } else if (appres.trace_file) tracefile = appres.trace_file; else { #if defined(_WIN32) /*[*/ tracefile_buf = xs_buffer("%s%sx3trc.$UNIQUE.txt", appres.trace_dir? appres.trace_dir: DEFAULT_TRACE_DIR, appres.trace_dir? "\\": ""); #else /*][*/ tracefile_buf = xs_buffer("%s/x3trc.$UNIQUE", appres.trace_dir); #endif /*]*/ tracefile = tracefile_buf; } #if defined(X3270_DISPLAY) /*[*/ if (tt == TT_INITIAL || tt == TT_ACTION) #endif /*]*/ { tracefile_callback((Widget)NULL, tracefile, PN); if (tracefile_buf != NULL) Free(tracefile_buf); return; } #if defined(X3270_DISPLAY) /*[*/ if (trace_shell == NULL) { trace_shell = create_form_popup("trace", tracefile_callback, appres.trace_monitor? no_tracefile_callback: NULL, FORM_NO_WHITE); XtVaSetValues(XtNameToWidget(trace_shell, ObjDialog), XtNvalue, tracefile, NULL); } /* Turn the toggle _off_ until the popup succeeds. */ appres.toggle[reason].value = False; appres.toggle[reason].changed = True; popup_popup(trace_shell, XtGrabExclusive); #endif /*]*/ if (tracefile_buf != NULL) Free(tracefile_buf); }
/* Callback for "OK" button on trace popup */ static void tracefile_callback(Widget w, XtPointer client_data, XtPointer call_data _is_unused) { char *tfn = CN; int devfd = -1; #if defined(X3270_DISPLAY) /*[*/ int pipefd[2]; Boolean just_piped = False; #endif /*]*/ char *buf; #if defined(X3270_DISPLAY) /*[*/ if (w) tfn = XawDialogGetValueString((Widget)client_data); else #endif /*]*/ tfn = (char *)client_data; tfn = do_subst(tfn, DS_VARS | DS_TILDE | DS_UNIQUE); if (strchr(tfn, '\'') || ((int)strlen(tfn) > 0 && tfn[strlen(tfn)-1] == '\\')) { popup_an_error("Illegal file name: %s", tfn); Free(tfn); goto done; } tracef_max = 0; if (!strcmp(tfn, "stdout")) { tracef = stdout; } else { #if defined(X3270_DISPLAY) /*[*/ FILE *pipefile = NULL; if (!strcmp(tfn, "none") || !tfn[0]) { just_piped = True; if (!appres.trace_monitor) { popup_an_error("Must specify a trace file " "name"); free(tfn); goto done; } } if (appres.trace_monitor) { if (pipe(pipefd) < 0) { popup_an_errno(errno, "pipe() failed"); Free(tfn); goto done; } pipefile = fdopen(pipefd[1], "w"); if (pipefile == NULL) { popup_an_errno(errno, "fdopen() failed"); (void) close(pipefd[0]); (void) close(pipefd[1]); Free(tfn); goto done; } (void) SETLINEBUF(pipefile); (void) fcntl(pipefd[1], F_SETFD, 1); } if (just_piped) { tracef = pipefile; } else #endif /*]*/ { Boolean append = False; #if defined(X3270_DISPLAY) /*[*/ tracef_pipe = pipefile; #endif /*]*/ /* Get the trace file maximum. */ get_tracef_max(); /* Open and configure the file. */ if ((devfd = get_devfd(tfn)) >= 0) tracef = fdopen(dup(devfd), "a"); else if (!strncmp(tfn, ">>", 2)) { append = True; tracef = fopen(tfn + 2, "a"); } else tracef = fopen(tfn, "w"); if (tracef == (FILE *)NULL) { popup_an_errno(errno, "%s", tfn); #if defined(X3270_DISPLAY) /*[*/ fclose(tracef_pipe); (void) close(pipefd[0]); (void) close(pipefd[1]); #endif /*]*/ Free(tfn); goto done; } tracef_size = ftello(tracef); Replace(tracefile_name, NewString(append? tfn + 2: tfn)); (void) SETLINEBUF(tracef); #if !defined(_WIN32) /*[*/ (void) fcntl(fileno(tracef), F_SETFD, 1); #endif /*]*/ } } #if defined(X3270_DISPLAY) /*[*/ /* Start the monitor window */ if (tracef != stdout && appres.trace_monitor) { switch (tracewindow_pid = fork_child()) { case 0: /* child process */ { char cmd[64]; (void) snprintf(cmd, sizeof(cmd), "cat <&%d", pipefd[0]); (void) execlp("xterm", "xterm", "-title", just_piped? "trace": tfn, "-sb", "-e", "/bin/sh", "-c", cmd, CN); } (void) perror("exec(xterm) failed"); _exit(1); default: /* parent */ (void) close(pipefd[0]); ++children; break; case -1: /* error */ popup_an_errno(errno, "fork() failed"); break; } } #endif /*]*/ #if defined(_WIN32) && defined(C3270) /*[*/ /* Start the monitor window. */ if (tracef != stdout && appres.trace_monitor && is_installed) { STARTUPINFO startupinfo; PROCESS_INFORMATION process_information; char *path; char *args; (void) memset(&startupinfo, '\0', sizeof(STARTUPINFO)); startupinfo.cb = sizeof(STARTUPINFO); startupinfo.lpTitle = tfn; (void) memset(&process_information, '\0', sizeof(PROCESS_INFORMATION)); path = xs_buffer("%scatf.exe", instdir); args = xs_buffer("\"%scatf.exe\" \"%s\"", instdir, tfn); if (CreateProcess( path, args, NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, &startupinfo, &process_information) == 0) { popup_an_error("CreateProcess(%s) failed: %s", path, win32_strerror(GetLastError())); Free(path); Free(args); } else { Free(path); Free(args); tracewindow_handle = process_information.hProcess; CloseHandle(process_information.hThread); } } #endif /*]*/ Free(tfn); /* We're really tracing, turn the flag on. */ appres.toggle[trace_reason].value = True; appres.toggle[trace_reason].changed = True; menubar_retoggle(&appres.toggle[trace_reason], trace_reason); /* Display current status. */ buf = create_tracefile_header("started"); do_ts = False; wtrace("%s", buf); Free(buf); done: #if defined(X3270_DISPLAY) /*[*/ if (w) XtPopdown(trace_shell); #endif /*]*/ return; }
int parse_command_line(int argc, const char **argv, const char **cl_hostname) { int cl, i; int hn_argc; int sl; int xcmd_len = 0; char *xcmd; int xargc; const char **xargv; Boolean read_session_or_profile = False; /* Figure out who we are */ #if defined(_WIN32) /*[*/ programname = strrchr(argv[0], '\\'); #else /*][*/ programname = strrchr(argv[0], '/'); #endif /*]*/ if (programname) ++programname; else programname = argv[0]; /* Save the command string for tracing purposes. */ cl = strlen(programname); for (i = 0; i < argc; i++) { cl += 1 + strlen(argv[i]); } cl++; command_string = Malloc(cl); (void) strcpy(command_string, programname); for (i = 0; i < argc; i++) { (void) strcat(strcat(command_string, " "), argv[i]); } /* * Save the command-line options so they can be reapplied after * the session file or profile has been read in. */ xcmd_len = 0; for (i = 0; i < argc; i++) xcmd_len += strlen(argv[i]) + 1; xcmd = Malloc(xcmd_len + 1); xargv = (const char **)Malloc((argc + 1) * sizeof(char *)); xcmd_len = 0; for (i = 0; i < argc; i++) { xargv[i] = xcmd + xcmd_len; (void) strcpy(xcmd + xcmd_len, argv[i]); xcmd_len += strlen(argv[i]) + 1; } xargv[i] = CN; *(xcmd + xcmd_len) = '\0'; xargc = argc; #if defined(LOCAL_PROCESS) /*[*/ /* Pick out the -e option. */ parse_local_process(&argc, argv, cl_hostname); #endif /*]*/ /* Set the defaults. */ set_appres_defaults(); /* Parse command-line options. */ parse_options(&argc, argv); /* Pick out the remaining -set and -clear toggle options. */ parse_set_clear(&argc, argv); /* Now figure out if there's a hostname. */ for (hn_argc = 1; hn_argc < argc; hn_argc++) { if (!strcmp(argv[hn_argc], LAST_ARG)) break; } /* Verify command-line syntax. */ switch (hn_argc) { case 1: break; case 2: no_minus(argv[1]); *cl_hostname = argv[1]; break; case 3: no_minus(argv[1]); no_minus(argv[2]); *cl_hostname = xs_buffer("%s:%s", argv[1], argv[2]); break; default: usage("Too many command-line arguments"); break; } /* Delete the host name and any "--". */ if (argv[hn_argc] != CN && !strcmp(argv[hn_argc], LAST_ARG)) hn_argc++; if (hn_argc > 1) { for (i = 1; i < argc - hn_argc + 2; i++) { argv[i] = argv[i + hn_argc - 1]; } } /* Merge in the session. */ if (*cl_hostname != CN && (((sl = strlen(*cl_hostname)) > SESSION_SFX_LEN && !strcasecmp(*cl_hostname + sl - SESSION_SFX_LEN, SESSION_SFX)) #if defined(_WIN32) /*[*/ || ((sl = strlen(*cl_hostname)) > SESSION_SSFX_LEN && !strcasecmp(*cl_hostname + sl - SESSION_SSFX_LEN, SESSION_SSFX)) #endif /*]*/ )) { const char *pname; if (read_resource_file(*cl_hostname, True) < 0) x3270_exit(1); read_session_or_profile = True; pname = strrchr(*cl_hostname, '\\'); if (pname != CN) pname++; else pname = *cl_hostname; profile_name = NewString(pname); Replace(profile_path, NewString(profile_name)); sl = strlen(profile_name); if (sl > SESSION_SFX_LEN && !strcasecmp(profile_name + sl - SESSION_SFX_LEN, SESSION_SFX)) { profile_name[sl - SESSION_SFX_LEN] = '\0'; #if defined(_WIN32) /*[*/ } else if (sl > SESSION_SSFX_LEN && !strcasecmp(profile_name + sl - SESSION_SSFX_LEN, SESSION_SSFX)) { profile_name[sl - SESSION_SSFX_LEN] = '\0'; #endif /*]*/ } *cl_hostname = appres.hostname; /* might be NULL */ } else { /* There is no session file. */ #if defined(C3270) && !defined(_WIN32) /*[*/ /* * For c3270 only, read in the c3270 profile (~/.c3270pro). */ read_session_or_profile = merge_profile(); #endif /*]*/ /* * If there was a hostname resource defined somewhere, but not * as a positional command-line argument, pretend it was one, * so we will connect to it at start-up. */ if (*cl_hostname == CN && appres.hostname != CN) *cl_hostname = appres.hostname; } /* * Now parse the command-line arguments again, so they take * precedence over the session file or profile. */ if (read_session_or_profile) { parse_options(&xargc, xargv); parse_set_clear(&xargc, xargv); } /* Can't free xcmd, parts of it are still in use. */ Free((char *)xargv); /* * All right, we have all of the resources defined. * Sort out the contradictory and implicit settings. */ if (appres.apl_mode) appres.charset = Apl; if (*cl_hostname == CN) appres.once = False; if (appres.conf_dir == CN) appres.conf_dir = LIBX3270DIR; #if defined(X3270_TRACE) /*[*/ if (!appres.debug_tracing) { appres.toggle[TRACING].value = False; } #endif /*]*/ return argc; }
/* * Validate a resource that is fetched explicitly, rather than via appres. */ static int valid_explicit(const char *resname, unsigned len) { static struct { char *name; enum { V_FLAT, V_WILD, V_COLOR } type; } explicit_resources[] = { { ResKeymap, V_WILD }, { ResAssocCommand, V_FLAT }, { ResLuCommandLine, V_FLAT }, { ResPrintTextScreensPerPage, V_FLAT }, #if defined(_WIN32) /*[*/ { ResPrinterCodepage, V_FLAT }, { ResPrinterCommand, V_FLAT }, { ResPrinterName, V_FLAT }, { ResPrintTextFont, V_FLAT }, { ResPrintTextHorizontalMargin, V_FLAT }, { ResPrintTextOrientation, V_FLAT }, { ResPrintTextSize, V_FLAT }, { ResPrintTextVerticalMargin, V_FLAT }, { ResHostColorForDefault, V_FLAT }, { ResHostColorForIntensified, V_FLAT }, { ResHostColorForProtected, V_FLAT }, { ResHostColorForProtectedIntensified,V_FLAT }, { ResConsoleColorForHostColor, V_COLOR }, #else /*][*/ { ResPrinterCommand, V_FLAT }, { ResPrintTextCommand, V_FLAT }, { ResCursesColorForDefault, V_FLAT }, { ResCursesColorForIntensified, V_FLAT }, { ResCursesColorForProtected, V_FLAT }, { ResCursesColorForProtectedIntensified,V_FLAT }, { ResCursesColorForHostColor, V_COLOR }, #endif /*]*/ { NULL, V_WILD } }; int i; int j; for (i = 0; explicit_resources[i].name != CN; i++) { unsigned sl = strlen(explicit_resources[i].name); switch (explicit_resources[i].type) { case V_FLAT: /* Exact match. */ if (len == sl && !strncmp(explicit_resources[i].name, resname, sl)) return 0; break; case V_WILD: /* xxx.* match. */ if (len > sl + 1 && resname[sl] == '.' && !strncmp(explicit_resources[i].name, resname, sl)) return 0; break; case V_COLOR: /* xxx<host-color> or xxx<host-color-index> match. */ for (j = 0; host_color[j].name != CN; j++) { char *x; x = xs_buffer("%s%s", explicit_resources[i].name, host_color[j].name); if (strlen(x) == len && !strncmp(x, resname, len)) { Free(x); return 0; } Free(x); x = xs_buffer("%s%d", explicit_resources[i].name, host_color[j].index); if (strlen(x) == len && !strncmp(x, resname, len)) { Free(x); return 0; } Free(x); } break; } } return -1; }
/* Parse the command line and read in any session file. */ int parse_command_line(int argc, const char **argv, const char **cl_hostname) { size_t cl; int i; int hn_argc; size_t sl; size_t xcmd_len = 0; char *xcmd; int xargc; const char **xargv; bool read_session_or_profile = false; /* Figure out who we are */ #if defined(_WIN32) /*[*/ programname = strrchr(argv[0], '\\'); #else /*][*/ programname = strrchr(argv[0], '/'); #endif /*]*/ if (programname) { ++programname; } else { programname = argv[0]; } /* Save the command string for tracing purposes. */ cl = strlen(programname); for (i = 0; i < argc; i++) { cl += 1 + strlen(argv[i]); } cl++; command_string = Malloc(cl); (void) strcpy(command_string, programname); for (i = 0; i < argc; i++) { (void) strcat(strcat(command_string, " "), argv[i]); } /* * Save the command-line options so they can be reapplied after * the session file or profile has been read in. */ xcmd_len = 0; for (i = 0; i < argc; i++) { xcmd_len += strlen(argv[i]) + 1; } xcmd = Malloc(xcmd_len + 1); xargv = (const char **)Malloc((argc + 1) * sizeof(char *)); xcmd_len = 0; for (i = 0; i < argc; i++) { xargv[i] = xcmd + xcmd_len; (void) strcpy(xcmd + xcmd_len, argv[i]); xcmd_len += strlen(argv[i]) + 1; } xargv[i] = NULL; *(xcmd + xcmd_len) = '\0'; xargc = argc; #if defined(LOCAL_PROCESS) /*[*/ /* Pick out the -e option. */ parse_local_process(&argc, argv, cl_hostname); #endif /*]*/ /* Set the defaults. */ set_appres_defaults(); /* Parse command-line options. */ parse_options(&argc, argv); /* Pick out the remaining -set and -clear toggle options. */ parse_set_clear(&argc, argv); /* Now figure out if there's a hostname. */ for (hn_argc = 1; hn_argc < argc; hn_argc++) { if (!strcmp(argv[hn_argc], LAST_ARG)) { break; } } /* Verify command-line syntax. */ switch (hn_argc) { case 1: break; case 2: no_minus(argv[1]); *cl_hostname = argv[1]; break; case 3: no_minus(argv[1]); no_minus(argv[2]); *cl_hostname = xs_buffer("%s:%s", argv[1], argv[2]); break; default: usage("Too many command-line arguments"); break; } /* Delete the host name and any "--". */ if (argv[hn_argc] != NULL && !strcmp(argv[hn_argc], LAST_ARG)) { hn_argc++; } if (hn_argc > 1) { for (i = 1; i < argc - hn_argc + 2; i++) { argv[i] = argv[i + hn_argc - 1]; } } /* Merge in the session. */ if (session_suffix == NULL) { session_suffix = xs_buffer(".%s", app); session_suffix_len = strlen(session_suffix); } #if defined(_WIN32) /*[*/ if (session_short_suffix == NULL) { session_short_suffix = xs_buffer(".%.3s", app); session_short_suffix_len = strlen(session_short_suffix); } #endif /*]*/ if (*cl_hostname != NULL && (((sl = strlen(*cl_hostname)) > session_suffix_len && !strcasecmp(*cl_hostname + sl - session_suffix_len, session_suffix)) #if defined(_WIN32) /*[*/ || ((sl = strlen(*cl_hostname)) > session_short_suffix_len && !strcasecmp(*cl_hostname + sl - session_short_suffix_len, session_short_suffix)) #endif /*]*/ )) { const char *pname; if (!read_resource_file(*cl_hostname, true)) { x3270_exit(1); } read_session_or_profile = true; pname = strrchr(*cl_hostname, '\\'); if (pname != NULL) { pname++; } else { pname = *cl_hostname; } profile_name = NewString(pname); Replace(profile_path, NewString(profile_name)); sl = strlen(profile_name); if (sl > session_suffix_len && !strcasecmp(profile_name + sl - session_suffix_len, session_suffix)) { profile_name[sl - session_suffix_len] = '\0'; #if defined(_WIN32) /*[*/ } else if (sl > session_short_suffix_len && !strcasecmp(profile_name + sl - session_short_suffix_len, session_short_suffix)) { profile_name[sl - session_short_suffix_len] = '\0'; #endif /*]*/ } *cl_hostname = appres.hostname; /* might be NULL */ } else { /* There is no session file. */ /* For c3270 only, read in the c3270 profile (~/.c3270pro). */ if (merge_profilep != NULL) { read_session_or_profile = (*merge_profilep)(); } /* * If there was a hostname resource defined somewhere, but not * as a positional command-line argument, pretend it was one, * so we will connect to it at start-up. */ if (*cl_hostname == NULL && appres.hostname != NULL) { *cl_hostname = appres.hostname; } } /* * Now parse the command-line arguments again, so they take * precedence over the session file or profile. */ if (read_session_or_profile) { parse_options(&xargc, xargv); parse_set_clear(&xargc, xargv); } /* Can't free xcmd, parts of it are still in use. */ Free((char *)xargv); /* * All right, we have all of the resources defined. * Sort out the contradictory and implicit settings. */ if (appres.apl_mode) { appres.charset = Apl; } if (*cl_hostname == NULL) { appres.once = false; } if (!appres.debug_tracing) { /* debug_tracing was explicitly cleared */ set_toggle(TRACING, false); } #if defined(_WIN32) /*[*/ if (appres.utf8) { /* utf8 overrides local_cp */ appres.local_cp = CP_UTF8; } #endif /*]*/ return argc; }