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)  

memory.c
Go to the documentation of this file.
1/*
2 * Project : tin - a Usenet reader
3 * Module : memory.c
4 * Author : I. Lea & R. Skrenta
5 * Created : 1991-04-01
6 * Updated : 2021-09-22
7 * Notes :
8 *
9 * Copyright (c) 1991-2022 Iain Lea <iain@bricbrac.de>, Rich Skrenta <skrenta@pbm.com>
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
46/*
47 * Dynamic arrays maximum (initialized in init_alloc()) & current sizes
48 * num_* values are one past top of used part of array
49 */
51int num_active = -1;
57int num_save = 0;
59int num_scope = -1;
60
61/*
62 * Dynamic arrays
63 */
64int *my_group; /* .newsrc --> active[] */
65t_artnum *base; /* base articles for each thread */
66struct t_group *active; /* active newsgroups */
67struct t_scope *scopes = NULL; /* attributes stores in .tin/attributes */
68struct t_newnews *newnews; /* active file sizes on different servers */
69struct t_article *arts; /* articles headers in current group */
70struct t_save *save; /* sorts articles before saving them */
71
72/*
73 * Local prototypes
74 */
75static void free_active_arrays(void);
76static void free_attributes(struct t_attribute *attributes);
77static void free_scopes_arrays(void);
78static void free_newnews_array(void);
79static void free_if_not_default(char **attrib, const char *deflt);
80static void free_input_history(void);
81
82
83/*
84 * Dynamic table management
85 * These settings are memory conservative: small initial allocations
86 * and a 50% expansion on table overflow. A fast vm system with
87 * much memory might want to start with higher initial allocations
88 * and a 100% expansion on overflow, especially for the arts[] array.
89 */
90void
92 void)
93{
94 /*
95 * active file arrays
96 */
99
100 active = my_malloc(sizeof(*active) * (size_t) max_active);
101 newnews = my_malloc(sizeof(*newnews) * (size_t) max_newnews);
102 my_group = my_calloc(1, sizeof(int) * (size_t) max_active);
103
104 /*
105 * article headers array
106 */
109
110 arts = my_calloc(1, sizeof(*arts) * (size_t) max_art);
111 base = my_malloc(sizeof(t_artnum) * (size_t) max_base);
112
113 ofmt = my_calloc(1, sizeof(*ofmt) * 9); /* initial number of overview fields */
114
115 /*
116 * save file array
117 */
119
120 save = my_malloc(sizeof(*save) * (size_t) max_save);
121
122 /*
123 * scope array
124 */
126 expand_scope();
127
128#ifndef USE_CURSES
129 screen = (struct t_screen *) 0;
130#endif /* !USE_CURSES */
131}
132
133
134void
136 void)
137{
138 int i = max_art;
139
140 max_art += max_art >> 1; /* increase by 50% */
141 arts = my_realloc(arts, sizeof(*arts) * (size_t) max_art);
142 /*
143 * memset(&arts[i].artnum, 0, (max_art - i - 1) * sizeof(*arts));
144 * seems to be not faster at all
145 */
146 for (; i < max_art; i++)
147 arts[i].subject = arts[i].from = arts[i].xref = arts[i].path = arts[i].refs = arts[i].msgid = NULL;
148}
149
150
151void
153 void)
154{
155 max_active += max_active >> 1; /* increase by 50% */
156 if (active == NULL) {
157 active = my_malloc(sizeof(*active) * (size_t) max_active);
158 my_group = my_calloc(1, sizeof(int) * (size_t) max_active);
159 } else {
160 active = my_realloc(active, sizeof(*active) * (size_t) max_active);
161 my_group = my_realloc(my_group, sizeof(int) * (size_t) max_active);
162 }
163}
164
165
166void
168 void)
169{
170 max_base += max_base >> 1; /* increase by 50% */
171 base = my_realloc(base, sizeof(t_artnum) * (size_t) max_base);
172}
173
174
175void
177 void)
178{
179 max_save += max_save >> 1; /* increase by 50% */
180 save = my_realloc(save, sizeof(struct t_save) * (size_t) max_save);
181}
182
183
184void
186 void)
187{
188 if ((scopes == NULL) || (num_scope < 0)) {
189 if (scopes == NULL)
190 scopes = my_malloc(sizeof(*scopes) * (size_t) max_scope);
191 num_scope = 0;
192 } else {
193 max_scope += max_scope >> 1; /* increase by 50% */
194 scopes = my_realloc(scopes, sizeof(*scopes) * (size_t) max_scope);
195 }
196}
197
198
199void
201 void)
202{
203 max_newnews += max_newnews >> 1; /* increase by 50% */
204 newnews = my_realloc(newnews, sizeof(struct t_newnews) * (size_t) max_newnews);
205}
206
207
208#ifndef USE_CURSES
209void
211 t_bool allocate)
212{
213 int i;
214
215 if (allocate) {
216 screen = my_malloc(sizeof(struct t_screen) * (size_t) cLINES + 1);
217
218 for (i = 0; i < cLINES; i++)
219# if defined(MULTIBYTE_ABLE) && !defined(NO_LOCALE)
220 screen[i].col = my_malloc((size_t) ((size_t) cCOLS * MB_CUR_MAX + 2));
221# else
222 screen[i].col = my_malloc((size_t) ((size_t) cCOLS + 2));
223# endif /* MULTIBYTE_ABLE && !NO_LOCALE */
224 } else {
225 if (screen != NULL) {
226 for (i = 0; i < cLINES; i++)
228
230 }
231 }
232}
233#endif /* !USE_CURSES */
234
235
236void
238 void)
239{
240 hash_reclaim();
241
242#ifndef USE_CURSES
243 if (!batch_mode)
245#endif /* !USE_CURSES */
246
248 free_msgids();
253
254#ifdef HAVE_COLOR
255 FreeIfNeeded(quote_regex.re);
256 FreeIfNeeded(quote_regex.extra);
257 FreeIfNeeded(quote_regex2.re);
258 FreeIfNeeded(quote_regex2.extra);
259 FreeIfNeeded(quote_regex3.re);
260 FreeIfNeeded(quote_regex3.extra);
261 FreeIfNeeded(extquote_regex.re);
262 FreeIfNeeded(extquote_regex.extra);
263#endif /* HAVE_COLOR */
292
293 if (!batch_mode) {
294 free_keymaps();
296 }
297
299
300 if (save != NULL) {
303 }
304
305 if (newnews != NULL) {
308 }
309
313
314 if (ofmt) { /* ofmt might not be allocated yet on early abort */
315 int i;
316 for (i = 0; ofmt[i].name; i++)
317 free(ofmt[i].name);
318 free(ofmt);
319 }
320
321 tin_fgets(NULL, FALSE);
322 rfc1522_decode(NULL);
323
324 free(tin_progname);
325}
326
327
328void
330 void)
331{
332 int i;
333
334 for_each_art(i) {
335 arts[i].artnum = T_ARTNUM_CONST(0);
336 arts[i].date = (time_t) 0;
337 FreeAndNull(arts[i].xref);
338 FreeAndNull(arts[i].path);
339
340 /*
341 * .refs & .msgid are usually free()d in build_references()
342 * nevertheless we try to free() it here in case tin_done()
343 * was called before build_references()
344 */
345 FreeAndNull(arts[i].refs);
346 FreeAndNull(arts[i].msgid);
347
348 arts[i].tagged = 0;
350 arts[i].prev = ART_NORMAL;
353 arts[i].selected = FALSE;
354 }
355}
356
357
358/*
359 * Use this only for attributes that have a fixed default of a static string
360 * in tinrc
361 */
362static void
364 char **attrib,
365 const char *deflt)
366{
367 if (*attrib != deflt)
368 FreeAndNull(*attrib);
369}
370
371
372/*
373 * Free memory of one attributes struct only
374 */
375static void
377 struct t_attribute *attributes)
378{
383 FreeAndNull(attributes->fcc);
385 FreeAndNull(attributes->followup_to);
386#ifdef HAVE_ISPELL
387 FreeAndNull(attributes->ispell);
388#endif /* HAVE_ISPELL */
390 FreeAndNull(attributes->mailing_list);
391 FreeAndNull(attributes->mime_types_to_save);
394 if (attributes->headers_to_display) {
395 if (attributes->headers_to_display->header)
398 free(attributes->headers_to_display);
399 attributes->headers_to_display = (struct t_newsheader *) 0;
400 }
401 if (attributes->headers_to_not_display) {
402 if (attributes->headers_to_not_display->header)
405 free(attributes->headers_to_not_display);
406 attributes->headers_to_not_display = (struct t_newsheader *) 0;
407 }
410 FreeAndNull(attributes->quick_kill_scope);
411 FreeAndNull(attributes->quick_select_scope);
414 FreeAndNull(attributes->savefile);
416#ifdef CHARSET_CONVERSION
417 FreeAndNull(attributes->undeclared_charset);
418#endif /* CHARSET_CONVERSION */
419 FreeAndNull(attributes->x_headers);
420 FreeAndNull(attributes->x_body);
421}
422
423
424void
426 int num)
427{
428 struct t_scope *scope;
429
430 scope = &scopes[num];
431 FreeAndNull(scope->scope);
432 free_attributes(scope->attribute);
433 free(scope->attribute);
434 scope->attribute = (struct t_attribute *) 0;
435 free(scope->state);
436 scope->state = (struct t_attribute_state *) 0;
437}
438
439
440static void
442 void)
443{
444 while (num_scope > 0)
447 num_scope = -1;
448}
449
450
451static void
453 void)
454{
455 FreeAndNull(my_group); /* my_group[] */
456
457 if (active != NULL) { /* active[] */
458 int i;
459
460 for_each_group(i) {
462 FreeAndNull(active[i].description);
463 FreeAndNull(active[i].aliasedto);
464 if (active[i].type == GROUP_TYPE_MAIL || active[i].type == GROUP_TYPE_SAVE) {
466 }
467 FreeAndNull(active[i].newsrc.xbitmap);
468 if (active[i].attribute && !active[i].attribute->global) {
469 free(active[i].attribute);
470 active[i].attribute = (struct t_attribute *) 0;
471 }
472 }
474 }
475 num_active = -1;
476}
477
478
479void
481 void)
482{
483 int i;
484
485 for (i = 0; i < num_save; i++) {
486 FreeAndNull(save[i].path);
487 /* file does NOT need to be freed */
488 save[i].file = NULL;
489 save[i].mailbox = FALSE;
490 }
491 num_save = 0;
492}
493
494
495static void
497 void)
498{
499 int i;
500
501 for (i = 0; i < num_newnews; i++)
502 FreeAndNull(newnews[i].host);
503
504 num_newnews = 0;
505}
506
507
508static void
510 void)
511{
512 int his_w, his_e;
513
514 for (his_w = 0; his_w <= HIST_MAXNUM; his_w++) {
515 for (his_e = 0; his_e < HIST_SIZE; his_e++) {
516 FreeIfNeeded(input_history[his_w][his_e]);
517 }
518 }
519}
520
521
522void *
524 const char *file,
525 int line,
526 size_t size)
527{
528 void *p;
529
530#ifdef DEBUG
531 if (debug & DEBUG_MEM)
532 debug_print_malloc(TRUE, file, line, size);
533#endif /* DEBUG */
534
535 if ((p = malloc(size)) == NULL) {
536 error_message(2, txt_out_of_memory, tin_progname, (unsigned long) size, file, line);
537 giveup();
538 }
539 return p;
540}
541
542
543/*
544 * TODO: add fallback code with malloc(nmemb*size);memset(0,nmemb*size)?
545 */
546void *
548 const char *file,
549 int line,
550 size_t nmemb,
551 size_t size)
552{
553 void *p;
554
555#ifdef DEBUG
556 if (debug & DEBUG_MEM)
557 debug_print_malloc(TRUE, file, line, nmemb * size);
558#endif /* DEBUG */
559
560 if ((p = calloc(nmemb, size)) == NULL) {
561 error_message(2, txt_out_of_memory, tin_progname, (unsigned long) (nmemb * size), file, line);
562 giveup();
563 }
564 return p;
565}
566
567
568void *
570 const char *file,
571 int line,
572 void *p,
573 size_t size)
574{
575#ifdef DEBUG
576 if (debug & DEBUG_MEM)
577 debug_print_malloc(FALSE, file, line, size);
578#endif /* DEBUG */
579
580 if (!size) {
581 if (p)
582 free(p);
583
584 return NULL;
585 }
586
587 if (p) {
588 void *q = realloc(p, size);
589
590 if (q != NULL)
591 p = q;
592 else {
593 free(p);
594 p = NULL;
595 }
596 } else
597 p = malloc(size);
598
599 if (p == NULL) {
600 error_message(2, txt_out_of_memory, tin_progname, (unsigned long) size, file, line);
601 giveup();
602 }
603 return p;
604}
unsigned t_bool
Definition: bool.h:77
#define TRUE
Definition: bool.h:74
#define FALSE
Definition: bool.h:70
#define DEBUG_MEM
Definition: debug.h:52
struct t_filters glob_filter
Definition: filter.c:87
char * input_history[HIST_URL+1][15+1]
Definition: init.c:169
struct regex_cache verbatim_begin_regex
struct t_capabilities nntp_caps
Definition: init.c:513
struct regex_cache uubody_regex
struct regex_cache strip_re_regex
struct regex_cache shar_regex
#define HIST_MAXNUM
Definition: extern.h:1579
struct regex_cache uubegin_regex
struct t_overview_fmt * ofmt
Definition: xref.c:53
#define HIST_SIZE
Definition: extern.h:1581
struct regex_cache stars_regex
struct regex_cache url_regex
struct regex_cache verbatim_end_regex
struct regex_cache slashes_regex
char newsrc[PATH_LEN]
Definition: init.c:96
struct regex_cache news_regex
int cCOLS
Definition: curses.c:53
struct regex_cache mail_regex
int cLINES
Definition: curses.c:52
char * tin_progname
Definition: init.c:105
constext txt_out_of_memory[]
Definition: lang.c:724
struct regex_cache strokes_regex
Definition: init.c:185
struct t_config tinrc
Definition: init.c:192
unsigned short debug
Definition: debug.c:51
char default_organization[PATH_LEN]
Definition: init.c:73
char spooldir[PATH_LEN]
Definition: init.c:102
struct t_screen * screen
Definition: screen.c:51
struct regex_cache strip_was_regex
t_bool batch_mode
Definition: init.c:127
struct regex_cache underscores_regex
void expand_scope(void)
Definition: memory.c:185
void expand_active(void)
Definition: memory.c:152
int max_newnews
Definition: memory.c:52
int * my_group
Definition: memory.c:64
struct t_scope * scopes
Definition: memory.c:67
void init_alloc(void)
Definition: memory.c:91
void * my_realloc1(const char *file, int line, void *p, size_t size)
Definition: memory.c:569
int max_base
Definition: memory.c:55
void expand_art(void)
Definition: memory.c:135
struct t_newnews * newnews
Definition: memory.c:68
void expand_base(void)
Definition: memory.c:167
struct t_article * arts
Definition: memory.c:69
static void free_active_arrays(void)
Definition: memory.c:452
int num_save
Definition: memory.c:57
struct t_save * save
Definition: memory.c:70
void free_all_arrays(void)
Definition: memory.c:237
static void free_input_history(void)
Definition: memory.c:509
int max_art
Definition: memory.c:54
static void free_if_not_default(char **attrib, const char *deflt)
Definition: memory.c:363
void expand_save(void)
Definition: memory.c:176
int num_scope
Definition: memory.c:59
void free_art_array(void)
Definition: memory.c:329
t_artnum * base
Definition: memory.c:65
int max_active
Definition: memory.c:50
void * my_malloc1(const char *file, int line, size_t size)
Definition: memory.c:523
static void free_scopes_arrays(void)
Definition: memory.c:441
static void free_newnews_array(void)
Definition: memory.c:496
int max_save
Definition: memory.c:56
void free_save_array(void)
Definition: memory.c:480
void * my_calloc1(const char *file, int line, size_t nmemb, size_t size)
Definition: memory.c:547
int num_newnews
Definition: memory.c:53
void init_screen_array(t_bool allocate)
Definition: memory.c:210
void expand_newnews(void)
Definition: memory.c:200
static void free_attributes(struct t_attribute *attributes)
Definition: memory.c:376
void free_scope(int num)
Definition: memory.c:425
int num_active
Definition: memory.c:51
struct t_group * active
Definition: memory.c:66
int max_scope
Definition: memory.c:58
void free_keymaps(void)
Definition: keymap.c:231
void error_message(unsigned int sdelay, const char *fmt,...)
Definition: screen.c:224
void free_filter_array(struct t_filters *ptr)
Definition: filter.c:288
void hash_reclaim(void)
Definition: hashstr.c:134
char * tin_fgets(FILE *fp, t_bool header)
Definition: read.c:317
void free_msgids(void)
Definition: refs.c:554
_Noreturn void giveup(void)
Definition: main.c:1058
char * rfc1522_decode(const char *s)
Definition: rfc2047.c:232
const char * name
Definition: signal.c:117
pcre_extra * extra
Definition: tin.h:1963
pcre * re
Definition: tin.h:1962
Definition: tin.h:1533
time_t date
Definition: tin.h:1544
int prev
Definition: tin.h:1549
int thread
Definition: tin.h:1548
t_artnum artnum
Definition: tin.h:1534
unsigned int killed
Definition: tin.h:1552
t_bool selected
Definition: tin.h:1555
int tagged
Definition: tin.h:1547
unsigned int status
Definition: tin.h:1551
char * news_headers_to_display
Definition: tin.h:1627
char * mime_types_to_save
Definition: tin.h:1634
char * group_format
Definition: tin.h:1617
char * maildir
Definition: tin.h:1613
char * mailing_list
Definition: tin.h:1626
char * quick_kill_scope
Definition: tin.h:1624
char * date_format
Definition: tin.h:1619
char * x_body
Definition: tin.h:1630
char * sigfile
Definition: tin.h:1616
char * fcc
Definition: tin.h:1622
char * savedir
Definition: tin.h:1614
char * from
Definition: tin.h:1631
char * news_quote_format
Definition: tin.h:1632
char * editor_format
Definition: tin.h:1620
char * savefile
Definition: tin.h:1615
char * quick_select_scope
Definition: tin.h:1625
char * thread_format
Definition: tin.h:1618
struct t_newsheader * headers_to_display
Definition: tin.h:1642
char * quote_chars
Definition: tin.h:1633
struct t_newsheader * headers_to_not_display
Definition: tin.h:1643
char * x_headers
Definition: tin.h:1629
char * followup_to
Definition: tin.h:1623
char * organization
Definition: tin.h:1621
char * news_headers_to_not_display
Definition: tin.h:1628
char * implementation
Definition: nntplib.h:212
char * headers_range
Definition: nntplib.h:196
char * headers_id
Definition: nntplib.h:197
char maildir[PATH_LEN]
Definition: tinrc.h:106
char group_format[LEN]
Definition: tinrc.h:283
char quote_chars[LEN]
Definition: tinrc.h:122
char mail_address[HEADER_LEN]
Definition: tinrc.h:108
char savedir[PATH_LEN]
Definition: tinrc.h:138
char thread_format[LEN]
Definition: tinrc.h:284
char news_quote_format[LEN]
Definition: tinrc.h:121
char sigfile[PATH_LEN]
Definition: tinrc.h:133
char date_format[LEN]
Definition: tinrc.h:285
char editor_format[PATH_LEN]
Definition: tinrc.h:80
char news_headers_to_display[LEN]
Definition: tinrc.h:119
char news_headers_to_not_display[LEN]
Definition: tinrc.h:120
Definition: tin.h:1816
struct t_attribute * attribute
Definition: tin.h:1834
int num
Definition: tin.h:1581
char ** header
Definition: tin.h:1580
char * name
Definition: tin.h:2537
Definition: tin.h:1966
char * file
Definition: tin.h:1968
t_bool mailbox
Definition: tin.h:1969
Definition: tin.h:1794
char * scope
Definition: tin.h:1795
struct t_attribute_state * state
Definition: tin.h:1797
Definition: tin.h:1973
char * col
Definition: tin.h:1974
#define ART_NOTKILLED
Definition: tin.h:1353
long t_artnum
Definition: tin.h:229
#define for_each_group(x)
Definition: tin.h:2259
#define for_each_art(x)
Definition: tin.h:2260
#define DEFAULT_ARTICLE_NUM
Definition: tin.h:617
#define my_malloc(size)
Definition: tin.h:2245
#define FreeIfNeeded(p)
Definition: tin.h:2252
#define ART_NORMAL
Definition: tin.h:1340
#define FreeAndNull(p)
Definition: tin.h:2253
#define T_ARTNUM_CONST(v)
Definition: tin.h:232
#define GROUP_TYPE_SAVE
Definition: tin.h:1071
#define ART_EXPIRED
Definition: tin.h:1335
#define GROUP_TYPE_MAIL
Definition: tin.h:1069
#define DEFAULT_SAVE_NUM
Definition: tin.h:618
#define my_realloc(ptr, size)
Definition: tin.h:2247
#define DEFAULT_SCOPE_NUM
Definition: tin.h:623
#define my_calloc(nmemb, size)
Definition: tin.h:2246
#define ART_UNREAD
Definition: tin.h:1346
#define DEFAULT_NEWNEWS_NUM
Definition: tin.h:621
#define DEFAULT_ACTIVE_NUM
Definition: tin.h:620