This commit was manufactured by cvs2svn to create branch 'XEmacs-21_2'.
[chise/xemacs-chise.git-] / nt / runemacs.c
1 /*
2   Simple program to start Emacs with its console window hidden.
3
4   This program is provided purely for convenience, since most users will
5   use Emacs in windowing (GUI) mode, and will not want to have an extra
6   console window lying around.  */
7
8 /*
9    You may want to define this if you want to be able to install updated
10    emacs binaries even when other users are using the current version.
11    The problem with some file servers (notably Novell) is that an open
12    file cannot be overwritten, deleted, or even renamed.  So if someone
13    is running emacs.exe already, you cannot install a newer version.
14    By defining CHOOSE_NEWEST_EXE, you can name your new emacs.exe
15    something else which matches "emacs*.exe", and runemacs will
16    automatically select the newest emacs executeable in the bin directory.
17    (So you'll probably be able to delete the old version some hours/days
18    later).
19 */
20
21 /* #define CHOOSE_NEWEST_EXE */
22
23 #define WIN32
24
25 #include <windows.h>
26 #include <string.h>
27 #include <malloc.h>
28
29 #if defined(__CYGWIN32__)
30 #include <sys/types.h>
31 #include <sys/stat.h>
32 #endif
33
34 int WINAPI
35 WinMain (HINSTANCE hSelf, HINSTANCE hPrev, LPSTR cmdline, int nShow)
36 {
37   STARTUPINFO start;
38   SECURITY_ATTRIBUTES sec_attrs;
39   SECURITY_DESCRIPTOR sec_desc;
40   PROCESS_INFORMATION child;
41   int wait_for_child = FALSE;
42   DWORD ret_code = 0;
43   char *new_cmdline;
44   char *basename;
45   char *p;
46   char modname[MAX_PATH];
47
48   if (!GetModuleFileName (NULL, modname, MAX_PATH))
49     goto error;
50   if ((p = strrchr (modname, '\\')) == NULL)
51     goto error;
52
53   basename = alloca(strlen(p) + 1);
54   strcpy (basename, p + 1);
55   
56   *p = 0;
57
58   new_cmdline = alloca (MAX_PATH + strlen (cmdline) + 1);
59   strcpy (new_cmdline, modname);
60
61 #ifdef CHOOSE_NEWEST_EXE
62   {
63     /* Silly hack to allow new versions to be installed on
64        server even when current version is in use. */
65
66     char * best_name = alloca (MAX_PATH + 1);
67     FILETIME best_time = {0,0};
68     WIN32_FIND_DATA wfd;
69     HANDLE fh;
70     p = new_cmdline + strlen (new_cmdline);
71     strcpy (p, "\\xemacs*.exe ");
72     fh = FindFirstFile (new_cmdline, &wfd);
73     if (fh == INVALID_HANDLE_VALUE)
74       goto error;
75     do
76       {
77         if (wfd.ftLastWriteTime.dwHighDateTime > best_time.dwHighDateTime
78             || (wfd.ftLastWriteTime.dwHighDateTime == best_time.dwHighDateTime
79                 && wfd.ftLastWriteTime.dwLowDateTime > best_time.dwLowDateTime))
80           {
81             best_time = wfd.ftLastWriteTime;
82             strcpy (best_name, wfd.cFileName);
83           }
84       }
85     while (FindNextFile (fh, &wfd));
86     FindClose (fh);
87     *p++ = '\\';
88     strcpy (p, best_name);
89     strcat (p, " ");
90   }
91 #else
92 #if defined(__CYGWIN32__)
93   {
94     struct stat stbuf;
95     char sym_link_name[MAX_PATH+1], real_name[MAX_PATH+1];
96     
97     strcpy(sym_link_name, new_cmdline);
98     if (strcmp(basename, "rungnuclient.exe") == 0)
99       strcat(new_cmdline, "\\gnuclient.exe ");
100     else if (strcmp(basename, "runemacs.exe") == 0)
101       {
102         strcat(sym_link_name, "\\xemacs");
103           
104         if (lstat(sym_link_name, &stbuf) == 0)
105           {
106             if ((stbuf.st_mode & S_IFLNK) == S_IFLNK)
107               {
108                 if (readlink(sym_link_name, real_name, sizeof(real_name)) == -1)
109                   {
110                     MessageBox (NULL, "Error reading symbolic link for xemacs",
111                                 "Error", MB_ICONSTOP);
112                     return 1;
113                   }
114                 else
115                   {
116                     strcat(new_cmdline, "\\");
117                     strcat(new_cmdline, real_name);
118                     strcat(new_cmdline, " ");
119                   }
120               }
121             else
122               strcat(new_cmdline, "\\xemacs ");
123           }
124         else
125           {
126             MessageBox (NULL, "can't locate XEmacs executable",
127                         "Error", MB_ICONSTOP);
128             return 1;
129           }
130       }
131   }
132 #else                                   
133   if (strcmp(basename, "rungnuclient.exe") == 0)
134     strcat (new_cmdline, "\\gnuclient.exe ");
135   else 
136     strcat (new_cmdline, "\\xemacs.exe ");
137 #endif
138 #endif
139
140   /* Append original arguments if any; first look for -wait as first
141      argument, and apply that ourselves.  */
142   if (strncmp (cmdline, "-wait", 5) == 0)
143     {
144       wait_for_child = TRUE;
145       cmdline += 5;
146     }
147   strcat (new_cmdline, cmdline);
148
149   /* Set emacs_dir variable if runemacs was in "%emacs_dir%\bin".  */
150   if ((p = strrchr (modname, '\\')) && stricmp (p, "\\bin") == 0)
151     {
152       *p = 0;
153       for (p = modname; *p; p++)
154         if (*p == '\\') *p = '/';
155       SetEnvironmentVariable ("emacs_dir", modname);
156     }
157
158   memset (&start, 0, sizeof (start));
159   start.cb = sizeof (start);
160   start.dwFlags = STARTF_USESHOWWINDOW;
161   start.wShowWindow = SW_HIDE;
162
163   sec_attrs.nLength = sizeof (sec_attrs);
164   sec_attrs.lpSecurityDescriptor = NULL;
165   sec_attrs.bInheritHandle = FALSE;
166
167   if (CreateProcess (NULL, new_cmdline, &sec_attrs, NULL, TRUE, 0,
168                      NULL, NULL, &start, &child))
169     {
170       if (wait_for_child)
171         {
172           WaitForSingleObject (child.hProcess, INFINITE);
173           GetExitCodeProcess (child.hProcess, &ret_code);
174         }
175       CloseHandle (child.hThread);
176       CloseHandle (child.hProcess);
177     }
178   else
179     goto error;
180   return (int) ret_code;
181
182 error:
183   MessageBox (NULL, "Could not start XEmacs or gnuclient.", "Error", MB_ICONSTOP);
184   return 1;
185 }