]> cygwin.com Git - cygwin-apps/setup.git/blob - LogFile.cc
2002-11-10 Robert Collins <rbtcollins@hotmail.com>
[cygwin-apps/setup.git] / LogFile.cc
1 /*
2 * Copyright (c) 2002, Robert Collins.
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 Robert Collins <rbtcollins@hotmail.com>
13 *
14 */
15
16 /* Log to one or more files. */
17
18 #if 0
19 static const char *cvsid =
20 "\n%%% $Id$\n";
21 #endif
22
23 #include "LogFile.h"
24 #include "io_stream.h"
25 #include "win32.h"
26 #include "msg.h"
27 #include "resource.h"
28 #include <iostream>
29 #include <sstream>
30 #include <set>
31 #include <time.h>
32 #include <string>
33
34 using namespace std;
35
36 /* private helper class */
37 class filedef
38 {
39 public:
40 int level;
41 String key;
42 bool append;
43 filedef (String const &_path) : key (_path) {}
44 bool operator == (filedef const &rhs) const
45 {
46 return key.casecompare (rhs.key) == 0;
47 }
48 bool operator < (filedef const &rhs) const
49 {
50 return key.casecompare (rhs.key) < 0;
51 }
52 };
53
54 /* another */
55 struct LogEnt
56 {
57 LogEnt *next;
58 enum log_level level;
59 time_t when;
60 String msg;
61 };
62
63 static LogEnt *first_logent = 0;
64 static LogEnt **next_logent = &first_logent;
65 static LogEnt *currEnt = 0;
66 int exit_msg = 0;
67
68 typedef set<filedef> FileSet;
69 static FileSet files;
70 static stringbuf *theStream;
71
72 LogFile *
73 LogFile::createLogFile()
74 {
75 theStream = new std::stringbuf;
76 return new LogFile(theStream);
77 }
78
79 LogFile::LogFile(std::stringbuf *aStream) : LogSingleton (aStream)
80 {
81 }
82 LogFile::~LogFile(){}
83
84 void
85 LogFile::clearFiles ()
86 {
87 files.clear ();
88 }
89
90 void
91 LogFile::setFile (int minlevel, String const &path, bool append)
92 {
93 FileSet::iterator f = files.find (filedef(path));
94 if (f != files.end ())
95 files.erase (f);
96
97 filedef t (path);
98 t.level = minlevel;
99 t.append = append;
100 files.insert (t);
101 }
102
103 void
104 LogFile::exit (int const exit_code)
105 {
106 static int been_here = 0;
107 if (been_here)
108 #ifndef _CYGWIN_
109 ExitProcess (1);
110 #else
111 exit (1);
112 #endif
113 been_here = 1;
114
115 if (exit_msg)
116 note (NULL, exit_msg);
117
118 log (LOG_TIMESTAMP) << "Ending cygwin install" << endLog;
119
120 for (FileSet::iterator i = files.begin();
121 i != files.end(); ++i)
122 {
123 log_save (i->level, i->key, i->append);
124 }
125 #ifndef _CYGWIN_
126 ExitProcess (exit_code);
127 #else
128 exit (1);
129 #endif
130 }
131
132 void
133 LogFile::log_save (int babble, String const &filename, bool append)
134 {
135 static int been_here = 0;
136 if (been_here)
137 return;
138 been_here = 1;
139
140 io_stream::mkpath_p (PATH_TO_FILE, String("file://") + filename);
141
142 io_stream *f = io_stream::open(String("file://") + filename, append ? "at" : "wt");
143 if (!f)
144 {
145 fatal (NULL, IDS_NOLOGFILE, filename.cstr_oneuse());
146 return;
147 }
148
149 LogEnt *l;
150
151 for (l = first_logent; l; l = l->next)
152 {
153 if (babble || !(l->level == LOG_BABBLE))
154 {
155 char *tstr = l->msg.cstr();
156 f->write (tstr, strlen (tstr));
157 if (tstr[strlen (tstr) - 1] != '\n')
158 f->write ("\n", 1);
159 }
160 }
161
162 delete f;
163 been_here = 0;
164 }
165
166 ostream &
167 LogFile::operator() (log_level theLevel)
168 {
169 if (theLevel < 1 || theLevel > 2)
170 throw "barfoo";
171 if (!theStream)
172 theStream = new std::stringbuf;
173 rdbuf (theStream);
174 currEnt = new LogEnt;
175 currEnt->next = 0;
176 currEnt->level = theLevel;
177 return *this;
178 }
179
180 void
181 LogFile::endEntry()
182 {
183 if (!currEnt)
184 {
185 /* get a default LogEnt */
186 currEnt = new LogEnt;
187 currEnt->next = 0;
188 currEnt->level = LOG_PLAIN;
189 }
190 *next_logent = currEnt;
191 next_logent = &(currEnt->next);
192 time (&(currEnt->when));
193 if (currEnt->level == LOG_TIMESTAMP)
194 {
195 char b[100];
196 struct tm *tm = localtime (&(currEnt->when));
197 strftime (b, 1000, "%Y/%m/%d %H:%M:%S ", tm);
198 currEnt->msg = b;
199 }
200 /* What follows is a hack to get around an (apparent) bug in libg++-3 with
201 * non-0 memory on alloc
202 */
203 currEnt->msg += theStream->str();
204 // OLD code (libg++3) string(theStream->str()).substr(0,theStream->pcount()).c_str();
205 msg ("LOG: %d %s", currEnt->level, theStream->str().c_str());
206 //string(theStream->str()).substr(0,theStream->rdbuf()->pcount()).c_str());
207 // theStream->freeze(0);
208 delete theStream;
209 /* reset for next use */
210 theStream = new std::stringbuf;
211 rdbuf (theStream);
212 init (theStream);
213 }
This page took 0.043699 seconds and 5 git commands to generate.