]> cygwin.com Git - cygwin-apps/setup.git/blame - script.cc
2003-03-18 Igor Pechtchanski <pechtcha@cs.nyu.edu>
[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;
185#if 0
186 si.wShowWindow = SW_HIDE;
187 flags = CREATE_NO_WINDOW; // Note: might not work on Win9x
188#else
189 // TODO: introduce a script progress tracker and use the above
190 si.wShowWindow = SW_MINIMIZE;
191#endif
192 }
193
194 BOOL createSucceeded = CreateProcess (0, cmdline, 0, 0, inheritHandles,
195 flags, 0, get_root_dir ().cstr_oneuse(),
196 &si, &pi);
bc78a6d5 197
92f9402a 198 if (createSucceeded)
bc78a6d5 199 WaitForSingleObject (pi.hProcess, INFINITE);
92f9402a
RC
200 CloseHandle(pi.hProcess);
201 CloseHandle(pi.hThread);
bc78a6d5
RC
202}
203
204void
1069407c 205run_script (String const &dir, String const &fname, BOOL to_log)
bc78a6d5 206{
3c054baf 207 char *ext = strrchr (fname.cstr_oneuse(), '.');
bc78a6d5
RC
208 if (!ext)
209 return;
210
1069407c
MB
211 String log_name = "";
212 if (to_log)
213 {
214 char tmp_pat[] = "/var/log/setup.log.postinstallXXXXXXX";
215 log_name = String (mktemp(tmp_pat));
216 }
217 OutputLog file_out(log_name);
218
3c054baf 219 if (sh.size() && strcmp (ext, ".sh") == 0)
bc78a6d5 220 {
1ac649ed 221 String f2 = dir + fname;
1069407c
MB
222 log(LOG_PLAIN) << "running: " << sh << " -c " << f2 << endLog;
223 run (sh.cstr_oneuse(), "-c", f2.cstr_oneuse(), file_out);
bc78a6d5
RC
224 }
225 else if (cmd && strcmp (ext, ".bat") == 0)
226 {
1ac649ed 227 String f2 = backslash (cygpath (dir + fname));
1069407c
MB
228 log(LOG_PLAIN) << "running: " << cmd << " /c " << f2 << endLog;
229 run (cmd, "/c", f2.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 */
1ac649ed 238 io_stream::remove (String ("cygfile://") + dir + fname + ".done");
bc78a6d5 239
1ac649ed
RC
240 io_stream::move (String ("cygfile://") + dir + fname,
241 String ("cygfile://") + dir + fname+ ".done");
bc78a6d5
RC
242}
243
244void
3c054baf 245try_run_script (String const &dir, String const &fname)
bc78a6d5 246{
1ac649ed
RC
247 if (io_stream::exists (String ("cygfile://")+ dir + fname + ".sh"))
248 run_script (dir.cstr_oneuse(), (fname + ".sh").cstr_oneuse());
249 if (io_stream::exists (String ("cygfile://")+ dir + fname + ".bat"))
250 run_script (dir.cstr_oneuse(), (fname + ".bat").cstr_oneuse());
bc78a6d5
RC
251}
252
ad646f43
RC
253bool
254Script::isAScript (String const &file)
255{
256 /* file may be /etc/postinstall or etc/postinstall */
257 if (file.casecompare ("/etc/postinstall/", 17) && file.casecompare ("etc/postinstall/", 16))
258 return false;
259 if (file.cstr_oneuse()[file.size() - 1] == '/')
260 return false;
261 return true;
262}
263
264Script::Script (String const &fileName) : scriptName (fileName)
265{
266
267}
268
269String
270Script::baseName()const
271{
272 String result = scriptName;
273 while (result.find ('/'))
274 result = result.substr(result.find ('/'));
275 return result;
276}
This page took 0.053403 seconds and 5 git commands to generate.