1 /* GNU Mailutils -- a suite of utilities for electronic mail
2    Copyright (C) 1999-2021 Free Software Foundation, Inc.
3 
4    This library is free software; you can redistribute it and/or
5    modify it under the terms of the GNU Lesser General Public
6    License as published by the Free Software Foundation; either
7    version 3 of the License, or (at your option) any later version.
8 
9    This library is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12    Lesser General Public License for more details.
13 
14    You should have received a copy of the GNU Lesser General
15    Public License along with this library.  If not, see
16    <http://www.gnu.org/licenses/>. */
17 
18 #ifdef HAVE_CONFIG_H
19 # include <config.h>
20 #endif
21 
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <syslog.h>
25 #include <string.h>
26 #include <mailutils/diag.h>
27 #include <mailutils/nls.h>
28 #include <mailutils/errno.h>
29 #include <mailutils/stdstream.h>
30 #include <mailutils/stream.h>
31 #include <mailutils/locus.h>
32 
33 void
mu_diag_init()34 mu_diag_init ()
35 {
36   if (!mu_strerr)
37     mu_stdstream_setup (MU_STDSTREAM_RESET_NONE);
38 }
39 
40 void
mu_diag_voutput(int level,const char * fmt,va_list ap)41 mu_diag_voutput (int level, const char *fmt, va_list ap)
42 {
43   mu_diag_init ();
44   mu_stream_printf (mu_strerr, "\033s<%d>", level);
45   mu_stream_vprintf (mu_strerr, fmt, ap);
46   mu_stream_write (mu_strerr, "\n", 1, NULL);
47 }
48 
49 void
mu_diag_output(int level,const char * fmt,...)50 mu_diag_output (int level, const char *fmt, ...)
51 {
52   va_list ap;
53   va_start (ap, fmt);
54   mu_diag_voutput (level, fmt, ap);
55   va_end (ap);
56 }
57 
58 void
mu_vdiag_at_locus_range(int level,struct mu_locus_range const * loc,const char * fmt,va_list ap)59 mu_vdiag_at_locus_range (int level, struct mu_locus_range const *loc,
60 			 const char *fmt, va_list ap)
61 {
62   struct mu_locus_range old_loc = MU_LOCUS_RANGE_INITIALIZER;
63   int old_mode;
64   int restore = 0;
65 
66   if (loc)
67     {
68       if (mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM,
69 			   MU_IOCTL_LOGSTREAM_GET_LOCUS_RANGE, &old_loc) == 0)
70 	{
71 	  if (mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM,
72 			       MU_IOCTL_LOGSTREAM_GET_MODE, &old_mode) == 0)
73 	    {
74 	      int mode = old_mode | MU_LOGMODE_LOCUS;
75 	      mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM,
76 			       MU_IOCTL_LOGSTREAM_SET_MODE, &mode);
77 	      mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM,
78 			       MU_IOCTL_LOGSTREAM_SET_LOCUS_RANGE, (void*) loc);
79 	      restore = 1;
80 	    }
81 	}
82     }
83 
84   mu_diag_voutput (level, fmt, ap);
85 
86   if (restore)
87     {
88       mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM,
89 		       MU_IOCTL_LOGSTREAM_SET_LOCUS_RANGE, &old_loc);
90       mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM,
91 		       MU_IOCTL_LOGSTREAM_SET_MODE, &old_mode);
92       mu_locus_range_deinit (&old_loc);
93     }
94 }
95 
96 void
mu_diag_at_locus_range(int level,struct mu_locus_range const * loc,const char * fmt,...)97 mu_diag_at_locus_range (int level, struct mu_locus_range const *loc,
98 			const char *fmt, ...)
99 {
100   va_list ap;
101   va_start (ap, fmt);
102   mu_vdiag_at_locus_range (level, loc, fmt, ap);
103   va_end (ap);
104 }
105 
106 void
mu_diag_at_locus_point(int level,struct mu_locus_point const * loc,const char * fmt,...)107 mu_diag_at_locus_point (int level, struct mu_locus_point const *loc,
108 			const char *fmt, ...)
109 {
110   va_list ap;
111   struct mu_locus_range lr = MU_LOCUS_RANGE_INITIALIZER;
112   lr.beg = *loc;
113   va_start (ap, fmt);
114   mu_vdiag_at_locus_range (level, &lr, fmt, ap);
115   va_end (ap);
116 }
117 
118 void
mu_diag_vprintf(int level,const char * fmt,va_list ap)119 mu_diag_vprintf (int level, const char *fmt, va_list ap)
120 {
121   mu_diag_init ();
122   mu_stream_printf (mu_strerr, "\033s<%d>", level);
123   mu_stream_vprintf (mu_strerr, fmt, ap);
124 }
125 
126 void
mu_diag_cont_vprintf(const char * fmt,va_list ap)127 mu_diag_cont_vprintf (const char *fmt, va_list ap)
128 {
129   mu_diag_init ();
130   mu_stream_vprintf (mu_strerr, fmt, ap);
131 }
132 
133 void
mu_diag_printf(int level,const char * fmt,...)134 mu_diag_printf (int level, const char *fmt, ...)
135 {
136   va_list ap;
137   va_start (ap, fmt);
138   mu_diag_vprintf (level, fmt, ap);
139   va_end (ap);
140 }
141 
142 void
mu_diag_cont_printf(const char * fmt,...)143 mu_diag_cont_printf (const char *fmt, ...)
144 {
145   va_list ap;
146   va_start (ap, fmt);
147   mu_diag_cont_vprintf (fmt, ap);
148   va_end (ap);
149 }
150 
151 const char *
mu_diag_level_to_string(int level)152 mu_diag_level_to_string (int level)
153 {
154   switch (level)
155     {
156     case MU_DIAG_EMERG:
157       return _("emergency");
158 
159     case MU_DIAG_ALERT:
160       return _("alert");
161 
162     case MU_DIAG_CRIT:
163       return _("critical");
164 
165     case MU_DIAG_ERROR:
166       return _("error");
167 
168     case MU_DIAG_WARNING:
169       return _("warning");
170 
171     case MU_DIAG_NOTICE:
172       return _("notice");
173 
174     case MU_DIAG_INFO:
175       return _("info");
176 
177     case MU_DIAG_DEBUG:
178       return _("debug");
179     }
180   return _("unknown");
181 }
182 
183 void
mu_diag_funcall(mu_log_level_t level,const char * func,const char * arg,int err)184 mu_diag_funcall (mu_log_level_t level, const char *func,
185 		 const char *arg, int err)
186 {
187   if (err)
188     /* TRANSLATORS: First %s stands for function name, second for its
189        arguments, third one for the actual error message. */
190     mu_diag_output (level, _("%s(%s) failed: %s"), func, mu_prstr (arg),
191 		    mu_strerror (err));
192   else
193     /* TRANSLATORS: First %s stands for function name, second for its
194        arguments. */
195     mu_diag_output (level, _("%s(%s) failed"), func, mu_prstr (arg));
196 }
197