Setup postinstall logging (was Re: Pending setup patches (issue 2))
Igor Pechtchanski
pechtcha@cs.nyu.edu
Fri Mar 14 17:32:00 GMT 2003
On 10 Mar 2003, Robert Collins wrote:
> On Wed, 2003-03-05@11:52, Igor Pechtchanski wrote:
> > On 5 Mar 2003, Robert Collins wrote:
>
> > > Other than that, please expand to address all scripts.
> > > Rob
> >
> > Rob,
> >
> > There is a design issue here that I'd like to address before I work more
> > on this. I recall your comment that this should be tied into the logging
> > subsystem. Unfortunately, this would involve a much more complex code,
> > with pipes and forks. The same is true if we want "tee"-like behavior,
> > i.e. windows popping up *and* output going to a file. The way this is
> > implemented now is the output stream of the script process is tied to a
> > file, but the limitation is that the file is written right away. Do we
> > want a more complex design now, or should I just allow running a generic
> > script with output going to a file (for the moment)?
> > Igor
>
> Hmm, I'd like the following idiom:
> generate to a file.
> copy the file into the log buffer.
>
> That will get the postinstall scripts into the log.
>
> Howabout that?
> Rob
Ok, here's the next iteration of this patch. It still pops a console with
nothing in it when running postinstall scripts -- I'm sure there's a way
to remove it, but can't find it at the moment. It does, however,
correctly redirect the output of postinstall scripts into the LOG_BABBLE
file. Most of the patch is OS-independent, but the output redirection
mechanism has been tested on Win95 by Brian Keener (see
<http://cygwin.com/ml/cygwin-apps/2003-03/msg00364.html>) and hasn't been
changed in this patch.
Igor
P.S. Note that this patch conflicts slightly with my other patch
(postinstall script ordering). Nothing a human can't fix, but both at
once will not apply cleanly OOTB. Whichever one of them goes in first,
I'll regenerate and resubmit the other one.
==============================================================================
ChangeLog:
2003-03-13 Igor Pechtchanski <pechtcha@cs.nyu.edu>
* script.cc (run): Add lname parameter.
Redirect output of subprocess to file, creating the
path if necessary.
(run_script): Add optional to_log boolean parameter.
If to_log, redirect output to temporary file.
(openOutputLog): New helper function.
(closeOutputLog): New helper function.
(removeOutputLog): New helper function.
* script.h (run_script): Add optional to_log parameter.
* log.h (log_file): New function.
* log.cc (log_file): New Function
(BUFLEN): New #define.
* postinstall.cc (RunFindVisitor::visitFile): Pass
filename to run_script().
--
http://cs.nyu.edu/~pechtcha/
|\ _,,,---,,_ pechtcha@cs.nyu.edu
ZZZzz /,`.-'`' -. ;-;;,_ igor@watson.ibm.com
|,4- ) )-,_. ,\ ( `'-' Igor Pechtchanski
'---''(_/--' `-'\_) fL a.k.a JaguaR-R-R-r-r-r-.-.-. Meow!
Oh, boy, virtual memory! Now I'm gonna make myself a really *big* RAMdisk!
-- /usr/games/fortune
-------------- next part --------------
Index: postinstall.cc
===================================================================
RCS file: /cvs/cygwin-apps/setup/postinstall.cc,v
retrieving revision 2.9
diff -u -p -r2.9 postinstall.cc
--- postinstall.cc 19 May 2002 03:07:51 -0000 2.9
+++ postinstall.cc 13 Mar 2003 18:34:51 -0000
@@ -33,7 +33,7 @@ public:
RunFindVisitor (){}
virtual void visitFile(String const &basePath, const WIN32_FIND_DATA *theFile)
{
- run_script ("/etc/postinstall/", theFile->cFileName);
+ run_script ("/etc/postinstall/", theFile->cFileName, TRUE);
}
virtual ~ RunFindVisitor () {}
protected:
Index: log.cc
===================================================================
RCS file: /cvs/cygwin-apps/setup/log.cc,v
retrieving revision 2.13
diff -u -p -r2.13 log.cc
--- log.cc 27 Jun 2002 11:01:10 -0000 2.13
+++ log.cc 14 Mar 2003 17:12:21 -0000
@@ -36,6 +36,8 @@ static const char *cvsid =
#include "io_stream.h"
+#define BUFLEN 1000
+
void
log (enum log_level level, String const &message)
{
@@ -45,9 +47,38 @@ log (enum log_level level, String const
void
log (enum log_level level, const char *fmt, ...)
{
- char buf[1000];
+ char buf[BUFLEN];
va_list args;
va_start (args, fmt);
- vsnprintf (buf, 1000, fmt, args);
+ vsnprintf (buf, BUFLEN, fmt, args);
log (level, String(buf));
+}
+
+void
+log_file (enum log_level level, String const &filename)
+{
+ char buf[BUFLEN];
+ int num;
+ bool non_empty = false;
+ io_stream *f = io_stream::open(String("cygfile://") + filename, "rt");
+ if (!f)
+ {
+ const char *err = strerror (errno);
+ if (!err)
+ err = "(unknown error)";
+ note (NULL, IDS_ERR_OPEN_READ, filename.cstr_oneuse(), err);
+ return;
+ }
+
+ std::ostream &out = LogSingleton::GetInstance()(level);
+ while ((num = f->read(buf, BUFLEN-1)) != 0)
+ {
+ buf[num] = '\0';
+ out << buf;
+ non_empty = true;
+ }
+ if (non_empty)
+ out << endLog;
+
+ delete f;
}
Index: log.h
===================================================================
RCS file: /cvs/cygwin-apps/setup/log.h,v
retrieving revision 2.5
diff -u -p -r2.5 log.h
--- log.h 4 May 2002 12:15:56 -0000 2.5
+++ log.h 14 Mar 2003 17:12:21 -0000
@@ -23,3 +23,4 @@
void log (enum log_level level, const char *fmt, ...)
__attribute__ ((format (printf, 2, 3)));
void log (enum log_level level, String const &);
+void log_file (enum log_level level, String const &filename);
Index: script.cc
===================================================================
RCS file: /cvs/cygwin-apps/setup/script.cc,v
retrieving revision 2.4
diff -u -p -r2.4 script.cc
--- script.cc 18 Feb 2002 13:53:07 -0000 2.4
+++ script.cc 14 Mar 2003 17:12:21 -0000
@@ -30,6 +30,8 @@ static const char *cvsid =
#include "filemanip.h"
#include "mount.h"
#include "io_stream.h"
+#include "script.h"
+#include "mkdir.h"
static String sh = String();
static const char *cmd = 0;
@@ -78,13 +80,60 @@ init_run_script ()
}
}
+static BOOL
+openOutputLog (HANDLE &file_out, String const &lname)
+{
+ SECURITY_ATTRIBUTES sa;
+ memset (&sa, 0, sizeof (sa));
+ sa.nLength = sizeof (sa);
+ sa.bInheritHandle = TRUE;
+ sa.lpSecurityDescriptor = NULL;
+
+ if (mkdir_p (0, backslash (cygpath (lname)).cstr_oneuse()))
+ return FALSE;
+
+ file_out = CreateFile (backslash (cygpath (lname)).cstr_oneuse(),
+ GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE,
+ &sa, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
+ if (file_out == INVALID_HANDLE_VALUE)
+ {
+ log (LOG_PLAIN, String ("Error: Unable to redirect output to '") +
+ lname + "'; using console");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static void
+closeOutputLog (HANDLE &file_out)
+{
+ if (file_out == INVALID_HANDLE_VALUE)
+ return;
+
+ CloseHandle (file_out);
+}
+
+static void
+removeOutputLog (String const &lname)
+{
+ if (io_stream::remove (String ("cygfile://") + lname))
+ {
+ log (LOG_PLAIN, String ("error: Unable to remove temporary file '") +
+ lname + "'");
+ }
+}
+
static void
-run (const char *sh, const char *args, const char *file)
+run (const char *sh, const char *args, const char *file, String const &lname)
{
BOOL b;
char cmdline[_MAX_PATH];
STARTUPINFO si;
PROCESS_INFORMATION pi;
+ HANDLE file_out = INVALID_HANDLE_VALUE;
+ DWORD dwCPFlags = CREATE_NEW_CONSOLE;
+ BOOL bInheritHandles = FALSE;
sprintf (cmdline, "%s %s %s", sh, args, file);
memset (&pi, 0, sizeof (pi));
@@ -93,34 +142,60 @@ run (const char *sh, const char *args, c
si.lpTitle = (char *) "Cygwin Setup Post-Install Script";
si.dwFlags = STARTF_USEPOSITION;
- b = CreateProcess (0, cmdline, 0, 0, 0,
- CREATE_NEW_CONSOLE, 0, get_root_dir ().cstr_oneuse(), &si, &pi);
+ if (lname.size())
+ if (openOutputLog (file_out, lname))
+ {
+ bInheritHandles = TRUE;
+ si.dwFlags = STARTF_USESTDHANDLES;
+ si.hStdOutput = file_out;
+ si.hStdError = file_out;
+ dwCPFlags = 0;
+ }
+
+ b = CreateProcess (0, cmdline, 0, 0, bInheritHandles,
+ dwCPFlags, 0, get_root_dir ().cstr_oneuse(), &si, &pi);
if (b)
WaitForSingleObject (pi.hProcess, INFINITE);
+
+ if (lname.size())
+ closeOutputLog (file_out);
}
void
-run_script (String const &dir, String const &fname)
+run_script (String const &dir, String const &fname, BOOL to_log)
{
char *ext = strrchr (fname.cstr_oneuse(), '.');
if (!ext)
return;
+ String lname = "";
+ if (to_log)
+ {
+ char tmp_pat[] = "/var/log/setup.log.postinstallXXXXXXX";
+ lname = String (mktemp(tmp_pat));
+ }
+
if (sh.size() && strcmp (ext, ".sh") == 0)
{
String f2 = dir + fname;
log (LOG_PLAIN, String ("running: ") + sh + " -c " + f2);
- run (sh.cstr_oneuse(), "-c", f2.cstr_oneuse());
+ run (sh.cstr_oneuse(), "-c", f2.cstr_oneuse(), lname);
}
else if (cmd && strcmp (ext, ".bat") == 0)
{
String f2 = backslash (cygpath (dir + fname));
log (LOG_PLAIN, String ("running: ") + cmd + " /c " + f2);
- run (cmd, "/c", f2.cstr_oneuse());
+ run (cmd, "/c", f2.cstr_oneuse(), lname);
}
else
return;
+
+ if (to_log)
+ {
+ log_file(LOG_BABBLE, lname);
+ removeOutputLog (lname);
+ }
/* if file exists then delete it otherwise just ignore no file error */
io_stream::remove (String ("cygfile://") + dir + fname + ".done");
Index: script.h
===================================================================
RCS file: /cvs/cygwin-apps/setup/script.h,v
retrieving revision 2.2
diff -u -p -r2.2 script.h
--- script.h 18 Feb 2002 12:35:23 -0000 2.2
+++ script.h 14 Mar 2003 17:12:21 -0000
@@ -21,7 +21,7 @@
we have a Bourne shell, execute it using sh. Otherwise, if fname
has suffix .bat, execute using cmd */
-void run_script (String const &dir, String const &fname);
+void run_script (String const &dir, String const &fname, BOOL to_log = FALSE);
/* Initialisation stuff for run_script: sh, cmd, CYGWINROOT and PATH */
void init_run_script ();
More information about the Cygwin-apps
mailing list