tin  2.6.1
About: TIN is a threaded NNTP and spool based UseNet newsreader.
  Fossies Dox: tin-2.6.1.tar.xz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

debug.c
Go to the documentation of this file.
1/*
2 * Project : tin - a Usenet reader
3 * Module : debug.c
4 * Author : I. Lea
5 * Created : 1991-04-01
6 * Updated : 2021-02-01
7 * Notes : debug routines
8 *
9 * Copyright (c) 1991-2022 Iain Lea <iain@bricbrac.de>
10 * All rights reserved.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 *
16 * 1. Redistributions of source code must retain the above copyright notice,
17 * this list of conditions and the following disclaimer.
18 *
19 * 2. Redistributions in binary form must reproduce the above copyright
20 * notice, this list of conditions and the following disclaimer in the
21 * documentation and/or other materials provided with the distribution.
22 *
23 * 3. Neither the name of the copyright holder nor the names of its
24 * contributors may be used to endorse or promote products derived from
25 * this software without specific prior written permission.
26 *
27 * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
28 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
31 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37 * POSSIBILITY OF SUCH DAMAGE.
38 */
39
40
41#ifndef TIN_H
42# include "tin.h"
43#endif /* !TIN_H */
44
45#ifdef DEBUG
46# ifndef NEWSRC_H
47# include "newsrc.h"
48# endif /* !NEWSRC_H */
49#endif /* DEBUG */
50
51unsigned short debug;
52
53#ifdef DEBUG
54/*
55 * Local prototypes
56 */
57static void debug_print_attributes(struct t_attribute *attr, FILE *fp);
58static void debug_print_filter(FILE *fp, int num, struct t_filter *the_filter);
59static void debug_print_newsrc(struct t_newsrc *lnewsrc, FILE *fp);
60
61
62/*
63 * remove debug files
64 */
65void
66debug_delete_files(
67 void)
68{
69 char file[PATH_LEN];
70
71 if (debug & (DEBUG_NNTP | DEBUG_REMOVE)) {
72 joinpath(file, sizeof(file), TMPDIR, "NNTP");
73 unlink(file);
74 }
75
77 joinpath(file, sizeof(file), TMPDIR, "ARTS");
78 unlink(file);
79 joinpath(file, sizeof(file), TMPDIR, "FILTER");
80 unlink(file);
81 }
82
84 joinpath(file, sizeof(file), TMPDIR, "BITMAP");
85 unlink(file);
86 }
87
88 if (debug & (DEBUG_REFS | DEBUG_REMOVE)) {
89 joinpath(file, sizeof(file), TMPDIR, "REFS.dump");
90 unlink(file);
91 joinpath(file, sizeof(file), TMPDIR, "REFS.info");
92 unlink(file);
93 }
94
95 if (debug & (DEBUG_MEM | DEBUG_REMOVE)) {
96 joinpath(file, sizeof(file), TMPDIR, "MALLOC");
97 unlink(file);
98 }
99
100 if (debug & (DEBUG_ATTRIB | DEBUG_REMOVE)) {
101 joinpath(file, sizeof(file), TMPDIR, "ATTRIBUTES");
102 unlink(file);
103 joinpath(file, sizeof(file), TMPDIR, "SCOPES-R");
104 unlink(file);
105 joinpath(file, sizeof(file), TMPDIR, "SCOPES-W");
106 unlink(file);
107 }
108
109 if (debug & (DEBUG_MISC | DEBUG_REMOVE)) {
110 joinpath(file, sizeof(file), TMPDIR, "ACTIVE");
111 unlink(file);
112 joinpath(file, sizeof(file), TMPDIR, "GNKSA");
113 unlink(file);
114 }
115}
116
117
118/*
119 * tin specific debug routines
120 */
121void
122debug_print_arts(
123 void)
124{
125 int i;
126
127 for_each_art(i) /* fopen/close() horror */
128 debug_print_header(&arts[i]);
129}
130
131
132void
133debug_print_header(
134 struct t_article *s)
135{
136 static char file[PATH_LEN] = { '\0' };
137 FILE *fp;
138
139 if (!(debug & DEBUG_FILTER))
140 return;
141
142 if (!*file)
143 joinpath(file, sizeof(file), TMPDIR, "ARTS");
144
145 if ((fp = fopen(file, "a")) != NULL) {
146 fprintf(fp, "art=[%5"T_ARTNUM_PFMT"] tag=[%s] kill=[%s] selected=[%s]\n", s->artnum,
150 fprintf(fp, "subj=[%-38s]\n", s->subject);
151 fprintf(fp, "date=[%ld] from=[%s] name=[%s]\n", (long) s->date, s->from,
152 BlankIfNull(s->name));
153 fprintf(fp, "msgid=[%s] refs=[%s]\n",
154 BlankIfNull(s->msgid),
155 BlankIfNull(s->refs));
156
157 if (s->killed)
158 fprintf(fp, "score=[%d] gnksa=[%d] lines=[%d]\n", s->score, s->gnksa_code, s->line_count);
159
160 fprintf(fp, "thread=[%d] prev=[%d] status=[%u]\n\n", s->thread, s->prev, s->status);
161 fflush(fp);
162# ifdef HAVE_FCHMOD
163 fchmod(fileno(fp), (S_IRUGO|S_IWUGO));
164# else
165# ifdef HAVE_CHMOD
166 chmod(file, (S_IRUGO|S_IWUGO));
167# endif /* HAVE_CHMOD */
168# endif /* HAVE_FCHMOD */
169 fclose(fp);
170 }
171}
172
173
174void
175debug_print_active(
176 void)
177{
178 static char file[PATH_LEN] = { '\0' };
179 FILE *fp;
180
181 if (!(debug & DEBUG_MISC))
182 return;
183
184 if (!*file)
185 joinpath(file, sizeof(file), TMPDIR, "ACTIVE");
186
187 if ((fp = fopen(file, "w")) != NULL) {
188 int i;
189 struct t_group *group;
190
191 for_each_group(i) {
192 group = &active[i];
193 fprintf(fp, "[%4d]=[%s] type=[%s] spooldir=[%s]\n",
194 i, group->name,
195 (group->type == GROUP_TYPE_NEWS ? "NEWS" : "MAIL"),
196 group->spooldir);
197 fprintf(fp, "count=[%4"T_ARTNUM_PFMT"] max=[%4"T_ARTNUM_PFMT"] min=[%4"T_ARTNUM_PFMT"] mod=[%c]\n",
198 group->count, group->xmax, group->xmin, group->moderated);
199 fprintf(fp, " nxt=[%4d] hash=[%lu] description=[%s]\n", group->next,
200 hash_groupname(group->name), BlankIfNull(group->description));
201 if (debug & DEBUG_NEWSRC)
202 debug_print_newsrc(&group->newsrc, fp);
203 if (debug & DEBUG_ATTRIB)
204 debug_print_attributes(group->attribute, fp);
205 }
206# ifdef HAVE_FCHMOD
207 fchmod(fileno(fp), (S_IRUGO|S_IWUGO));
208# else
209# ifdef HAVE_CHMOD
210 chmod(file, (S_IRUGO|S_IWUGO));
211# endif /* HAVE_CHMOD */
212# endif /* HAVE_FCHMOD */
213 fclose(fp);
214 }
215}
216
217
218static void
219debug_print_attributes(
220 struct t_attribute *attr,
221 FILE *fp)
222{
223 if (attr == NULL)
224 return;
225
226 fprintf(fp, "global=[%u] show=[%u] thread=[%u] sort=[%u] author=[%u] auto_select=[%u] batch_save=[%u] process=[%u]\n",
227 attr->global,
229 attr->thread_articles,
230 attr->sort_article_type,
231 attr->show_author,
232 attr->auto_select,
233 attr->batch_save,
234 attr->post_process_type);
235 fprintf(fp, "select_header=[%u] select_global=[%s] select_expire=[%s]\n",
239 fprintf(fp, "kill_header =[%u] kill_global =[%s] kill_expire =[%s]\n",
240 attr->quick_kill_header,
243 fprintf(fp, "maildir=[%s] savedir=[%s] savefile=[%s]\n",
244 BlankIfNull(attr->maildir),
245 BlankIfNull(attr->savedir),
246 BlankIfNull(attr->savefile));
247 fprintf(fp, "sigfile=[%s] followup_to=[%s]\n\n",
248 BlankIfNull(attr->sigfile),
249 BlankIfNull(attr->followup_to));
250 fflush(fp);
251}
252
253
254void
255debug_print_malloc(
256 t_bool is_malloc,
257 const char *xfile,
258 int line,
259 size_t size)
260{
261 static char file[PATH_LEN] = { '\0' };
262 static size_t total = 0;
263 FILE *fp;
264
265 if (!*file)
266 joinpath(file, sizeof(file), TMPDIR, "MALLOC");
267
268 if ((fp = fopen(file, "a")) != NULL) {
269 total += size;
270 /* sometimes size_t is long */
271 fprintf(fp, "%12s:%-4d %s(%6lu). Total %lu\n", xfile, line, is_malloc ? " malloc" : "realloc", (unsigned long) size, (unsigned long) total);
272# ifdef HAVE_FCHMOD
273 fchmod(fileno(fp), (S_IRUGO|S_IWUGO));
274# else
275# ifdef HAVE_CHMOD
276 chmod(file, (S_IRUGO|S_IWUGO));
277# endif /* HAVE_CHMOD */
278# endif /* HAVE_FCHMOD */
279 fclose(fp);
280 }
281}
282
283
284static void
285debug_print_filter(
286 FILE *fp,
287 int num,
288 struct t_filter *the_filter)
289{
290 static const char sign[] = { ' ', '=', '<', '>', '\0' };
291
292 fprintf(fp, "[%3d] group=[%s]\n inscope=[%s] score=[%d] case=[%s]\n",
293 num, BlankIfNull(the_filter->scope),
294 (the_filter->inscope ? "TRUE" : "FILTER"),
295 the_filter->score,
296 the_filter->icase ? "C" : "I");
297
298 if (the_filter->subj)
299 fprintf(fp, " subj=[%s]\n", the_filter->subj);
300 if (the_filter->from)
301 fprintf(fp, " from=[%s]\n", the_filter->from);
302 if (the_filter->msgid)
303 fprintf(fp, " msgid=[%s]\n", the_filter->msgid);
304 if (the_filter->xref)
305 fprintf(fp, " xref=[%s]\n", the_filter->xref);
306 if (the_filter->path)
307 fprintf(fp, " path=[%s]\n", the_filter->path);
308
309 fprintf(fp, " lines=[%c%d] gnksa=[%c%d]\n",
310 sign[(int) the_filter->lines_cmp], the_filter->lines_num,
311 sign[(int) the_filter->gnksa_cmp], the_filter->gnksa_num);
312
313 if (the_filter->time)
314 fprintf(fp, " time=[%ld][%s]\n", (long) the_filter->time, BlankIfNull(str_trim(ctime(&the_filter->time))));
315}
316
317
318void
319debug_print_filters(
320 void)
321{
322 int i, num;
323 static char file[PATH_LEN] = { '\0' };
324 struct t_filter *the_filter;
325 FILE *fp;
326
327 if (!*file)
328 joinpath(file, sizeof(file), TMPDIR, "FILTER");
329
330 if ((fp = fopen(file, "w")) != NULL) {
331 /*
332 * print global filter
333 */
334 num = glob_filter.num;
335 the_filter = glob_filter.filter;
336 fprintf(fp, "*** BEG GLOBAL FILTER=[%3d] ***\n", num);
337 for (i = 0; i < num; i++) {
338 debug_print_filter(fp, i, &the_filter[i]);
339 fprintf(fp, "\n");
340 }
341 fprintf(fp, "*** END GLOBAL FILTER ***\n");
342
343# ifdef HAVE_FCHMOD
344 fchmod(fileno(fp), (S_IRUGO|S_IWUGO));
345# else
346# ifdef HAVE_CHMOD
347 chmod(file, (S_IRUGO|S_IWUGO));
348# endif /* HAVE_CHMOD */
349# endif /* HAVE_FCHMOD */
350 fclose(fp);
351 }
352}
353
354
355void
356debug_print_file(
357 const char *fname,
358 const char *fmt,
359 ...)
360{
361 FILE *fp;
362 char *buf;
363 char file[PATH_LEN];
364 va_list ap;
365
366 if (!debug)
367 return;
368
369 va_start(ap, fmt);
370 buf = fmt_message(fmt, ap);
371 va_end(ap);
372
373 joinpath(file, sizeof(file), TMPDIR, fname);
374
375 if ((fp = fopen(file, "a")) != NULL) {
376 fprintf(fp, "%s\n", buf);
377# ifdef HAVE_FCHMOD
378 fchmod(fileno(fp), (S_IRUGO|S_IWUGO));
379# else
380# ifdef HAVE_CHMOD
381 chmod(file, (S_IRUGO|S_IWUGO));
382# endif /* HAVE_CHMOD */
383# endif /* HAVE_FCHMOD */
384 fclose(fp);
385 }
386 free(buf);
387}
388
389
390void
391debug_print_comment(
392 const char *comment)
393{
394 if (!(debug & DEBUG_NEWSRC))
395 return;
396
397 debug_print_file("BITMAP", comment);
398}
399
400
401void
402debug_print_bitmap(
403 struct t_group *group,
404 struct t_article *art)
405{
406 FILE *fp;
407 char file[PATH_LEN];
408
409 if (!(debug & DEBUG_NEWSRC))
410 return;
411
412 joinpath(file, sizeof(file), TMPDIR, "BITMAP");
413 if (group != NULL) {
414 if ((fp = fopen(file, "a")) != NULL) {
415 fprintf(fp, "\nActive: Group=[%s] sub=[%c] min=[%"T_ARTNUM_PFMT"] max=[%"T_ARTNUM_PFMT"] count=[%"T_ARTNUM_PFMT"] num_unread=[%"T_ARTNUM_PFMT"]\n",
416 group->name, SUB_CHAR(group->subscribed),
417 group->xmin, group->xmax, group->count,
418 group->newsrc.num_unread);
419 if (art != NULL) {
420 fprintf(fp, "art=[%5"T_ARTNUM_PFMT"] tag=[%s] kill=[%s] selected=[%s] subj=[%s]\n",
421 art->artnum,
422 bool_unparse(art->tagged),
423 bool_unparse(art->killed),
424 bool_unparse(art->selected),
425 art->subject);
426 fprintf(fp, "thread=[%d] prev=[%d] status=[%s]\n",
427 art->thread, art->prev,
428 (art->status == ART_READ ? "READ" : "UNREAD"));
429 }
430 debug_print_newsrc(&group->newsrc, fp);
431# ifdef HAVE_FCHMOD
432 fchmod(fileno(fp), (S_IRUGO|S_IWUGO));
433# else
434# ifdef HAVE_CHMOD
435 chmod(file, (S_IRUGO|S_IWUGO));
436# endif /* HAVE_CHMOD */
437# endif /* HAVE_FCHMOD */
438 fclose(fp);
439 }
440 }
441}
442
443
444static void
445debug_print_newsrc(
446 struct t_newsrc *lnewsrc,
447 FILE *fp)
448{
449 int j;
450 t_artnum i;
451
452 fprintf(fp, "Newsrc: min=[%"T_ARTNUM_PFMT"] max=[%"T_ARTNUM_PFMT"] bitlen=[%"T_ARTNUM_PFMT"] num_unread=[%"T_ARTNUM_PFMT"] present=[%d]\n",
453 lnewsrc->xmin, lnewsrc->xmax, lnewsrc->xbitlen,
454 lnewsrc->num_unread, (lnewsrc->present ? 1 : 0));
455
456 fprintf(fp, "bitmap=[");
457 if (lnewsrc->xbitlen && lnewsrc->xbitmap) {
458 for (j = 0, i = lnewsrc->xmin; i <= lnewsrc->xmax; i++) {
459 fprintf(fp, "%d",
460 (NTEST(lnewsrc->xbitmap, i - lnewsrc->xmin) == ART_READ ?
462 if ((j++ % 8) == 7 && i < lnewsrc->xmax)
463 fprintf(fp, " ");
464 }
465 }
466 fprintf(fp, "]\n");
467 fflush(fp);
468}
469
470
471# ifdef NNTP_ABLE
472const char *
473logtime(
474 void)
475{
476# if defined(HAVE_CLOCK_GETTIME) || defined(HAVE_GETTIMEOFDAY)
477 static struct t_tintime log_time;
478 static char out[40];
479
480 if (tin_gettime(&log_time) == 0) {
481 if (my_strftime(out, 39, " [%H:%M:%S.", gmtime(&(log_time.tv_sec)))) {
482 sprintf(out + 11, "%09ld", log_time.tv_nsec); /* strlen(" [hh:mm:ss.") */
483 out[17] = '\0'; /* strlen(" [hh:mm:ss.uuuuuu") */
484 strcat(out, "] ");
485 return out;
486 }
487 }
488# endif /* HAVE_CLOCK_GETTIME || HAVE_GETTIMEOFDAY */
489 return " ";
490}
491# endif /* NNTP_ABLE */
492#endif /* DEBUG */
unsigned t_bool
Definition: bool.h:77
#define bool_unparse(b)
Definition: bool.h:83
static t_openartinfo * art
Definition: cook.c:78
unsigned short debug
Definition: debug.c:51
#define DEBUG_REMOVE
Definition: debug.h:56
#define DEBUG_MISC
Definition: debug.h:54
#define DEBUG_NEWSRC
Definition: debug.h:50
#define DEBUG_REFS
Definition: debug.h:51
#define DEBUG_MEM
Definition: debug.h:52
#define DEBUG_FILTER
Definition: debug.h:49
#define DEBUG_NNTP
Definition: debug.h:47
#define DEBUG_ATTRIB
Definition: debug.h:53
struct t_filters glob_filter
Definition: filter.c:87
struct t_article * arts
Definition: memory.c:69
struct t_group * active
Definition: memory.c:66
static char buf[16]
Definition: langinfo.c:50
#define NTEST(n, b)
Definition: newsrc.h:122
char * str_trim(char *string)
Definition: string.c:539
size_t my_strftime(char *s, size_t maxsize, const char *format, struct tm *timeptr)
Definition: strftime.c:64
unsigned long hash_groupname(const char *group)
Definition: list.c:83
int tin_gettime(struct t_tintime *tt)
Definition: misc.c:4201
void joinpath(char *result, size_t result_size, const char *dir, const char *file)
Definition: joinpath.c:50
char * fmt_message(const char *fmt, va_list ap)
Definition: screen.c:73
Definition: tin.h:1533
time_t date
Definition: tin.h:1544
char * subject
Definition: tin.h:1535
int prev
Definition: tin.h:1549
char * refs
Definition: tin.h:1542
int thread
Definition: tin.h:1548
int score
Definition: tin.h:1550
int line_count
Definition: tin.h:1545
t_artnum artnum
Definition: tin.h:1534
int gnksa_code
Definition: tin.h:1546
unsigned int killed
Definition: tin.h:1552
char * msgid
Definition: tin.h:1541
t_bool selected
Definition: tin.h:1555
int tagged
Definition: tin.h:1547
char * from
Definition: tin.h:1536
char * name
Definition: tin.h:1537
unsigned int status
Definition: tin.h:1551
unsigned quick_select_expire
Definition: tin.h:1649
unsigned batch_save
Definition: tin.h:1658
unsigned quick_kill_header
Definition: tin.h:1645
unsigned thread_articles
Definition: tin.h:1677
unsigned quick_kill_expire
Definition: tin.h:1646
char * maildir
Definition: tin.h:1613
unsigned auto_select
Definition: tin.h:1657
char * quick_kill_scope
Definition: tin.h:1624
char * sigfile
Definition: tin.h:1616
char * savedir
Definition: tin.h:1614
unsigned global
Definition: tin.h:1644
char * savefile
Definition: tin.h:1615
char * quick_select_scope
Definition: tin.h:1625
unsigned quick_select_header
Definition: tin.h:1648
unsigned post_process_type
Definition: tin.h:1700
char * followup_to
Definition: tin.h:1623
unsigned show_author
Definition: tin.h:1680
unsigned sort_article_type
Definition: tin.h:1694
unsigned show_only_unread_arts
Definition: tin.h:1674
Definition: tin.h:1916
char * path
Definition: tin.h:1923
unsigned int inscope
Definition: tin.h:1931
char * msgid
Definition: tin.h:1921
int gnksa_num
Definition: tin.h:1927
char lines_cmp
Definition: tin.h:1929
struct t_filter_comment * comment
Definition: tin.h:1917
time_t time
Definition: tin.h:1925
unsigned int icase
Definition: tin.h:1932
int score
Definition: tin.h:1928
char * scope
Definition: tin.h:1918
char * subj
Definition: tin.h:1919
int lines_num
Definition: tin.h:1926
char gnksa_cmp
Definition: tin.h:1930
char * from
Definition: tin.h:1920
char * xref
Definition: tin.h:1922
struct t_filter * filter
Definition: tin.h:1902
int num
Definition: tin.h:1901
Definition: tin.h:1816
char * description
Definition: tin.h:1819
char moderated
Definition: tin.h:1821
t_artnum xmin
Definition: tin.h:1824
t_artnum xmax
Definition: tin.h:1823
struct t_attribute * attribute
Definition: tin.h:1834
int next
Definition: tin.h:1832
unsigned int type
Definition: tin.h:1825
t_bool subscribed
Definition: tin.h:1829
char * name
Definition: tin.h:1817
t_artnum count
Definition: tin.h:1822
char * spooldir
Definition: tin.h:1820
struct t_newsrc newsrc
Definition: tin.h:1833
Definition: tin.h:1804
t_artnum xbitlen
Definition: tin.h:1809
t_bool present
Definition: tin.h:1805
t_bitmap * xbitmap
Definition: tin.h:1810
t_artnum xmax
Definition: tin.h:1807
t_artnum num_unread
Definition: tin.h:1806
t_artnum xmin
Definition: tin.h:1808
long t_artnum
Definition: tin.h:229
#define SUB_CHAR(x)
Definition: tin.h:1369
#define TMPDIR
Definition: tin.h:2170
#define S_IWUGO
Definition: tin.h:2211
#define for_each_group(x)
Definition: tin.h:2259
#define for_each_art(x)
Definition: tin.h:2260
#define unlink(file)
Definition: tin.h:387
#define PATH_LEN
Definition: tin.h:843
#define GROUP_TYPE_NEWS
Definition: tin.h:1070
#define T_ARTNUM_PFMT
Definition: tin.h:230
#define ART_READ
Definition: tin.h:1345
#define S_IRUGO
Definition: tin.h:2210
#define ART_UNREAD
Definition: tin.h:1346
#define BlankIfNull(p)
Definition: tin.h:2255