1 
2 #ifdef HAVE_CONFIG_H
3 #include "config.h"
4 #endif
5 
6 #ifdef HAVE_PRINTF_H
7 
8 #ifdef HAVE_STDIO_H
9 #include <stdio.h>
10 #endif
11 #include <stdlib.h>
12 #ifdef HAVE_TIME_H
13 #include <time.h>
14 #endif
15 #ifdef HAVE_SYSLOG_H
16 #include <syslog.h>
17 #endif
18 
19 #include <wchar.h>
20 
21 #include "sigparams.h"
22 #include "util.h"
23 
24 
25 /*
26   signature parameters: custom printf conversion codes that can be
27   used to add computed information to a signature block
28 
29   by MAtteo HCE Valsasna <valsasna@uninsubria.it>
30 
31 */
32 
33 extern int debug;
34 
35 /*
36   add to this array the conversion functions to be registered */
37 
38 static struct param_info {
39   int conv_specifier;
40   int (*print_fun) (FILE *stream,
41 		    const struct printf_info *info,
42 		    const void *const *args);
43 }  conversions[] =
44 {
45   {'R', print_count },
46   {'D', print_delta },
47   {'T', print_time },
48   {'Y', print_daycount },
49   {'H', print_first_in_day },
50   /* terminator ;) */
51   {'0', NULL }
52 };
53 
54 
55 /* global vars used to create a process status informations an user
56    could find useful
57 */
58 
59 /* process fire count*/
60 int count;
61 
62 /* daily fire count */
63 int day_count;
64 int first_in_day;
65 
66 time_t current_time, last_eval_time, process_start_time;
67 
68 /* used to detect day change */
69 int last_eval_day;
70 int last_eval_month;
71 
72 char * first_in_day_msg;
73 
74 #define init_sigparams_BUFSIZE 256
75 
76 /* module initialization */
init_sigparams()77 void init_sigparams()
78 {
79   int rv = 0;
80   char errmsg[init_sigparams_BUFSIZE];
81   int ii;
82 
83   count = 0;
84   day_count = 0;
85   /* TODO: should be customizable */
86   first_in_day_msg =
87     "you are my first mail recipient of the day, congratulations!\n";
88   first_in_day = 1;
89 
90   time(& process_start_time);
91   current_time = process_start_time;
92 
93 
94   /* register conversion functions */
95   for (ii = 0; conversions[ii].print_fun; ii ++)
96     {
97       rv = register_printf_function (conversions[ii].conv_specifier,
98 				     conversions[ii].print_fun,
99 				     print_arginfo);
100       if (rv != 0) {
101 	snprintf(errmsg, init_sigparams_BUFSIZE,
102 		 "sigparams.c: initializing %c (%d) conversion",
103 		 conversions[ii].conv_specifier,
104 		 conversions[ii].conv_specifier);
105 	perror(errmsg);
106 	exit(1);
107       }
108     }
109 }
110 
111 /*
112    this function gets called at every read of .signature, before the
113    actual signature printig happens.
114 
115    all status collecting code should go here - NOT in print_*
116    functions - so that if conversion specifiers are added or removed
117    from .signature.tmpl without restarting gensig, status is still
118    computed correctly
119 
120 */
121 
foreach_sigparams()122 void foreach_sigparams()
123 {
124   int current_day, current_month;
125 
126   count ++;
127   day_count ++;
128 
129   last_eval_time = current_time;
130   time(& current_time);
131   current_day = localtime(& current_time) -> tm_mday;
132   current_month = localtime(& current_time) -> tm_mon;
133 
134   /* see if this is the first run in a new day, taking care of
135      februaries (if we just compared days, an user reading a signature
136      on the Nth of february and doing the next read on the Nth of
137      march would not get the first_in_day message) */
138   if (current_day != last_eval_day ||
139       current_month != last_eval_month)
140     {
141       last_eval_day = current_day;
142       last_eval_month = current_month;
143       day_count = 1;
144       first_in_day = 1;
145     }
146   else first_in_day = 0;
147 
148 
149   /* we are computing time differencies, a good position to detect
150      clock skews */
151 
152   if (difftime(current_time, last_eval_time) < 0)
153     {
154       if (debug)
155 	{
156 	  fprintf(stderr, "time warp? wonderful!\n");
157 	  fprintf(stderr, "last time run: %s\n", ctime(&last_eval_time));
158 	  fprintf(stderr, "current time: %s\n", ctime(&current_time));
159 	}
160       else
161 	{
162 	  openlog("gensig", LOG_PID, LOG_USER);
163 	  syslog(LOG_WARNING, "time warp? wonderful!");
164 	  syslog(LOG_WARNING, "last time run: %s", ctime(&last_eval_time));
165 	  syslog(LOG_WARNING, "current time: %s", ctime(&current_time));
166 	}
167     }
168 }
169 
170 /*
171    print_arginfo:
172 
173    this is called by *printf to know how many arguments to pass to
174    print_* when a %? conversion specifier is found in the format
175    string
176 
177    since we are printing values that depend on program state and not
178    on user input, we always return 0
179 
180 */
181 
print_arginfo(const struct printf_info * info,size_t n,int * argtypes)182 int print_arginfo (const struct printf_info *info, size_t n,
183 		   int *argtypes)
184 {
185   return 0;
186 }
187 
188 /*
189   TODO: print_* functions could consider the info parameter they
190   receive (it contains formatting instructions)
191 */
192 
193 /* count: number of times .signature was read in process life */
194 
print_count(FILE * stream,const struct printf_info * info,const void * const * args)195 int print_count(FILE *stream,
196 		const struct printf_info *info,
197 		const void *const *args)
198 {
199   return fprintf(stream, "%d", count);
200 }
201 
202 
203 /* delta: time elapsed since last read */
204 
print_delta(FILE * stream,const struct printf_info * info,const void * const * args)205 int print_delta(FILE *stream,
206 		const struct printf_info *info,
207 		const void *const *args)
208 {
209   int seconds = (int) difftime(current_time, last_eval_time);
210 
211   return fprint_delta(stream, seconds);
212 }
213 
214 /* time: time elapsed since process start */
215 
print_time(FILE * stream,const struct printf_info * info,const void * const * args)216 int print_time(FILE *stream,
217 		const struct printf_info *info,
218 		const void *const *args)
219 {
220   int seconds = (int) difftime(current_time, process_start_time);
221 
222   return fprint_delta(stream, seconds);
223 }
224 
225 
226 
227 /* day count: number of reads in a day */
228 
print_daycount(FILE * stream,const struct printf_info * info,const void * const * args)229 int print_daycount(FILE *stream,
230 		const struct printf_info *info,
231 		const void *const *args)
232 {
233   return fprintf(stream, "%d", day_count);
234 }
235 
236 
237 /* first in day: pring a message for the first read in a day */
238 
print_first_in_day(FILE * stream,const struct printf_info * info,const void * const * args)239 int print_first_in_day(FILE *stream,
240 		const struct printf_info *info,
241 		const void *const *args)
242 {
243   if (first_in_day)
244     {
245       return fprintf(stream, "%s", first_in_day_msg);
246     }
247   else return 0;
248 }
249 
250 #endif
251