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