1 /* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */
2 
3 #include <sys/types.h>
4 
5 #include <pobl/bl_def.h>    /* USE_WIN32API/HAVE_WINDOWS_H */
6 #include <pobl/bl_unistd.h> /* bl_getuid/bl_getgid */
7 #include <pobl/bl_conf_io.h>
8 #include <pobl/bl_privilege.h>
9 #include <pobl/bl_debug.h>
10 #include <pobl/bl_dlfcn.h>
11 #include <pobl/bl_mem.h> /* malloc */
12 
13 #ifdef HAVE_WINDOWS_H
14 #include <windows.h>
15 #endif
16 
17 #include "main_loop.h"
18 
19 #if defined(USE_WIN32API)
20 #define CONFIG_PATH "."
21 #elif defined(SYSCONFDIR)
22 #define CONFIG_PATH SYSCONFDIR
23 #else
24 #define CONFIG_PATH "/etc"
25 #endif
26 
27 #ifdef USE_WIN32API
28 #include <stdlib.h> /* _fmode */
29 #include <fcntl.h>  /* _O_BINARY */
30 static char *dummy_argv[] = {"mlterm", NULL};
31 #define argv (__argv ? __argv : dummy_argv)
32 #define argc __argc
33 #endif
34 
35 /* --- static functions --- */
36 
37 #if defined(__CYGWIN__) || defined(__MSYS__)
38 #ifdef __CYGWIN__
39 #define ENV_PCON "CYGWIN"
40 #else
41 #define ENV_PCON "MSYS"
42 #endif
43 
44 #include <stdlib.h> /* setenv */
45 
init_cygwin_env(void)46 static void init_cygwin_env(void) {
47   char *cur_val;
48   char *new_val;
49   size_t len;
50 
51   /*
52    * 'disable_pcon' variable in winsup/cygwin/global.cc disables win32 pseudo console.
53    * (See fhandler_pty_master::setup_pseudoconsole() in fhandler_tty.cc)
54    *
55    * If cur_len >= new_len, _addenv() in winsup/cygwin/environ.cc doesn't call parse_optons()
56    * which changes 'disable_pcon' variable according to the value of "CYGWIN" environmental
57    * variable.
58    *
59    * So call setenv() with not only "disable_pcon" but also the current value of "CYGWIN"
60    * environmental variable.
61    */
62 
63   if ((cur_val = getenv(ENV_PCON))) {
64     len = strlen(cur_val) + 1;
65   } else {
66     len = 0;
67   }
68 
69   /* Don't use alloca() here before bl_alloca_begin_stack_frame() is called in main_loop_start(). */
70   if ((new_val = malloc(len + 12 + 1))) {
71     if (cur_val) {
72       memcpy(new_val, cur_val, len - 1);
73       new_val[len - 1] = ' ';
74     }
75     strcpy(new_val + len, "disable_pcon");
76     setenv(ENV_PCON, new_val, 1);
77     free(new_val);
78   }
79 }
80 #endif
81 
82 #if defined(HAVE_WINDOWS_H) && !defined(USE_WIN32API)
83 
84 #include <stdio.h> /* sprintf */
85 #include <sys/utsname.h>
86 
87 #include <pobl/bl_util.h>
88 
check_console(void)89 static void check_console(void) {
90   int count;
91   HWND conwin;
92   char app_name[6 + DIGIT_STR_LEN(u_int) + 1];
93   HANDLE handle;
94 
95   if (!(handle = GetStdHandle(STD_OUTPUT_HANDLE)) || handle == INVALID_HANDLE_VALUE) {
96 #if 0
97     struct utsname name;
98     char *rel;
99 
100     if (uname(&name) == 0 && (rel = alloca(strlen(name.release) + 1))) {
101       char *p;
102 
103       if ((p = strchr(strcpy(rel, name.release), '.'))) {
104         int major;
105         int minor;
106 
107         *p = '\0';
108         major = atoi(rel);
109         rel = p + 1;
110 
111         if ((p = strchr(rel, '.'))) {
112           *p = '\0';
113           minor = atoi(rel);
114 
115           if (major >= 2 || (major == 1 && minor >= 7)) {
116             /*
117              * Mlterm works without console
118              * in cygwin 1.7 or later.
119              */
120             return;
121           }
122         }
123       }
124     }
125 
126     /* AllocConsole() after starting mlterm doesn't work on MSYS. */
127     if (!AllocConsole())
128 #endif
129     {
130       return;
131     }
132   }
133 
134   /* Hide allocated console window */
135 
136   sprintf(app_name, "mlterm%08x", (unsigned int)GetCurrentThreadId());
137   LockWindowUpdate(GetDesktopWindow());
138   SetConsoleTitle(app_name);
139 
140   for (count = 0; count < 20; count++) {
141     if ((conwin = FindWindow(NULL, app_name))) {
142       ShowWindowAsync(conwin, SW_HIDE);
143       break;
144     }
145 
146     Sleep(40);
147   }
148 
149   LockWindowUpdate(NULL);
150 }
151 
152 #else
153 
154 #define check_console() (1)
155 
156 #endif
157 
158 /* --- global functions --- */
159 
160 #ifdef USE_WIN32API
WinMain(HINSTANCE hinst,HINSTANCE hprev,char * cmdline,int cmdshow)161 int PASCAL WinMain(HINSTANCE hinst, HINSTANCE hprev, char *cmdline, int cmdshow)
162 #else
163 int main(int argc, char **argv)
164 #endif
165 {
166 #ifdef __CYGWIN__
167   init_cygwin_env();
168 #endif
169 
170 #if defined(USE_WIN32API) && defined(USE_LIBSSH2)
171   WSADATA wsadata;
172 
173   WSAStartup(MAKEWORD(2, 0), &wsadata);
174 #endif
175 
176 #ifdef USE_WIN32API
177   _fmode = _O_BINARY;
178 #endif
179 
180   check_console();
181 
182   /* Don't call before NSApplicationMain() */
183 #if !defined(USE_SDL2) || !defined(__APPLE__)
184   /* normal user */
185   bl_priv_change_euid(bl_getuid());
186   bl_priv_change_egid(bl_getgid());
187 #endif
188 
189   bl_set_sys_conf_dir(CONFIG_PATH);
190 
191 #if (defined(__NetBSD__) || defined(__OpenBSD__)) && defined(USE_FRAMEBUFFER)
192   /*
193    * XXX
194    * It performs well to read as large amount of data as possible
195    * on framebuffer on old machines.
196    */
197   vt_set_timeout_read_pty(0xffff); /* 65535 sec */
198 #endif
199 
200   if (!main_loop_init(argc, argv)) {
201 #ifdef DEBUG
202     bl_warn_printf(BL_DEBUG_TAG " ui_term_manager_init() failed.\n");
203 #endif
204 
205     return 1;
206   }
207 
208   main_loop_start();
209 
210   /*
211    * Stale utmp is left without this if the last window is closed and final()
212    * in vt_pty_unix.c is not called.
213    */
214   main_loop_final();
215 
216 #if defined(USE_WIN32API) && defined(USE_LIBSSH2)
217   WSACleanup();
218 #endif
219 
220   bl_dl_close_all();
221 
222   return 0;
223 }
224