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(¤t_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(¤t_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