2 * Copyright (c) 2001, Jan Nieuwenhuizen.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * A copy of the GNU General Public License can be found at
12 * Written by DJ Delorie <dj@cygnus.com>
13 * Jan Nieuwenhuizen <janneke@gnu.org>
17 /* The purpose of this file is to provide functions for the invocation
18 of install scripts. */
21 static const char *cvsid
=
29 #include "LogSingleton.h"
30 #include "filemanip.h"
32 #include "io_stream.h"
36 static String sh
= String();
37 static const char *cmd
= 0;
38 static OSVERSIONINFO verinfo
;
40 static const char *shells
[] = {
51 for (int i
= 0; shells
[i
]; i
++)
53 sh
= backslash (cygpath (shells
[i
]));
54 if (_access (sh
.cstr_oneuse(), 0) == 0)
59 char old_path
[_MAX_PATH
];
60 GetEnvironmentVariable ("PATH", old_path
, sizeof (old_path
));
61 SetEnvironmentVariable ("PATH", backslash (cygpath ("/bin") + ";" +
62 cygpath ("/usr/bin") + ";" +
63 old_path
).cstr_oneuse());
64 SetEnvironmentVariable ("CYGWINROOT", get_root_dir ().cstr_oneuse());
66 verinfo
.dwOSVersionInfoSize
= sizeof (verinfo
);
67 GetVersionEx (&verinfo
);
69 switch (verinfo
.dwPlatformId
)
71 case VER_PLATFORM_WIN32_NT
:
74 case VER_PLATFORM_WIN32_WINDOWS
:
86 OutputLog (String
const &filename
);
88 HANDLE
handle () { return _handle
; }
89 BOOL
isValid () { return _handle
!= INVALID_HANDLE_VALUE
; }
90 BOOL
isEmpty () { return GetFileSize (_handle
, NULL
) == 0; }
91 friend std::ostream
&operator<< (std::ostream
&, OutputLog
&);
93 enum { BUFLEN
= 1000 };
96 void out_to(std::ostream
&);
99 OutputLog::OutputLog (String
const &filename
)
100 : _handle(INVALID_HANDLE_VALUE
), _filename(filename
)
102 if (!_filename
.size())
105 SECURITY_ATTRIBUTES sa
;
106 memset (&sa
, 0, sizeof (sa
));
107 sa
.nLength
= sizeof (sa
);
108 sa
.bInheritHandle
= TRUE
;
109 sa
.lpSecurityDescriptor
= NULL
;
111 if (mkdir_p (0, backslash (cygpath (_filename
)).cstr_oneuse()))
114 _handle
= CreateFile (backslash (cygpath (_filename
)).cstr_oneuse(),
115 GENERIC_READ
|GENERIC_WRITE
, FILE_SHARE_READ
|FILE_SHARE_WRITE
,
116 &sa
, CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
118 if (_handle
== INVALID_HANDLE_VALUE
)
120 log(LOG_PLAIN
) << "error: Unable to redirect output to '" << _filename
121 << "'; using console" << endLog
;
125 OutputLog::~OutputLog ()
127 if (_handle
!= INVALID_HANDLE_VALUE
)
128 CloseHandle (_handle
);
129 if (_filename
.size() &&
130 !DeleteFile(backslash (cygpath (_filename
)).cstr_oneuse()))
132 log(LOG_PLAIN
) << "error: Unable to remove temporary file '" << _filename
138 operator<< (std::ostream
&out
, OutputLog
&log
)
145 OutputLog::out_to(std::ostream
&out
)
149 FlushFileBuffers (_handle
);
150 SetFilePointer(_handle
, 0, NULL
, FILE_BEGIN
);
152 while (ReadFile(_handle
, buf
, BUFLEN
-1, &num
, NULL
) && num
!= 0)
158 SetFilePointer(_handle
, 0, NULL
, FILE_END
);
162 run (const char *sh
, const char *args
, const char *file
, OutputLog
&file_out
)
164 char cmdline
[_MAX_PATH
];
166 PROCESS_INFORMATION pi
;
167 DWORD flags
= CREATE_NEW_CONSOLE
;
168 BOOL inheritHandles
= FALSE
;
170 sprintf (cmdline
, "%s %s %s", sh
, args
, file
);
171 memset (&pi
, 0, sizeof (pi
));
172 memset (&si
, 0, sizeof (si
));
174 si
.lpTitle
= (char *) "Cygwin Setup Post-Install Script";
175 si
.dwFlags
= STARTF_USEPOSITION
;
177 if (file_out
.isValid ())
179 inheritHandles
= TRUE
;
180 si
.dwFlags
|= STARTF_USESTDHANDLES
;
181 si
.hStdInput
= GetStdHandle (STD_INPUT_HANDLE
);
182 si
.hStdOutput
= file_out
.handle ();
183 si
.hStdError
= file_out
.handle ();
184 si
.dwFlags
|= STARTF_USESHOWWINDOW
;
185 si
.wShowWindow
= SW_HIDE
;
186 flags
= CREATE_NO_WINDOW
; // Note: this is ignored on Win9x
189 BOOL createSucceeded
= CreateProcess (0, cmdline
, 0, 0, inheritHandles
,
190 flags
, 0, get_root_dir ().cstr_oneuse(),
194 WaitForSingleObject (pi
.hProcess
, INFINITE
);
195 CloseHandle(pi
.hProcess
);
196 CloseHandle(pi
.hThread
);
200 run_script (String
const &dir
, String
const &fname
, BOOL to_log
)
202 char *ext
= strrchr (fname
.cstr_oneuse(), '.');
206 String log_name
= "";
209 char tmp_pat
[] = "/var/log/setup.log.postinstallXXXXXXX";
210 log_name
= String (mktemp(tmp_pat
));
212 OutputLog
file_out(log_name
);
214 if (sh
.size() && strcmp (ext
, ".sh") == 0)
216 String f2
= dir
+ fname
;
217 log(LOG_PLAIN
) << "running: " << sh
<< " -c " << f2
<< endLog
;
218 run (sh
.cstr_oneuse(), "-c", f2
.cstr_oneuse(), file_out
);
220 else if (cmd
&& strcmp (ext
, ".bat") == 0)
222 String f2
= backslash (cygpath (dir
+ fname
));
223 log(LOG_PLAIN
) << "running: " << cmd
<< " /c " << f2
<< endLog
;
224 run (cmd
, "/c", f2
.cstr_oneuse(), file_out
);
229 if (to_log
&& !file_out
.isEmpty ())
230 log(LOG_BABBLE
) << file_out
<< endLog
;
232 /* if file exists then delete it otherwise just ignore no file error */
233 io_stream::remove (String ("cygfile://") + dir
+ fname
+ ".done");
235 io_stream::move (String ("cygfile://") + dir
+ fname
,
236 String ("cygfile://") + dir
+ fname
+ ".done");
240 try_run_script (String
const &dir
, String
const &fname
)
242 if (io_stream::exists (String ("cygfile://")+ dir
+ fname
+ ".sh"))
243 run_script (dir
.cstr_oneuse(), (fname
+ ".sh").cstr_oneuse());
244 if (io_stream::exists (String ("cygfile://")+ dir
+ fname
+ ".bat"))
245 run_script (dir
.cstr_oneuse(), (fname
+ ".bat").cstr_oneuse());
248 char const Script::ETCPostinstall
[] = "/etc/postinstall/";
251 Script::isAScript (String
const &file
)
253 /* file may be /etc/postinstall or etc/postinstall */
254 if (file
.casecompare (ETCPostinstall
, sizeof(ETCPostinstall
)) &&
255 file
.casecompare (ETCPostinstall
+1, sizeof(ETCPostinstall
)-1))
257 if (file
.cstr_oneuse()[file
.size() - 1] == '/')
262 Script::Script (String
const &fileName
) : scriptName (fileName
)
268 Script::baseName() const
270 String result
= scriptName
;
271 while (result
.find ('/'))
272 result
= result
.substr(result
.find ('/'));
277 Script::fullName() const
283 Script::run(BOOL to_log
) const
285 run_script("", scriptName
, to_log
);