root/arch/um/drivers/xterm.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. xterm_init
  2. xterm_setup
  3. xterm_open
  4. xterm_close

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
   4  */
   5 
   6 #include <stddef.h>
   7 #include <stdio.h>
   8 #include <stdlib.h>
   9 #include <unistd.h>
  10 #include <errno.h>
  11 #include <string.h>
  12 #include <termios.h>
  13 #include "chan_user.h"
  14 #include <os.h>
  15 #include <um_malloc.h>
  16 #include "xterm.h"
  17 
  18 struct xterm_chan {
  19         int pid;
  20         int helper_pid;
  21         char *title;
  22         int device;
  23         int raw;
  24         struct termios tt;
  25 };
  26 
  27 static void *xterm_init(char *str, int device, const struct chan_opts *opts)
  28 {
  29         struct xterm_chan *data;
  30 
  31         data = uml_kmalloc(sizeof(*data), UM_GFP_KERNEL);
  32         if (data == NULL)
  33                 return NULL;
  34         *data = ((struct xterm_chan) { .pid             = -1,
  35                                        .helper_pid      = -1,
  36                                        .device          = device,
  37                                        .title           = opts->xterm_title,
  38                                        .raw             = opts->raw } );
  39         return data;
  40 }
  41 
  42 /* Only changed by xterm_setup, which is a setup */
  43 static char *terminal_emulator = "xterm";
  44 static char *title_switch = "-T";
  45 static char *exec_switch = "-e";
  46 
  47 static int __init xterm_setup(char *line, int *add)
  48 {
  49         *add = 0;
  50         terminal_emulator = line;
  51 
  52         line = strchr(line, ',');
  53         if (line == NULL)
  54                 return 0;
  55 
  56         *line++ = '\0';
  57         if (*line)
  58                 title_switch = line;
  59 
  60         line = strchr(line, ',');
  61         if (line == NULL)
  62                 return 0;
  63 
  64         *line++ = '\0';
  65         if (*line)
  66                 exec_switch = line;
  67 
  68         return 0;
  69 }
  70 
  71 __uml_setup("xterm=", xterm_setup,
  72 "xterm=<terminal emulator>,<title switch>,<exec switch>\n"
  73 "    Specifies an alternate terminal emulator to use for the debugger,\n"
  74 "    consoles, and serial lines when they are attached to the xterm channel.\n"
  75 "    The values are the terminal emulator binary, the switch it uses to set\n"
  76 "    its title, and the switch it uses to execute a subprocess,\n"
  77 "    respectively.  The title switch must have the form '<switch> title',\n"
  78 "    not '<switch>=title'.  Similarly, the exec switch must have the form\n"
  79 "    '<switch> command arg1 arg2 ...'.\n"
  80 "    The default values are 'xterm=xterm,-T,-e'.  Values for gnome-terminal\n"
  81 "    are 'xterm=gnome-terminal,-t,-x'.\n\n"
  82 );
  83 
  84 static int xterm_open(int input, int output, int primary, void *d,
  85                       char **dev_out)
  86 {
  87         struct xterm_chan *data = d;
  88         int pid, fd, new, err;
  89         char title[256], file[] = "/tmp/xterm-pipeXXXXXX";
  90         char *argv[] = { terminal_emulator, title_switch, title, exec_switch,
  91                          OS_LIB_PATH "/uml/port-helper", "-uml-socket",
  92                          file, NULL };
  93 
  94         if (access(argv[4], X_OK) < 0)
  95                 argv[4] = "port-helper";
  96 
  97         /*
  98          * Check that DISPLAY is set, this doesn't guarantee the xterm
  99          * will work but w/o it we can be pretty sure it won't.
 100          */
 101         if (getenv("DISPLAY") == NULL) {
 102                 printk(UM_KERN_ERR "xterm_open: $DISPLAY not set.\n");
 103                 return -ENODEV;
 104         }
 105 
 106         /*
 107          * This business of getting a descriptor to a temp file,
 108          * deleting the file and closing the descriptor is just to get
 109          * a known-unused name for the Unix socket that we really
 110          * want.
 111          */
 112         fd = mkstemp(file);
 113         if (fd < 0) {
 114                 err = -errno;
 115                 printk(UM_KERN_ERR "xterm_open : mkstemp failed, errno = %d\n",
 116                        errno);
 117                 return err;
 118         }
 119 
 120         if (unlink(file)) {
 121                 err = -errno;
 122                 printk(UM_KERN_ERR "xterm_open : unlink failed, errno = %d\n",
 123                        errno);
 124                 close(fd);
 125                 return err;
 126         }
 127         close(fd);
 128 
 129         fd = os_create_unix_socket(file, sizeof(file), 1);
 130         if (fd < 0) {
 131                 printk(UM_KERN_ERR "xterm_open : create_unix_socket failed, "
 132                        "errno = %d\n", -fd);
 133                 return fd;
 134         }
 135 
 136         sprintf(title, data->title, data->device);
 137         pid = run_helper(NULL, NULL, argv);
 138         if (pid < 0) {
 139                 err = pid;
 140                 printk(UM_KERN_ERR "xterm_open : run_helper failed, "
 141                        "errno = %d\n", -err);
 142                 goto out_close1;
 143         }
 144 
 145         err = os_set_fd_block(fd, 0);
 146         if (err < 0) {
 147                 printk(UM_KERN_ERR "xterm_open : failed to set descriptor "
 148                        "non-blocking, err = %d\n", -err);
 149                 goto out_kill;
 150         }
 151 
 152         new = xterm_fd(fd, &data->helper_pid);
 153         if (new < 0) {
 154                 err = new;
 155                 printk(UM_KERN_ERR "xterm_open : os_rcv_fd failed, err = %d\n",
 156                        -err);
 157                 goto out_kill;
 158         }
 159 
 160         err = os_set_fd_block(new, 0);
 161         if (err) {
 162                 printk(UM_KERN_ERR "xterm_open : failed to set xterm "
 163                        "descriptor non-blocking, err = %d\n", -err);
 164                 goto out_close2;
 165         }
 166 
 167         CATCH_EINTR(err = tcgetattr(new, &data->tt));
 168         if (err) {
 169                 new = err;
 170                 goto out_close2;
 171         }
 172 
 173         if (data->raw) {
 174                 err = raw(new);
 175                 if (err) {
 176                         new = err;
 177                         goto out_close2;
 178                 }
 179         }
 180 
 181         unlink(file);
 182         data->pid = pid;
 183         *dev_out = NULL;
 184 
 185         return new;
 186 
 187  out_close2:
 188         close(new);
 189  out_kill:
 190         os_kill_process(pid, 1);
 191  out_close1:
 192         close(fd);
 193 
 194         return err;
 195 }
 196 
 197 static void xterm_close(int fd, void *d)
 198 {
 199         struct xterm_chan *data = d;
 200 
 201         if (data->pid != -1)
 202                 os_kill_process(data->pid, 1);
 203         data->pid = -1;
 204 
 205         if (data->helper_pid != -1)
 206                 os_kill_process(data->helper_pid, 0);
 207         data->helper_pid = -1;
 208 
 209         os_close_file(fd);
 210 }
 211 
 212 const struct chan_ops xterm_ops = {
 213         .type           = "xterm",
 214         .init           = xterm_init,
 215         .open           = xterm_open,
 216         .close          = xterm_close,
 217         .read           = generic_read,
 218         .write          = generic_write,
 219         .console_write  = generic_console_write,
 220         .window_size    = generic_window_size,
 221         .free           = generic_free,
 222         .winch          = 1,
 223 };

/* [<][>][^][v][top][bottom][index][help] */