While writing the man page, I realized that it was a bit silly not to accept
[samba.git] / source3 / utils / debug2html.c
1 /* ========================================================================== **
2  *                                debug2html.c
3  *
4  * Copyright (C) 1998 by Christopher R. Hertel
5  *
6  * Email: crh@ubiqx.mn.org
7  *
8  * -------------------------------------------------------------------------- **
9  * Parse Samba debug logs (2.0 & greater) and output the results as HTML.
10  * -------------------------------------------------------------------------- **
11  *
12  *  This program is free software; you can redistribute it and/or modify
13  *  it under the terms of the GNU General Public License as published by
14  *  the Free Software Foundation; either version 2 of the License, or
15  *  (at your option) any later version.
16  *
17  *  This program is distributed in the hope that it will be useful,
18  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
19  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  *  GNU General Public License for more details.
21  *
22  *  You should have received a copy of the GNU General Public License
23  *  along with this program; if not, write to the Free Software
24  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25  *
26  * -------------------------------------------------------------------------- **
27  * This program provides an example of the use of debugparse.c, and also
28  * does a decent job of converting Samba logs into HTML.
29  * -------------------------------------------------------------------------- **
30  *
31  * $Revision: 1.7 $
32  *
33  * ========================================================================== **
34  */
35
36 #include "includes.h"
37
38 /* -------------------------------------------------------------------------- **
39  * Global values.
40  */
41
42 FILE *infile  = stdin;
43 FILE *outfile = stdout;
44
45 /* -------------------------------------------------------------------------- **
46  * The size of the read buffer.
47  */
48
49 #define DBG_BSIZE 1024
50
51 /* -------------------------------------------------------------------------- **
52  * Functions...
53  */
54
55 static dbg_Token modechange( dbg_Token new, dbg_Token mode )
56   /* ------------------------------------------------------------------------ **
57    * Handle a switch between header and message printing.
58    *
59    *  Input:  new   - The token value of the current token.  This indicates
60    *                  the lexical item currently being recognized.
61    *          mode  - The current mode.  This is either dbg_null or
62    *                  dbg_message.  It could really be any toggle
63    *                  (true/false, etc.)
64    *
65    *  Output: The new mode.  This will be the same as the input mode unless
66    *          there was a transition in or out of message processing.
67    *
68    *  Notes:  The purpose of the mode value is to mark the beginning and end
69    *          of the message text block.  In order to show the text in its
70    *          correct format, it must be included within a <PRE></PRE> block.
71    *
72    * ------------------------------------------------------------------------ **
73    */
74   {
75   switch( new )
76     {
77     case dbg_null:
78     case dbg_ignore:
79       return( mode );
80     case dbg_message:
81       if( dbg_message != mode )
82         {
83         /* Switching to message mode. */
84         (void)fprintf( outfile, "<PRE>\n" );
85         return( dbg_message );
86         }
87       break;
88     default:
89       if( dbg_message == mode )
90         {
91         /* Switching out of message mode. */
92         (void)fprintf( outfile, "</PRE>\n\n" );
93         return( dbg_null );
94         }
95     }
96
97   return( mode );
98   } /* modechange */
99
100 static void newblock( dbg_Token old, dbg_Token new )
101   /* ------------------------------------------------------------------------ **
102    * Handle the transition between tokens.
103    *
104    *  Input:  old - The previous token.
105    *          new - The current token.
106    *
107    *  Output: none.
108    *
109    *  Notes:  This is called whenever there is a transition from one token
110    *          type to another.  It first prints the markup tags that close
111    *          the previous token, and then the markup tags for the new
112    *          token.
113    *
114    * ------------------------------------------------------------------------ **
115    */
116   {
117   switch( old )
118     {
119     case dbg_timestamp:
120       (void)fprintf( outfile, ",</B>" );
121       break;
122     case dbg_level:
123       (void)fprintf( outfile, "</FONT>]</B>\n   " );
124       break;
125     case dbg_sourcefile:
126       (void)fprintf( outfile, ":" );
127       break;
128     case dbg_lineno:
129       (void)fprintf( outfile, ")" );
130       break;
131     }
132
133   switch( new )
134     {
135     case dbg_timestamp:
136       (void)fprintf( outfile, "<B>[" );
137       break;
138     case dbg_level:
139       (void)fprintf( outfile, " <B><FONT COLOR=MAROON>" );
140       break;
141     case dbg_lineno:
142       (void)fprintf( outfile, "(" );
143       break;
144     }
145   } /* newblock */
146
147 static void charprint( dbg_Token tok, int c )
148   /* ------------------------------------------------------------------------ **
149    * Filter the input characters to determine what goes to output.
150    *
151    *  Input:  tok - The token value of the current character.
152    *          c   - The current character.
153    *
154    *  Output: none.
155    *
156    * ------------------------------------------------------------------------ **
157    */
158   {
159   switch( tok )
160     {
161     case dbg_ignore:
162     case dbg_header:
163       break;
164     case dbg_null:
165     case dbg_eof:
166       (void)putc( '\n', outfile );
167       break;
168     default:
169       switch( c )
170         {
171         case '<':
172           (void)fprintf( outfile, "&lt;" );
173           break;
174         case '>':
175           (void)fprintf( outfile, "&gt;" );
176           break;
177         case '&':
178           (void)fprintf( outfile, "&amp;" );
179           break;
180         case '\"':
181           (void)fprintf( outfile, "&#34;" );
182           break;
183         default:
184           (void)putc( c, outfile );
185           break;
186         }
187     }
188   } /* charprint */
189
190 static void convert( void )
191   /* ------------------------------------------------------------------------ **
192    * Read the input logfile, converting the entries to HTML.
193    *
194    *  Input:  none.
195    *  output: none.
196    *  Notes:  Reads from the global infile, writes to the global outfile.
197    *          These default to stdin and stdout, respectively.
198    *
199    * ------------------------------------------------------------------------ **
200    */
201   {
202   int       i;
203   int       len;
204   char      bufr[DBG_BSIZE];
205   dbg_Token old   = dbg_null,
206             new   = dbg_null,
207             state = dbg_null,
208             mode  = dbg_null;
209
210   while( (!feof( infile ))
211       && ((len = fread( bufr, 1, DBG_BSIZE, infile )) > 0) )
212     {
213     for( i = 0; i < len; i++ )
214       {
215       old = new;
216       new = dbg_char2token( &state, bufr[i] );
217       if( new != old )
218         {
219         mode = modechange( new, mode );
220         newblock( old, new );
221         }
222       charprint( new, bufr[i] );
223       }
224     }
225   (void)modechange( dbg_eof, mode );
226
227   } /* convert */
228
229 static void usage( void )
230   /* ------------------------------------------------------------------------ **
231    * Prints a usage message on stderr, then gently exits.
232    *
233    *  Input:  none.
234    *  Output: none.  Exits with return code of 0.
235    *
236    * ------------------------------------------------------------------------ **
237    */
238   {
239   fprintf( stderr, "This utility converts Samba log files " );
240   fprintf( stderr, "into HTML documents.\n" );
241   fprintf( stderr, "Usage:\n" );
242   fprintf( stderr, "  debug2html <infile> <outfile>\n" );
243   exit( 0 );
244   } /* usage */
245
246 static FILE *carefull_fopen( const char *path, const char *type )
247   /* ------------------------------------------------------------------------ **
248    * Checks for leading '-' characters, which are generically regarded as
249    * flags.  Also exits the program gracefully should the file fail to open.
250    *
251    *  Input:  path  - pathname of the file to open.
252    *          type  - open mode.  See fopen(3S).
253    *
254    *  Output: Pointer to open file.
255    *
256    * ------------------------------------------------------------------------ **
257    */
258   {
259   FILE *tmp;
260
261   if( '-' == path[0] || '\0' == path[0] )
262     usage();
263
264   tmp = sys_fopen( path, type );
265   if( NULL == tmp )
266     {
267     fprintf( stderr, "Error opening file %s: %s\n", path, strerror(errno) );
268     exit( 1 );
269     }
270   return( tmp );
271   } /* carefull_fopen */
272
273 int main( int argc, char *argv[] )
274   /* ------------------------------------------------------------------------ **
275    * This simple program scans and parses Samba debug logs, and produces HTML
276    * output.
277    *
278    *  Input:  argc    - Argument count.
279    *          argv[1] - Input file name.
280    *          argv[2] - Output file name.
281    *                    A '-' character by itself means use defaults (i.e.,
282    *                    <stdin> or <stdout> depending upon the argument.
283    *                    A string beginning with '-' and containing more than
284    *                    that one character will generate a usage message.
285    *
286    *  Output: An exit value of 1 is returned if an error was encountered
287    *          while opening a file, else 0.
288    *
289    *  Notes:  The HTML output is sent to stdout.
290    *
291    * ------------------------------------------------------------------------ **
292    */
293   {
294   if( argc > 3 )
295     usage();
296
297   if( argc > 1 && 0 != strcmp( argv[1], "-" ) )
298     infile = carefull_fopen( argv[1], "r" );
299
300   if( argc > 2 && 0 != strcmp( argv[2], "-" ) )
301     infile = carefull_fopen( argv[2], "w" );
302
303   (void)fprintf( outfile,
304                  "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2//EN\">\n" );
305   (void)fprintf( outfile, "<HTML>\n<HEAD>\n" );
306   (void)fprintf( outfile,
307                  "  <TITLE>Samba Log</TITLE>\n</HEAD>\n\n<BODY>\n" );
308
309   convert();
310
311   (void)fprintf( outfile, "</BODY>\n</HTML>\n" );
312
313   return( 0 );
314   } /* main */