1 /*===========================================================================
2 *
3 *                            PUBLIC DOMAIN NOTICE
4 *               National Center for Biotechnology Information
5 *
6 *  This software/database is a "United States Government Work" under the
7 *  terms of the United States Copyright Act.  It was written as part of
8 *  the author's official duties as a United States Government employee and
9 *  thus cannot be copyrighted.  This software/database is freely available
10 *  to the public for use. The National Library of Medicine and the U.S.
11 *  Government have not placed any restriction on its use or reproduction.
12 *
13 *  Although all reasonable efforts have been taken to ensure the accuracy
14 *  and reliability of the software and data, the NLM and the U.S.
15 *  Government do not and cannot warrant the performance or results that
16 *  may be obtained by using this software or data. The NLM and the U.S.
17 *  Government disclaim all warranties, express or implied, including
18 *  warranties of performance, merchantability or fitness for any particular
19 *  purpose.
20 *
21 *  Please cite the author in any work or product based on this material.
22 *
23 * ===========================================================================
24 *
25 */
26 
27 #include "plogger.hpp"
28 #include <kfc/callstk.hpp>
29 #include <kfc/rsrc.hpp>
30 #include <kfc/string.hpp>
31 #include <kfc/caps.hpp>
32 
33 #if UNIX
34 #include <unistd.h>
35 #include <string.h>
36 #include <stdlib.h>
37 #include <time.h>
38 #else
39 #error "unsupported target platform"
40 #endif
41 
42 namespace vdb3
43 {
make(const char * ident)44     Log plogger_t :: make ( const char * ident )
45     {
46         FUNC_ENTRY ();
47 
48         // going to record a "hostname procname[pid]"
49         StringBuffer hostproc;
50 
51         // create a newline
52         ConstString newline ( "\n", 1 );
53 #if UNIX
54         // hostname
55         char namebuf [ 512 ];
56         int status = gethostname ( namebuf, sizeof namebuf );
57         if ( status != 0 )
58         {
59             strncpy ( namebuf, "<HOST-UNKNOWN>", sizeof namebuf );
60             status = 0;
61         }
62         ConstString hostname ( namebuf, strlen ( namebuf ) );
63 
64         // process id
65         pid_t pid = getpid ();
66 
67         // process name
68         if ( ident == 0 || ident [ 0 ] == 0 )
69             hostproc . append ( "%s[%d]", & hostname, pid );
70         else
71         {
72             const char * leaf = strrchr ( ident, '/' );
73             if ( leaf ++ == 0 )
74                 leaf = ident;
75             ConstString procname ( leaf, strlen ( leaf ) );
76 
77             hostproc . append ( "%s %s[%d]", & hostname, & procname, pid );
78         }
79 #endif
80 
81         plogger_t * obj = new plogger_t ( hostproc . to_str (), newline );
82         return obj ->  make_ref ( obj, CAP_WRITE );
83     }
84 
msg(LogLevel priority,const char * fmt,va_list args)85     void plogger_t :: msg ( LogLevel priority, const char * fmt, va_list args )
86     {
87         // guard against /dev/null
88         if ( ! rsrc -> err )
89             return;
90 
91         FUNC_ENTRY ();
92 
93         static const char * months [ 12 ] =
94         {
95             "Jan", "Feb", "Mar", "Apr", "May", "Jun",
96             "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
97         };
98 
99 #if UNIX
100         // timestamp
101         // TBD - this should be entirely through timemgr
102 #warning "timestamp should be via TimeMgrItf"
103         time_t secs = time ( 0 );
104         struct tm tm = * localtime ( & secs );
105 
106         // create month string
107         assert ( tm . tm_mon >= 0 && tm . tm_mon < 12 );
108         ConstString month ( months [ tm . tm_mon ], 3 );
109 
110         // timestamp: 'Sep 25 10:49:18'
111         // print timestamp, host&process[pid]
112         StringBuffer buffer ( "%s %2d %02d:%02d:%02d %s: "
113                               , & month
114                               , tm . tm_mday
115                               , tm . tm_hour
116                               , tm . tm_min
117                               , tm . tm_sec
118                               , & hostproc
119             );
120 #endif
121 
122         // print message
123         if ( fmt != 0 && fmt [ 0 ] != 0 )
124             buffer . vappend ( fmt, args );
125 
126         // trim off trailing white-space
127         buffer . trim ();
128 
129         // end with newline
130         buffer += newline;
131 
132         // extract memory from string
133         String str = buffer . to_str ();
134 
135         // copy to log stream
136         rsrc -> err . write_all ( str . to_mem () );
137     }
138 
plogger_t(const String & ident,const String & nl)139     plogger_t :: plogger_t ( const String & ident, const String & nl )
140         : hostproc ( ident )
141         , newline ( nl )
142     {
143     }
144 
~plogger_t()145     plogger_t :: ~ plogger_t ()
146     {
147     }
148 }
149