Warn if two .exes conflict with each other and the second does not
[wine/multimedia.git] / console / xterm.c
blobcb675f793b9b9f3fd4fa2a1d93b01ed29321815e
1 /* xterm.c */
3 /* This "driver" is designed to go on top of an existing driver
4 to provide support for features only present if using an
5 xterm or compatible program for your console output. It should
6 inlcude such features as resizing, separation of output from the
7 standard wine console, and a configurable title bar for
8 Win32 console. */
9 /* Right now, it doesn't have any "special" features */
11 #include <signal.h>
12 #include <sys/ioctl.h>
13 #include <fcntl.h>
14 #include <unistd.h>
15 #include <termios.h>
16 #include <errno.h>
18 #include "windows.h"
19 #include "console.h"
20 #include "debug.h"
22 static BOOL32 wine_create_console(FILE **master, FILE **slave, int *pid);
23 static FILE *wine_openpty(FILE **master, FILE **slave, char *name,
24 struct termios *term, struct winsize *winsize);
26 /* The console -- I chose to keep the master and slave
27 * (UNIX) file descriptors around in case they are needed for
28 * ioctls later. The pid is needed to destroy the xterm on close
30 typedef struct _XTERM_CONSOLE {
31 FILE *master; /* xterm side of pty */
32 FILE *slave; /* wine side of pty */
33 int pid; /* xterm's pid, -1 if no xterm */
34 } XTERM_CONSOLE;
36 static XTERM_CONSOLE xterm_console;
38 CONSOLE_device chain;
39 FILE *old_in, *old_out;
41 void XTERM_Start()
43 /* Here, this is a supplementary driver so we should remember to call
44 the chain. */
45 chain.init = driver.init;
46 driver.init = XTERM_Init;
48 chain.close = driver.close;
49 driver.close = XTERM_Close;
52 void XTERM_Init()
54 wine_create_console(&xterm_console.master, &xterm_console.slave,
55 &xterm_console.pid);
57 old_in = driver.console_in;
58 driver.console_in = xterm_console.slave;
60 old_out = driver.console_out;
61 driver.console_out = xterm_console.slave;
63 /* Then call the chain... */
64 if (chain.init)
65 chain.init();
68 void XTERM_Close()
70 /* Call the chain first... */
71 if (chain.close)
72 chain.close();
74 driver.console_in = old_in;
75 driver.console_out = old_out;
77 /* make sure a xterm exists to kill */
78 if (xterm_console.pid != -1) {
79 kill(xterm_console.pid, SIGTERM);
83 /**
84 * It looks like the openpty that comes with glibc in RedHat 5.0
85 * is buggy (second call returns what looks like a dup of 0 and 1
86 * instead of a new pty), this is a generic replacement.
88 /** Can't we determine this using autoconf?
91 static FILE *wine_openpty(FILE **master, FILE **slave, char *name,
92 struct termios *term, struct winsize *winsize)
94 FILE *fdm, *fds;
95 char *ptr1, *ptr2;
96 char pts_name[512];
98 strcpy (pts_name, "/dev/ptyXY");
99 for (ptr1 = "pqrstuvwxyzPQRST"; *ptr1 != 0; ptr1++) {
100 pts_name[8] = *ptr1;
101 for (ptr2 = "0123456789abcdef"; *ptr2 != 0; ptr2++) {
102 pts_name[9] = *ptr2;
104 if ((fdm = fopen(pts_name, "r+")) == NULL) {
105 if (errno == ENOENT)
106 return (FILE *) -1;
107 else
108 continue;
110 pts_name[5] = 't';
111 if ((fds = fopen(pts_name, "r+")) == NULL) {
112 pts_name[5] = 'p';
113 continue;
115 *master = fdm;
116 *slave = fds;
118 if (term != NULL)
119 tcsetattr((*slave)->_fileno, TCSANOW, term);
120 if (winsize != NULL)
121 ioctl((*slave)->_fileno, TIOCSWINSZ, winsize);
123 if (name != NULL)
124 strcpy(name, pts_name);
125 return fds;
128 return (FILE *) -1;
131 static BOOL32 wine_create_console(FILE **master, FILE **slave, int *pid)
133 struct termios term;
134 char buf[1024];
135 char c = '\0';
136 int status = 0;
137 int i;
139 if (tcgetattr(0, &term) < 0) return FALSE;
140 term.c_lflag |= ICANON;
141 term.c_lflag &= ~ECHO;
142 if (wine_openpty(master, slave, NULL, &term, NULL) < 0)
143 return FALSE;
145 if ((*pid=fork()) == 0) {
146 tcsetattr((*slave)->_fileno, TCSADRAIN, &term);
147 sprintf(buf, "-Sxx%d", (*master)->_fileno);
148 execlp("xterm", "xterm", buf, NULL);
149 ERR(console, "error creating AllocConsole xterm\n");
150 exit(1);
153 /* most xterms like to print their window ID when used with -S;
154 * read it and continue before the user has a chance...
155 * NOTE: this is the reason we started xterm with ECHO off,
156 * we'll turn it back on below
159 for (i=0; c!='\n'; (status=fread(&c, 1, 1, *slave)), i++) {
160 if (status == -1 && c == '\0') {
161 /* wait for xterm to be created */
162 usleep(100);
164 if (i > 10000) {
165 WARN(console, "can't read xterm WID\n");
166 kill(*pid, SIGKILL);
167 return FALSE;
170 term.c_lflag |= ECHO;
171 tcsetattr((*master)->_fileno, TCSADRAIN, &term);
173 return TRUE;