Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mRemoteNG/PuTTYNG.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'unix/gtkmain.c')
-rw-r--r--unix/gtkmain.c673
1 files changed, 0 insertions, 673 deletions
diff --git a/unix/gtkmain.c b/unix/gtkmain.c
deleted file mode 100644
index ec8f7da4..00000000
--- a/unix/gtkmain.c
+++ /dev/null
@@ -1,673 +0,0 @@
-/*
- * gtkmain.c: the common main-program code between the straight-up
- * Unix PuTTY and pterm, which they do not share with the
- * multi-session gtkapp.c.
- */
-
-#define _GNU_SOURCE
-
-#include <string.h>
-#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
-#include <signal.h>
-#include <stdio.h>
-#include <time.h>
-#include <errno.h>
-#include <locale.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <gtk/gtk.h>
-#if !GTK_CHECK_VERSION(3,0,0)
-#include <gdk/gdkkeysyms.h>
-#endif
-
-#if GTK_CHECK_VERSION(2,0,0)
-#include <gtk/gtkimmodule.h>
-#endif
-
-#define MAY_REFER_TO_GTK_IN_HEADERS
-
-#include "putty.h"
-#include "terminal.h"
-#include "gtkcompat.h"
-#include "gtkfont.h"
-#include "gtkmisc.h"
-
-#ifndef NOT_X_WINDOWS
-#include <gdk/gdkx.h>
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
-#include <X11/Xatom.h>
-#include "x11misc.h"
-#endif
-
-static char *progname, **gtkargvstart;
-static int ngtkargs;
-
-static const char *app_name = "pterm";
-
-char *x_get_default(const char *key)
-{
-#ifndef NOT_X_WINDOWS
- Display *disp;
- if ((disp = get_x11_display()) == NULL)
- return NULL;
- return XGetDefault(disp, app_name, key);
-#else
- return NULL;
-#endif
-}
-
-void fork_and_exec_self(int fd_to_close, ...)
-{
- /*
- * Re-execing ourself is not an exact science under Unix. I do
- * the best I can by using /proc/self/exe if available and by
- * assuming argv[0] can be found on $PATH if not.
- *
- * Note that we also have to reconstruct the elements of the
- * original argv which gtk swallowed, since the user wants the
- * new session to appear on the same X display as the old one.
- */
- char **args;
- va_list ap;
- int i, n;
- int pid;
-
- /*
- * Collect the arguments with which to re-exec ourself.
- */
- va_start(ap, fd_to_close);
- n = 2; /* progname and terminating NULL */
- n += ngtkargs;
- while (va_arg(ap, char *) != NULL)
- n++;
- va_end(ap);
-
- args = snewn(n, char *);
- args[0] = progname;
- args[n-1] = NULL;
- for (i = 0; i < ngtkargs; i++)
- args[i+1] = gtkargvstart[i];
-
- i++;
- va_start(ap, fd_to_close);
- while ((args[i++] = va_arg(ap, char *)) != NULL);
- va_end(ap);
-
- assert(i == n);
-
- /*
- * Do the double fork.
- */
- pid = fork();
- if (pid < 0) {
- perror("fork");
- sfree(args);
- return;
- }
-
- if (pid == 0) {
- int pid2 = fork();
- if (pid2 < 0) {
- perror("fork");
- _exit(1);
- } else if (pid2 > 0) {
- /*
- * First child has successfully forked second child. My
- * Work Here Is Done. Note the use of _exit rather than
- * exit: the latter appears to cause destroy messages
- * to be sent to the X server. I suspect gtk uses
- * atexit.
- */
- _exit(0);
- }
-
- /*
- * If we reach here, we are the second child, so we now
- * actually perform the exec.
- */
- if (fd_to_close >= 0)
- close(fd_to_close);
-
- execv("/proc/self/exe", args);
- execvp(progname, args);
- perror("exec");
- _exit(127);
-
- } else {
- int status;
- sfree(args);
- waitpid(pid, &status, 0);
- }
-
-}
-
-void launch_duplicate_session(Conf *conf)
-{
- /*
- * For this feature we must marshal conf and (possibly) pty_argv
- * into a byte stream, create a pipe, and send this byte stream
- * to the child through the pipe.
- */
- int i, ret;
- strbuf *serialised;
- char option[80];
- int pipefd[2];
-
- if (pipe(pipefd) < 0) {
- perror("pipe");
- return;
- }
-
- serialised = strbuf_new();
-
- conf_serialise(BinarySink_UPCAST(serialised), conf);
- if (use_pty_argv && pty_argv)
- for (i = 0; pty_argv[i]; i++)
- put_asciz(serialised, pty_argv[i]);
-
- sprintf(option, "---[%d,%zu]", pipefd[0], serialised->len);
- noncloexec(pipefd[0]);
- fork_and_exec_self(pipefd[1], option, NULL);
- close(pipefd[0]);
-
- i = ret = 0;
- while (i < serialised->len &&
- (ret = write(pipefd[1], serialised->s + i,
- serialised->len - i)) > 0)
- i += ret;
- if (ret < 0)
- perror("write to pipe");
- close(pipefd[1]);
- strbuf_free(serialised);
-}
-
-void launch_new_session(void)
-{
- fork_and_exec_self(-1, NULL);
-}
-
-void launch_saved_session(const char *str)
-{
- fork_and_exec_self(-1, "-load", str, NULL);
-}
-
-int read_dupsession_data(Conf *conf, char *arg)
-{
- int fd, i, ret, size;
- char *data;
- BinarySource src[1];
-
- if (sscanf(arg, "---[%d,%d]", &fd, &size) != 2) {
- fprintf(stderr, "%s: malformed magic argument `%s'\n", appname, arg);
- exit(1);
- }
-
- data = snewn(size, char);
- i = ret = 0;
- while (i < size && (ret = read(fd, data + i, size - i)) > 0)
- i += ret;
- if (ret < 0) {
- perror("read from pipe");
- exit(1);
- } else if (i < size) {
- fprintf(stderr, "%s: unexpected EOF in Duplicate Session data\n",
- appname);
- exit(1);
- }
-
- BinarySource_BARE_INIT(src, data, size);
- if (!conf_deserialise(conf, src)) {
- fprintf(stderr, "%s: malformed Duplicate Session data\n", appname);
- exit(1);
- }
- if (use_pty_argv) {
- int pty_argc = 0;
- size_t argv_startpos = src->pos;
-
- while (get_asciz(src), !get_err(src))
- pty_argc++;
-
- src->err = BSE_NO_ERROR;
-
- if (pty_argc > 0) {
- src->pos = argv_startpos;
-
- pty_argv = snewn(pty_argc + 1, char *);
- pty_argv[pty_argc] = NULL;
- for (i = 0; i < pty_argc; i++)
- pty_argv[i] = dupstr(get_asciz(src));
- }
- }
-
- if (get_err(src) || get_avail(src) > 0) {
- fprintf(stderr, "%s: malformed Duplicate Session data\n", appname);
- exit(1);
- }
-
- sfree(data);
- return 0;
-}
-
-static void help(FILE *fp) {
- if(fprintf(fp,
-"pterm option summary:\n"
-"\n"
-" --display DISPLAY Specify X display to use (note '--')\n"
-" -name PREFIX Prefix when looking up resources (default: pterm)\n"
-" -fn FONT Normal text font\n"
-" -fb FONT Bold text font\n"
-" -geometry GEOMETRY Position and size of window (size in characters)\n"
-" -sl LINES Number of lines of scrollback\n"
-" -fg COLOUR, -bg COLOUR Foreground/background colour\n"
-" -bfg COLOUR, -bbg COLOUR Foreground/background bold colour\n"
-" -cfg COLOUR, -bfg COLOUR Foreground/background cursor colour\n"
-" -T TITLE Window title\n"
-" -ut, +ut Do(default) or do not update utmp\n"
-" -ls, +ls Do(default) or do not make shell a login shell\n"
-" -sb, +sb Do(default) or do not display a scrollbar\n"
-" -log PATH, -sessionlog PATH Log all output to a file\n"
-" -nethack Map numeric keypad to hjklyubn direction keys\n"
-" -xrm RESOURCE-STRING Set an X resource\n"
-" -e COMMAND [ARGS...] Execute command (consumes all remaining args)\n"
- ) < 0 || fflush(fp) < 0) {
- perror("output error");
- exit(1);
- }
-}
-
-static void version(FILE *fp) {
- char *buildinfo_text = buildinfo("\n");
- if(fprintf(fp, "%s: %s\n%s\n", appname, ver, buildinfo_text) < 0 ||
- fflush(fp) < 0) {
- perror("output error");
- exit(1);
- }
- sfree(buildinfo_text);
-}
-
-static const char *geometry_string;
-
-void cmdline_error(const char *p, ...)
-{
- va_list ap;
- fprintf(stderr, "%s: ", appname);
- va_start(ap, p);
- vfprintf(stderr, p, ap);
- va_end(ap);
- fputc('\n', stderr);
- exit(1);
-}
-
-void window_setup_error(const char *errmsg)
-{
- fprintf(stderr, "%s: %s\n", appname, errmsg);
- exit(1);
-}
-
-bool do_cmdline(int argc, char **argv, bool do_everything, Conf *conf)
-{
- bool err = false;
- char *val;
-
- /*
- * Macros to make argument handling easier.
- *
- * Note that because they need to call `continue', they cannot be
- * contained in the usual do {...} while (0) wrapper to make them
- * syntactically single statements. I use the alternative if (1)
- * {...} else ((void)0).
- */
-#define EXPECTS_ARG if (1) { \
- if (--argc <= 0) { \
- err = true; \
- fprintf(stderr, "%s: %s expects an argument\n", appname, p); \
- continue; \
- } else \
- val = *++argv; \
- } else ((void)0)
-#define SECOND_PASS_ONLY if (1) { \
- if (!do_everything) \
- continue; \
- } else ((void)0)
-
- while (--argc > 0) {
- const char *p = *++argv;
- int ret;
-
- /*
- * Shameless cheating. Debian requires all X terminal
- * emulators to support `-T title'; but
- * cmdline_process_param will eat -T (it means no-pty) and
- * complain that pterm doesn't support it. So, in pterm
- * only, we convert -T into -title.
- */
- if ((cmdline_tooltype & TOOLTYPE_NONNETWORK) &&
- !strcmp(p, "-T"))
- p = "-title";
-
- ret = cmdline_process_param(p, (argc > 1 ? argv[1] : NULL),
- do_everything ? 1 : -1, conf);
-
- if (ret == -2) {
- cmdline_error("option \"%s\" requires an argument", p);
- } else if (ret == 2) {
- --argc, ++argv; /* skip next argument */
- continue;
- } else if (ret == 1) {
- continue;
- }
-
- if (!strcmp(p, "-fn") || !strcmp(p, "-font")) {
- FontSpec *fs;
- EXPECTS_ARG;
- SECOND_PASS_ONLY;
- fs = fontspec_new(val);
- conf_set_fontspec(conf, CONF_font, fs);
- fontspec_free(fs);
-
- } else if (!strcmp(p, "-fb")) {
- FontSpec *fs;
- EXPECTS_ARG;
- SECOND_PASS_ONLY;
- fs = fontspec_new(val);
- conf_set_fontspec(conf, CONF_boldfont, fs);
- fontspec_free(fs);
-
- } else if (!strcmp(p, "-fw")) {
- FontSpec *fs;
- EXPECTS_ARG;
- SECOND_PASS_ONLY;
- fs = fontspec_new(val);
- conf_set_fontspec(conf, CONF_widefont, fs);
- fontspec_free(fs);
-
- } else if (!strcmp(p, "-fwb")) {
- FontSpec *fs;
- EXPECTS_ARG;
- SECOND_PASS_ONLY;
- fs = fontspec_new(val);
- conf_set_fontspec(conf, CONF_wideboldfont, fs);
- fontspec_free(fs);
-
- } else if (!strcmp(p, "-cs")) {
- EXPECTS_ARG;
- SECOND_PASS_ONLY;
- conf_set_str(conf, CONF_line_codepage, val);
-
- } else if (!strcmp(p, "-geometry")) {
- EXPECTS_ARG;
- SECOND_PASS_ONLY;
- geometry_string = val;
- } else if (!strcmp(p, "-sl")) {
- EXPECTS_ARG;
- SECOND_PASS_ONLY;
- conf_set_int(conf, CONF_savelines, atoi(val));
-
- } else if (!strcmp(p, "-fg") || !strcmp(p, "-bg") ||
- !strcmp(p, "-bfg") || !strcmp(p, "-bbg") ||
- !strcmp(p, "-cfg") || !strcmp(p, "-cbg")) {
- EXPECTS_ARG;
- SECOND_PASS_ONLY;
-
- {
-#if GTK_CHECK_VERSION(3,0,0)
- GdkRGBA rgba;
- bool success = gdk_rgba_parse(&rgba, val);
-#else
- GdkColor col;
- bool success = gdk_color_parse(val, &col);
-#endif
-
- if (!success) {
- err = true;
- fprintf(stderr, "%s: unable to parse colour \"%s\"\n",
- appname, val);
- } else {
-#if GTK_CHECK_VERSION(3,0,0)
- int r = rgba.red * 255;
- int g = rgba.green * 255;
- int b = rgba.blue * 255;
-#else
- int r = col.red / 256;
- int g = col.green / 256;
- int b = col.blue / 256;
-#endif
-
- int index;
- index = (!strcmp(p, "-fg") ? 0 :
- !strcmp(p, "-bg") ? 2 :
- !strcmp(p, "-bfg") ? 1 :
- !strcmp(p, "-bbg") ? 3 :
- !strcmp(p, "-cfg") ? 4 :
- !strcmp(p, "-cbg") ? 5 : -1);
- assert(index != -1);
-
- conf_set_int_int(conf, CONF_colours, index*3+0, r);
- conf_set_int_int(conf, CONF_colours, index*3+1, g);
- conf_set_int_int(conf, CONF_colours, index*3+2, b);
- }
- }
-
- } else if (use_pty_argv && !strcmp(p, "-e")) {
- /* This option swallows all further arguments. */
- if (!do_everything)
- break;
-
- if (--argc > 0) {
- int i;
- pty_argv = snewn(argc+1, char *);
- ++argv;
- for (i = 0; i < argc; i++)
- pty_argv[i] = argv[i];
- pty_argv[argc] = NULL;
- break; /* finished command-line processing */
- } else
- err = true, fprintf(stderr, "%s: -e expects an argument\n",
- appname);
-
- } else if (!strcmp(p, "-title")) {
- EXPECTS_ARG;
- SECOND_PASS_ONLY;
- conf_set_str(conf, CONF_wintitle, val);
-
- } else if (!strcmp(p, "-log")) {
- Filename *fn;
- EXPECTS_ARG;
- SECOND_PASS_ONLY;
- fn = filename_from_str(val);
- conf_set_filename(conf, CONF_logfilename, fn);
- conf_set_int(conf, CONF_logtype, LGTYP_DEBUG);
- filename_free(fn);
-
- } else if (!strcmp(p, "-ut-") || !strcmp(p, "+ut")) {
- SECOND_PASS_ONLY;
- conf_set_bool(conf, CONF_stamp_utmp, false);
-
- } else if (!strcmp(p, "-ut")) {
- SECOND_PASS_ONLY;
- conf_set_bool(conf, CONF_stamp_utmp, true);
-
- } else if (!strcmp(p, "-ls-") || !strcmp(p, "+ls")) {
- SECOND_PASS_ONLY;
- conf_set_bool(conf, CONF_login_shell, false);
-
- } else if (!strcmp(p, "-ls")) {
- SECOND_PASS_ONLY;
- conf_set_bool(conf, CONF_login_shell, true);
-
- } else if (!strcmp(p, "-nethack")) {
- SECOND_PASS_ONLY;
- conf_set_bool(conf, CONF_nethack_keypad, true);
-
- } else if (!strcmp(p, "-sb-") || !strcmp(p, "+sb")) {
- SECOND_PASS_ONLY;
- conf_set_bool(conf, CONF_scrollbar, false);
-
- } else if (!strcmp(p, "-sb")) {
- SECOND_PASS_ONLY;
- conf_set_bool(conf, CONF_scrollbar, true);
-
- } else if (!strcmp(p, "-name")) {
- EXPECTS_ARG;
- app_name = val;
-
- } else if (!strcmp(p, "-xrm")) {
- EXPECTS_ARG;
- provide_xrm_string(val, appname);
-
- } else if(!strcmp(p, "-help") || !strcmp(p, "--help")) {
- help(stdout);
- exit(0);
-
- } else if(!strcmp(p, "-version") || !strcmp(p, "--version")) {
- version(stdout);
- exit(0);
-
- } else if (!strcmp(p, "-pgpfp")) {
- pgp_fingerprints();
- exit(1);
-
- } else if (p[0] != '-') {
- /* Non-option arguments not handled by cmdline.c are errors. */
- if (do_everything) {
- err = true;
- fprintf(stderr, "%s: unexpected non-option argument '%s'\n",
- appname, p);
- }
-
- } else {
- err = true;
- fprintf(stderr, "%s: unrecognized option '%s'\n", appname, p);
- }
- }
-
- return err;
-}
-
-GtkWidget *make_gtk_toplevel_window(GtkFrontend *frontend)
-{
- return gtk_window_new(GTK_WINDOW_TOPLEVEL);
-}
-
-const bool buildinfo_gtk_relevant = true;
-
-struct post_initial_config_box_ctx {
- Conf *conf;
- const char *geometry_string;
-};
-
-static void post_initial_config_box(void *vctx, int result)
-{
- struct post_initial_config_box_ctx ctx =
- *(struct post_initial_config_box_ctx *)vctx;
- sfree(vctx);
-
- if (result > 0) {
- new_session_window(ctx.conf, ctx.geometry_string);
- } else {
- /* In this main(), which only runs one session in total, a
- * negative result from the initial config box means we simply
- * terminate. */
- conf_free(ctx.conf);
- gtk_main_quit();
- }
-}
-
-void session_window_closed(void)
-{
- gtk_main_quit();
-}
-
-int main(int argc, char **argv)
-{
- Conf *conf;
- bool need_config_box;
-
- setlocale(LC_CTYPE, "");
-
- /* Call the function in ux{putty,pterm}.c to do app-type
- * specific setup */
- setup(true); /* true means we are a one-session process */
-
- progname = argv[0];
-
- /*
- * Copy the original argv before letting gtk_init fiddle with
- * it. It will be required later.
- */
- {
- int i, oldargc;
- gtkargvstart = snewn(argc-1, char *);
- for (i = 1; i < argc; i++)
- gtkargvstart[i-1] = dupstr(argv[i]);
- oldargc = argc;
- gtk_init(&argc, &argv);
- ngtkargs = oldargc - argc;
- }
-
- conf = conf_new();
-
- gtkcomm_setup();
-
- /*
- * Block SIGPIPE: if we attempt Duplicate Session or similar and
- * it falls over in some way, we certainly don't want SIGPIPE
- * terminating the main pterm/PuTTY. However, we'll have to
- * unblock it again when pterm forks.
- */
- block_signal(SIGPIPE, true);
-
- if (argc > 1 && !strncmp(argv[1], "---", 3)) {
- read_dupsession_data(conf, argv[1]);
- /* Splatter this argument so it doesn't clutter a ps listing */
- smemclr(argv[1], strlen(argv[1]));
-
- assert(!dup_check_launchable || conf_launchable(conf));
- need_config_box = false;
- } else {
- if (do_cmdline(argc, argv, false, conf))
- exit(1); /* pre-defaults pass to get -class */
- do_defaults(NULL, conf);
- if (do_cmdline(argc, argv, true, conf))
- exit(1); /* post-defaults, do everything */
-
- cmdline_run_saved(conf);
-
- if (cmdline_tooltype & TOOLTYPE_HOST_ARG)
- need_config_box = !cmdline_host_ok(conf);
- else
- need_config_box = false;
- }
-
- if (need_config_box) {
- /*
- * Put up the initial config box, which will pass the provided
- * parameters (with conf updated) to new_session_window() when
- * (if) the user selects Open. Or it might close without
- * creating a session window, if the user selects Cancel. Or
- * it might just create the session window immediately if this
- * is a pterm-style app which doesn't have an initial config
- * box at all.
- */
- struct post_initial_config_box_ctx *ctx =
- snew(struct post_initial_config_box_ctx);
- ctx->conf = conf;
- ctx->geometry_string = geometry_string;
- initial_config_box(conf, post_initial_config_box, ctx);
- } else {
- /*
- * No initial config needed; just create the session window
- * now.
- */
- new_session_window(conf, geometry_string);
- }
-
- gtk_main();
-
- return 0;
-}