This commit was generated by cvs2svn to compensate for changes in r6453,
[chise/xemacs-chise.git.1] / 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 *p;
45   char modname[MAX_PATH];
46
47   if (!GetModuleFileName (NULL, modname, MAX_PATH))
48     goto error;
49   if ((p = strrchr (modname, '\\')) == NULL)
50     goto error;
51   *p = 0;
52
53   new_cmdline = alloca (MAX_PATH + strlen (cmdline) + 1);
54   strcpy (new_cmdline, modname);
55
56 #ifdef CHOOSE_NEWEST_EXE
57   {
58     /* Silly hack to allow new versions to be installed on
59        server even when current version is in use. */
60
61     char * best_name = alloca (MAX_PATH + 1);
62     FILETIME best_time = {0,0};
63     WIN32_FIND_DATA wfd;
64     HANDLE fh;
65     p = new_cmdline + strlen (new_cmdline);
66     strcpy (p, "\\xemacs*.exe ");
67     fh = FindFirstFile (new_cmdline, &wfd);
68     if (fh == INVALID_HANDLE_VALUE)
69       goto error;
70     do
71       {
72         if (wfd.ftLastWriteTime.dwHighDateTime > best_time.dwHighDateTime
73             || (wfd.ftLastWriteTime.dwHighDateTime == best_time.dwHighDateTime
74                 && wfd.ftLastWriteTime.dwLowDateTime > best_time.dwLowDateTime))
75           {
76             best_time = wfd.ftLastWriteTime;
77             strcpy (best_name, wfd.cFileName);
78           }
79       }
80     while (FindNextFile (fh, &wfd));
81     FindClose (fh);
82     *p++ = '\\';
83     strcpy (p, best_name);
84     strcat (p, " ");
85   }
86 #else
87 #if defined(__CYGWIN32__)
88   {
89     struct stat stbuf;
90     char sym_link_name[MAX_PATH+1], real_name[MAX_PATH+1];
91     
92     strcpy(sym_link_name, new_cmdline);
93     strcat(sym_link_name, "\\xemacs");
94     if (lstat(sym_link_name, &stbuf) == 0)
95       {
96         if ((stbuf.st_mode & S_IFLNK) == S_IFLNK)
97           {
98             if (readlink(sym_link_name, real_name, sizeof(real_name)) == -1)
99               {
100                 MessageBox (NULL, "Error reading symbolic link for xemacs",
101                             "Error", MB_ICONSTOP);
102                 return 1;
103               }
104             else
105               {
106                 strcat(new_cmdline, "\\");
107                 strcat(new_cmdline, real_name);
108                 strcat(new_cmdline, " ");
109               }
110           }
111         else
112           strcat(new_cmdline, "\\xemacs ");
113       }
114     else
115       {
116         MessageBox (NULL, "can't locate XEmacs executable",
117                     "Error", MB_ICONSTOP);
118         return 1;
119       }
120   }
121 #else                                   
122   strcat (new_cmdline, "\\xemacs.exe ");
123 #endif
124 #endif
125
126   /* Append original arguments if any; first look for -wait as first
127      argument, and apply that ourselves.  */
128   if (strncmp (cmdline, "-wait", 5) == 0)
129     {
130       wait_for_child = TRUE;
131       cmdline += 5;
132     }
133   strcat (new_cmdline, cmdline);
134
135   /* Set emacs_dir variable if runemacs was in "%emacs_dir%\bin".  */
136   if ((p = strrchr (modname, '\\')) && stricmp (p, "\\bin") == 0)
137     {
138       *p = 0;
139       for (p = modname; *p; p++)
140         if (*p == '\\') *p = '/';
141       SetEnvironmentVariable ("emacs_dir", modname);
142     }
143
144   memset (&start, 0, sizeof (start));
145   start.cb = sizeof (start);
146   start.dwFlags = STARTF_USESHOWWINDOW;
147   start.wShowWindow = SW_HIDE;
148
149   sec_attrs.nLength = sizeof (sec_attrs);
150   sec_attrs.lpSecurityDescriptor = NULL;
151   sec_attrs.bInheritHandle = FALSE;
152
153   if (CreateProcess (NULL, new_cmdline, &sec_attrs, NULL, TRUE, 0,
154                      NULL, NULL, &start, &child))
155     {
156       if (wait_for_child)
157         {
158           WaitForSingleObject (child.hProcess, INFINITE);
159           GetExitCodeProcess (child.hProcess, &ret_code);
160         }
161       CloseHandle (child.hThread);
162       CloseHandle (child.hProcess);
163     }
164   else
165     goto error;
166   return (int) ret_code;
167
168 error:
169   MessageBox (NULL, "Could not start XEmacs.", "Error", MB_ICONSTOP);
170   return 1;
171 }