]> cygwin.com Git - cygwin-apps/setup.git/blame - script.cc
2003-10-23 Jerry D. Hedden <jerry@hedden.us>
[cygwin-apps/setup.git] / script.cc
CommitLineData
bc78a6d5
RC
1/*
2 * Copyright (c) 2001, Jan Nieuwenhuizen.
3 *
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.
8 *
9 * A copy of the GNU General Public License can be found at
10 * http://www.gnu.org/
11 *
12 * Written by DJ Delorie <dj@cygnus.com>
13 * Jan Nieuwenhuizen <janneke@gnu.org>
14 *
15 */
16
17/* The purpose of this file is to provide functions for the invocation
18 of install scripts. */
19
20#if 0
21static const char *cvsid =
22 "\n%%% $Id$\n";
23#endif
24
25#include "win32.h"
26#include <stdlib.h>
27#include <unistd.h>
28#include <stdio.h>
1069407c 29#include "LogSingleton.h"
3c054baf 30#include "filemanip.h"
bc78a6d5
RC
31#include "mount.h"
32#include "io_stream.h"
ad646f43 33#include "script.h"
1069407c 34#include "mkdir.h"
bc78a6d5 35
3c054baf 36static String sh = String();
bc78a6d5
RC
37static const char *cmd = 0;
38static OSVERSIONINFO verinfo;
39
40static const char *shells[] = {
41 "/bin/sh.exe",
42 "/usr/bin/sh.exe",
43 "/bin/bash.exe",
44 "/usr/bin/bash.exe",
45 0
46};
47
48void
49init_run_script ()
50{
51 for (int i = 0; shells[i]; i++)
52 {
1ac649ed 53 sh = backslash (cygpath (shells[i]));
3c054baf 54 if (_access (sh.cstr_oneuse(), 0) == 0)
bc78a6d5 55 break;
3c054baf 56 sh = String();
bc78a6d5
RC
57 }
58
59 char old_path[_MAX_PATH];
60 GetEnvironmentVariable ("PATH", old_path, sizeof (old_path));
1ac649ed
RC
61 SetEnvironmentVariable ("PATH", backslash (cygpath ("/bin") + ";" +
62 cygpath ("/usr/bin") + ";" +
63 old_path).cstr_oneuse());
3c054baf 64 SetEnvironmentVariable ("CYGWINROOT", get_root_dir ().cstr_oneuse());
bc78a6d5
RC
65
66 verinfo.dwOSVersionInfoSize = sizeof (verinfo);
67 GetVersionEx (&verinfo);
68
69 switch (verinfo.dwPlatformId)
70 {
71 case VER_PLATFORM_WIN32_NT:
72 cmd = "cmd.exe";
73 break;
74 case VER_PLATFORM_WIN32_WINDOWS:
75 cmd = "command.com";
76 break;
77 default:
78 cmd = "command.com";
79 break;
80 }
81}
82
1069407c
MB
83class OutputLog
84{
85public:
86 OutputLog (String const &filename);
87 ~OutputLog ();
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 &);
92private:
93 enum { BUFLEN = 1000 };
94 HANDLE _handle;
95 String _filename;
96 void out_to(std::ostream &);
97};
98
99OutputLog::OutputLog (String const &filename)
100 : _handle(INVALID_HANDLE_VALUE), _filename(filename)
101{
102 if (!_filename.size())
103 return;
104
105 SECURITY_ATTRIBUTES sa;
106 memset (&sa, 0, sizeof (sa));
107 sa.nLength = sizeof (sa);
108 sa.bInheritHandle = TRUE;
109 sa.lpSecurityDescriptor = NULL;
110
111 if (mkdir_p (0, backslash (cygpath (_filename)).cstr_oneuse()))
112 return;
113
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);
117
118 if (_handle == INVALID_HANDLE_VALUE)
119 {
120 log(LOG_PLAIN) << "error: Unable to redirect output to '" << _filename
121 << "'; using console" << endLog;
122 }
123}
124
125OutputLog::~OutputLog ()
126{
127 if (_handle != INVALID_HANDLE_VALUE)
128 CloseHandle (_handle);
129 if (_filename.size() &&
130 !DeleteFile(backslash (cygpath (_filename)).cstr_oneuse()))
131 {
132 log(LOG_PLAIN) << "error: Unable to remove temporary file '" << _filename
133 << "'" << endLog;
134 }
135}
136
137std::ostream &
138operator<< (std::ostream &out, OutputLog &log)
139{
140 log.out_to(out);
141 return out;
142}
143
144void
145OutputLog::out_to(std::ostream &out)
146{
147 char buf[BUFLEN];
148 DWORD num;
149 FlushFileBuffers (_handle);
150 SetFilePointer(_handle, 0, NULL, FILE_BEGIN);
151
152 while (ReadFile(_handle, buf, BUFLEN-1, &num, NULL) && num != 0)
153 {
154 buf[num] = '\0';
155 out << buf;
156 }
157
158 SetFilePointer(_handle, 0, NULL, FILE_END);
159}
160
bc78a6d5 161static void
1069407c 162run (const char *sh, const char *args, const char *file, OutputLog &file_out)
bc78a6d5 163{
bc78a6d5
RC
164 char cmdline[_MAX_PATH];
165 STARTUPINFO si;
166 PROCESS_INFORMATION pi;
1069407c
MB
167 DWORD flags = CREATE_NEW_CONSOLE;
168 BOOL inheritHandles = FALSE;
bc78a6d5
RC
169
170 sprintf (cmdline, "%s %s %s", sh, args, file);
171 memset (&pi, 0, sizeof (pi));
172 memset (&si, 0, sizeof (si));
173 si.cb = sizeof (si);
174 si.lpTitle = (char *) "Cygwin Setup Post-Install Script";
175 si.dwFlags = STARTF_USEPOSITION;
176
1069407c
MB
177 if (file_out.isValid ())
178 {
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;
1069407c 185 si.wShowWindow = SW_HIDE;
39ba3555 186 flags = CREATE_NO_WINDOW; // Note: this is ignored on Win9x
1069407c
MB
187 }
188
189 BOOL createSucceeded = CreateProcess (0, cmdline, 0, 0, inheritHandles,
190 flags, 0, get_root_dir ().cstr_oneuse(),
191 &si, &pi);
bc78a6d5 192
92f9402a 193 if (createSucceeded)
bc78a6d5 194 WaitForSingleObject (pi.hProcess, INFINITE);
92f9402a
RC
195 CloseHandle(pi.hProcess);
196 CloseHandle(pi.hThread);
bc78a6d5
RC
197}
198
1e3b2ad4
RC
199char const *
200Script::extension() const
201{
202 return strrchr (scriptName.cstr_oneuse(), '.');
203}
204
a0e56f67 205void
34ea5b6d 206Script::run() const
a0e56f67 207{
1e3b2ad4 208 if (!extension())
bc78a6d5
RC
209 return;
210
34ea5b6d 211 BOOL to_log (TRUE);
1069407c
MB
212 String log_name = "";
213 if (to_log)
214 {
215 char tmp_pat[] = "/var/log/setup.log.postinstallXXXXXXX";
216 log_name = String (mktemp(tmp_pat));
217 }
218 OutputLog file_out(log_name);
219
1e3b2ad4 220 if (sh.size() && strcmp (extension(), ".sh") == 0)
bc78a6d5 221 {
9f27ab95
RC
222 log(LOG_PLAIN) << "running: " << sh << " -c " << scriptName << endLog;
223 ::run (sh.cstr_oneuse(), "-c", scriptName.cstr_oneuse(), file_out);
bc78a6d5 224 }
1e3b2ad4 225 else if (cmd && strcmp (extension(), ".bat") == 0)
bc78a6d5 226 {
9f27ab95
RC
227 String windowsName = backslash (cygpath (scriptName));
228 log(LOG_PLAIN) << "running: " << cmd << " /c " << windowsName << endLog;
229 ::run (cmd, "/c", windowsName.cstr_oneuse(), file_out);
bc78a6d5
RC
230 }
231 else
232 return;
233
1069407c
MB
234 if (to_log && !file_out.isEmpty ())
235 log(LOG_BABBLE) << file_out << endLog;
236
bc78a6d5 237 /* if file exists then delete it otherwise just ignore no file error */
783ed9c5 238 io_stream::remove (String ("cygfile://") + scriptName + ".done");
bc78a6d5 239
783ed9c5
RC
240 io_stream::move (String ("cygfile://") + scriptName,
241 String ("cygfile://") + scriptName + ".done");
bc78a6d5
RC
242}
243
244void
3c054baf 245try_run_script (String const &dir, String const &fname)
bc78a6d5 246{
1ac649ed 247 if (io_stream::exists (String ("cygfile://")+ dir + fname + ".sh"))
2533f348 248 Script (dir + fname+ ".sh").run ();
1ac649ed 249 if (io_stream::exists (String ("cygfile://")+ dir + fname + ".bat"))
2533f348 250 Script (dir + fname+ ".bat").run ();
bc78a6d5
RC
251}
252
39ba3555
MB
253char const Script::ETCPostinstall[] = "/etc/postinstall/";
254
ad646f43
RC
255bool
256Script::isAScript (String const &file)
257{
258 /* file may be /etc/postinstall or etc/postinstall */
39ba3555
MB
259 if (file.casecompare (ETCPostinstall, sizeof(ETCPostinstall)) &&
260 file.casecompare (ETCPostinstall+1, sizeof(ETCPostinstall)-1))
ad646f43
RC
261 return false;
262 if (file.cstr_oneuse()[file.size() - 1] == '/')
263 return false;
264 return true;
265}
266
267Script::Script (String const &fileName) : scriptName (fileName)
268{
269
270}
271
272String
39ba3555 273Script::baseName() const
ad646f43
RC
274{
275 String result = scriptName;
276 while (result.find ('/'))
277 result = result.substr(result.find ('/'));
278 return result;
279}
39ba3555
MB
280
281String
282Script::fullName() const
283{
284 return scriptName;
285}
This page took 0.057577 seconds and 5 git commands to generate.