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