Initial import of the CDE 2.1.30 sources from the Open Group.
[oweals/cde.git] / cde / lib / tt / lib / util / tt_trace_stream.C
1 //%%  (c) Copyright 1993, 1994 Hewlett-Packard Company                  
2 //%%  (c) Copyright 1993, 1994 International Business Machines Corp.    
3 //%%  (c) Copyright 1993, 1994 Sun Microsystems, Inc.                   
4 //%%  (c) Copyright 1993, 1994 Novell, Inc.                             
5 //%%  $XConsortium: tt_trace_stream.C /main/3 1995/10/23 10:46:52 rswiston $                                                    
6 /*
7  * @(#)tt_trace_stream.C        1.13 94/11/18
8  *
9  * Copyright 1993 Sun Microsystems, Inc.  All rights reserved.
10  */
11
12 #include <stdarg.h>
13 #include <unistd.h>
14 #include <fcntl.h>
15 #include "util/tt_enumname.h"
16 #include "util/tt_port.h"
17 #include "util/tt_trace_stream.h"
18 #include "mp/mp_pattern.h"
19 #include "mp/mp_procid.h"
20
21 const int Tt_trace_buf_len = 4096;
22
23 _Tt_trace_stream::_Tt_trace_stream()
24 {
25 }
26
27 _Tt_trace_stream::_Tt_trace_stream(
28         const char *script
29 ) :
30         _Tt_trace_parser( script )
31 {
32         _is_entered = 0;
33 }
34
35 _Tt_trace_stream::_Tt_trace_stream(
36         int scriptfd
37 ) :
38         _Tt_trace_parser( scriptfd )
39 {
40         _is_entered = 0;
41 }
42
43 _Tt_trace_stream::~_Tt_trace_stream()
44 {
45         if (theFILE() != 0) {
46                 if (theFILE() != stderr) {
47                         fclose( theFILE() );
48                 }
49                 this->_Tt_ostream::operator=( (FILE *)0 );
50         }
51 }
52
53 //
54 // Returns
55 //      TT_OK
56 //      TT_WRN_STOPPED          the script has turned off all tracing
57 //      TT_ERR_INVALID          syntax error in script
58 //      TT_ERR_FILE             could not open output file
59 //      
60 Tt_status
61 _Tt_trace_stream::init()
62 {
63         int status = parse();
64         if (status != 0) {
65                 return TT_ERR_INVALID;
66         }
67         if (! any_tracing()) {
68                 return TT_WRN_STOPPED;
69         }
70         if (follow_val()) {
71                 char buf[ 20 ];
72                 ::sprintf( buf, "%d:\t", getpid() );
73                 set_indent( buf );
74         }
75
76         if (sink_val().len() <= 0) {
77                 this->_Tt_ostream::operator=( stderr );
78         } else {
79                 FILE    *fp = fopen( sink_val(), mode_val());
80                 this->_Tt_ostream::operator=( fp );
81                 if (theFILE() == 0) {
82                         _tt_syslog( 0, LOG_ERR, "tttracefile: %s: %m",
83                                     sink_val().operator const char *() );
84                         return TT_ERR_FILE;
85                 }
86                 fcntl(fileno(fp), F_SETFD, 1);  /* Close on exec */
87                 // Use line-buffering, in case of many writers
88                 setvbuf( theFILE(), 0, _IOLBF, 0 );
89         }
90         return TT_OK;
91 }
92
93 void
94 _Tt_trace_stream::incr_indent() const
95 {
96         set_indent( indent().cat("\t") );
97 }
98
99 void
100 _Tt_trace_stream::decr_indent() const
101 {
102         set_indent( indent().left( indent().len() - 1 ) );
103 }
104
105 const _Tt_trace_stream &
106 operator <<(
107         _Tt_trace_stream &os,
108         _Tt_message      &msg
109 )
110 {
111         if (os.attributes_val()) {
112                 // prevents infinite recursion
113                 os._Tt_ostream::operator <<( msg );
114                 return os;
115         }
116         os << _tt_enumname( msg.message_class() );
117         os << " <" << msg.api_id() << "> ";
118         os << _tt_enumname( msg.state() );
119         char *conjunction = " because ";
120         switch (msg.state()) {
121             case TT_CREATED:
122             case TT_SENT:
123                 os << " by <" << msg.sender()->id() << ">";
124                 break;
125             case TT_HANDLED:
126                 conjunction = " result: ";
127             case TT_REJECTED:
128             case TT_FAILED:
129                 if (! msg.handler().is_null()) {
130                         os << " by <" << msg.handler()->id() << ">";
131                 }
132                 os << conjunction << (Tt_status)msg.status();
133                 break;
134             default:
135                 break;
136         }
137         os << " " << msg.op() << "()\n";
138         return os;
139 }