"Fossies" - the Fresh Open Source Software Archive

Member "tin-2.6.2/src/memory.c" (9 Dec 2022, 13770 Bytes) of package /linux/misc/tin-2.6.2.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "memory.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 2.6.1_vs_2.6.2.

    1 /*
    2  *  Project   : tin - a Usenet reader
    3  *  Module    : memory.c
    4  *  Author    : I. Lea & R. Skrenta
    5  *  Created   : 1991-04-01
    6  *  Updated   : 2022-08-26
    7  *  Notes     :
    8  *
    9  * Copyright (c) 1991-2023 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  */
   50 int max_active;
   51 int num_active = -1;
   52 int max_newnews;
   53 int num_newnews = 0;
   54 int max_art;
   55 int max_base;
   56 int max_save;
   57 int num_save = 0;
   58 int max_scope;
   59 int num_scope = -1;
   60 
   61 /*
   62  * Dynamic arrays
   63  */
   64 int *my_group;              /* .newsrc --> active[] */
   65 t_artnum *base;             /* base articles for each thread */
   66 struct t_group *active;         /* active newsgroups */
   67 struct t_scope *scopes = NULL;  /* attributes stores in .tin/attributes */
   68 struct t_newnews *newnews;      /* active file sizes on different servers */
   69 struct t_article *arts;         /* articles headers in current group */
   70 struct t_save *save;            /* sorts articles before saving them */
   71 
   72 /*
   73  * Local prototypes
   74  */
   75 static void free_active_arrays(void);
   76 static void free_attributes(struct t_attribute *attributes);
   77 static void free_scopes_arrays(void);
   78 static void free_newnews_array(void);
   79 static void free_if_not_default(char **attrib, const char *deflt);
   80 static 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  */
   90 void
   91 init_alloc(
   92     void)
   93 {
   94     /*
   95      * active file arrays
   96      */
   97     max_active = DEFAULT_ACTIVE_NUM;
   98     max_newnews = DEFAULT_NEWNEWS_NUM;
   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      */
  107     max_art = DEFAULT_ARTICLE_NUM;
  108     max_base = DEFAULT_ARTICLE_NUM;
  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      */
  118     max_save = DEFAULT_SAVE_NUM;
  119 
  120     save = my_malloc(sizeof(*save) * (size_t) max_save);
  121 
  122     /*
  123      * scope array
  124      */
  125     max_scope = DEFAULT_SCOPE_NUM;
  126     expand_scope();
  127 
  128 #ifndef USE_CURSES
  129     screen = (struct t_screen *) 0;
  130 #endif /* !USE_CURSES */
  131 }
  132 
  133 
  134 void
  135 expand_art(
  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 
  151 void
  152 expand_active(
  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 
  166 void
  167 expand_base(
  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 
  175 void
  176 expand_save(
  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 
  184 void
  185 expand_scope(
  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 
  199 void
  200 expand_newnews(
  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
  209 void
  210 init_screen_array(
  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++)
  227                 FreeAndNull(screen[i].col);
  228 
  229             FreeAndNull(screen);
  230         }
  231     }
  232 }
  233 #endif /* !USE_CURSES */
  234 
  235 
  236 void
  237 free_all_arrays(
  238     void)
  239 {
  240     hash_reclaim();
  241 
  242 #ifndef USE_CURSES
  243     if (!batch_mode)
  244         init_screen_array(FALSE);
  245 #endif /* !USE_CURSES */
  246 
  247     free_art_array();
  248     free_msgids();
  249     FreeAndNull(arts);
  250     free_filter_array(&glob_filter);
  251     free_active_arrays();
  252     free_scopes_arrays();
  253 
  254 #ifdef HAVE_COLOR
  255     regex_cache_destroy(&quote_regex);
  256     regex_cache_destroy(&quote_regex2);
  257     regex_cache_destroy(&quote_regex3);
  258     regex_cache_destroy(&extquote_regex);
  259 #endif /* HAVE_COLOR */
  260     regex_cache_destroy(&slashes_regex);
  261     regex_cache_destroy(&stars_regex);
  262     regex_cache_destroy(&strokes_regex);
  263     regex_cache_destroy(&underscores_regex);
  264     regex_cache_destroy(&strip_re_regex);
  265     regex_cache_destroy(&strip_was_regex);
  266     regex_cache_destroy(&uubegin_regex);
  267     regex_cache_destroy(&uubody_regex);
  268     regex_cache_destroy(&verbatim_begin_regex);
  269     regex_cache_destroy(&verbatim_end_regex);
  270     regex_cache_destroy(&url_regex);
  271     regex_cache_destroy(&mail_regex);
  272     regex_cache_destroy(&news_regex);
  273     regex_cache_destroy(&shar_regex);
  274 
  275     if (!batch_mode) {
  276         free_keymaps();
  277         free_input_history();
  278     }
  279 
  280     FreeAndNull(base);
  281 
  282     if (save != NULL) {
  283         free_save_array();
  284         FreeAndNull(save);
  285     }
  286 
  287     if (newnews != NULL) {
  288         free_newnews_array();
  289         FreeAndNull(newnews);
  290     }
  291 
  292     FreeAndNull(nntp_caps.headers_range);
  293     FreeAndNull(nntp_caps.headers_id);
  294     FreeAndNull(nntp_caps.implementation);
  295 
  296     if (ofmt) { /* ofmt might not be allocated yet on early abort */
  297         int i;
  298         for (i = 0; ofmt[i].name; i++)
  299             free(ofmt[i].name);
  300         free(ofmt);
  301     }
  302 
  303     tin_fgets(NULL, FALSE);
  304     rfc1522_decode(NULL);
  305 
  306     free(tin_progname);
  307 }
  308 
  309 
  310 void
  311 free_art_array(
  312     void)
  313 {
  314     int i;
  315 
  316     for_each_art(i) {
  317         arts[i].artnum = T_ARTNUM_CONST(0);
  318         arts[i].date = (time_t) 0;
  319         FreeAndNull(arts[i].xref);
  320         FreeAndNull(arts[i].path);
  321 
  322         /*
  323          * .refs & .msgid are usually free()d in build_references()
  324          * nevertheless we try to free() it here in case tin_done()
  325          * was called before build_references()
  326          */
  327         FreeAndNull(arts[i].refs);
  328         FreeAndNull(arts[i].msgid);
  329 
  330         arts[i].tagged = 0;
  331         arts[i].thread = ART_EXPIRED;
  332         arts[i].prev = ART_NORMAL;
  333         arts[i].status = ART_UNREAD;
  334         arts[i].killed = ART_NOTKILLED;
  335         arts[i].selected = FALSE;
  336     }
  337 }
  338 
  339 
  340 /*
  341  * Use this only for attributes that have a fixed default of a static string
  342  * in tinrc
  343  */
  344 static void
  345 free_if_not_default(
  346     char **attrib,
  347     const char *deflt)
  348 {
  349     if (*attrib != deflt)
  350         FreeAndNull(*attrib);
  351 }
  352 
  353 
  354 /*
  355  * Free memory of one attributes struct only
  356  */
  357 static void
  358 free_attributes(
  359     struct t_attribute *attributes)
  360 {
  361     free_if_not_default(&attributes->group_format, tinrc.group_format);
  362     free_if_not_default(&attributes->thread_format, tinrc.thread_format);
  363     free_if_not_default(&attributes->date_format, tinrc.date_format);
  364     free_if_not_default(&attributes->editor_format, tinrc.editor_format);
  365     FreeAndNull(attributes->fcc);
  366     free_if_not_default(&attributes->from, tinrc.mail_address);
  367     FreeAndNull(attributes->followup_to);
  368 #ifdef HAVE_ISPELL
  369     FreeAndNull(attributes->ispell);
  370 #endif /* HAVE_ISPELL */
  371     free_if_not_default(&attributes->maildir, tinrc.maildir);
  372     FreeAndNull(attributes->mailing_list);
  373     FreeAndNull(attributes->mime_types_to_save);
  374     free_if_not_default(&attributes->news_headers_to_display, tinrc.news_headers_to_display);
  375     free_if_not_default(&attributes->news_headers_to_not_display, tinrc.news_headers_to_not_display);
  376     if (attributes->headers_to_display) {
  377         if (attributes->headers_to_display->header)
  378             FreeIfNeeded(*attributes->headers_to_display->header);
  379         FreeAndNull(attributes->headers_to_display->header);
  380         free(attributes->headers_to_display);
  381         attributes->headers_to_display = (struct t_newsheader *) 0;
  382     }
  383     if (attributes->headers_to_not_display) {
  384         if (attributes->headers_to_not_display->header)
  385             FreeIfNeeded(*attributes->headers_to_not_display->header);
  386         FreeAndNull(attributes->headers_to_not_display->header);
  387         free(attributes->headers_to_not_display);
  388         attributes->headers_to_not_display = (struct t_newsheader *) 0;
  389     }
  390     free_if_not_default(&attributes->news_quote_format, tinrc.news_quote_format);
  391     free_if_not_default(&attributes->organization, default_organization);
  392     FreeAndNull(attributes->quick_kill_scope);
  393     FreeAndNull(attributes->quick_select_scope);
  394     free_if_not_default(&attributes->quote_chars, tinrc.quote_chars);
  395     free_if_not_default(&attributes->savedir, tinrc.savedir);
  396     FreeAndNull(attributes->savefile);
  397     free_if_not_default(&attributes->sigfile, tinrc.sigfile);
  398 #ifdef CHARSET_CONVERSION
  399     FreeAndNull(attributes->undeclared_charset);
  400 #endif /* CHARSET_CONVERSION */
  401     FreeAndNull(attributes->x_headers);
  402     FreeAndNull(attributes->x_body);
  403 }
  404 
  405 
  406 void
  407 free_scope(
  408     int num)
  409 {
  410     struct t_scope *scope;
  411 
  412     scope = &scopes[num];
  413     FreeAndNull(scope->scope);
  414     free_attributes(scope->attribute);
  415     free(scope->attribute);
  416     scope->attribute = (struct t_attribute *) 0;
  417     free(scope->state);
  418     scope->state = (struct t_attribute_state *) 0;
  419 }
  420 
  421 
  422 static void
  423 free_scopes_arrays(
  424     void)
  425 {
  426     while (num_scope > 0)
  427         free_scope(--num_scope);
  428     FreeAndNull(scopes);
  429     num_scope = -1;
  430 }
  431 
  432 
  433 static void
  434 free_active_arrays(
  435     void)
  436 {
  437     FreeAndNull(my_group);  /* my_group[] */
  438 
  439     if (active != NULL) {   /* active[] */
  440         int i;
  441 
  442         for_each_group(i) {
  443             FreeAndNull(active[i].name);
  444             FreeAndNull(active[i].description);
  445             FreeAndNull(active[i].aliasedto);
  446             if (active[i].type == GROUP_TYPE_MAIL || active[i].type == GROUP_TYPE_SAVE) {
  447                 FreeAndNull(active[i].spooldir);
  448             }
  449             FreeAndNull(active[i].newsrc.xbitmap);
  450             if (active[i].attribute && !active[i].attribute->global) {
  451                 free(active[i].attribute);
  452                 active[i].attribute = (struct t_attribute *) 0;
  453             }
  454         }
  455         FreeAndNull(active);
  456     }
  457     num_active = -1;
  458 }
  459 
  460 
  461 void
  462 free_save_array(
  463     void)
  464 {
  465     int i;
  466 
  467     for (i = 0; i < num_save; i++) {
  468         FreeAndNull(save[i].path);
  469         /* file does NOT need to be freed */
  470         save[i].file = NULL;
  471         save[i].mailbox = FALSE;
  472     }
  473     num_save = 0;
  474 }
  475 
  476 
  477 static void
  478 free_newnews_array(
  479     void)
  480 {
  481     int i;
  482 
  483     for (i = 0; i < num_newnews; i++)
  484         FreeAndNull(newnews[i].host);
  485 
  486     num_newnews = 0;
  487 }
  488 
  489 
  490 static void
  491 free_input_history(
  492     void)
  493 {
  494     int his_w, his_e;
  495 
  496     for (his_w = 0; his_w <= HIST_MAXNUM; his_w++) {
  497         for (his_e = 0; his_e < HIST_SIZE; his_e++) {
  498             FreeIfNeeded(input_history[his_w][his_e]);
  499         }
  500     }
  501 }
  502 
  503 
  504 void *
  505 my_malloc1(
  506     const char *file,
  507     int line,
  508     size_t size)
  509 {
  510     void *p;
  511 
  512 #ifdef DEBUG
  513     if (debug & DEBUG_MEM)
  514         debug_print_malloc(TRUE, file, line, size);
  515 #endif /* DEBUG */
  516 
  517     if ((p = malloc(size)) == NULL) {
  518         error_message(2, txt_out_of_memory, tin_progname, (unsigned long) size, file, line);
  519         giveup();
  520     }
  521     return p;
  522 }
  523 
  524 
  525 /*
  526  * TODO: add fallback code with malloc(nmemb*size);memset(0,nmemb*size)?
  527  */
  528 void *
  529 my_calloc1(
  530     const char *file,
  531     int line,
  532     size_t nmemb,
  533     size_t size)
  534 {
  535     void *p;
  536 
  537 #ifdef DEBUG
  538     if (debug & DEBUG_MEM)
  539         debug_print_malloc(TRUE, file, line, nmemb * size);
  540 #endif /* DEBUG */
  541 
  542     if ((p = calloc(nmemb, size)) == NULL) {
  543         error_message(2, txt_out_of_memory, tin_progname, (unsigned long) (nmemb * size), file, line);
  544         giveup();
  545     }
  546     return p;
  547 }
  548 
  549 
  550 void *
  551 my_realloc1(
  552     const char *file,
  553     int line,
  554     void *p,
  555     size_t size)
  556 {
  557 #ifdef DEBUG
  558     if (debug & DEBUG_MEM)
  559         debug_print_malloc(FALSE, file, line, size);
  560 #endif /* DEBUG */
  561 
  562     if (!size) {
  563         if (p)
  564             free(p);
  565 
  566         return NULL;
  567     }
  568 
  569     if (p) {
  570         void *q = realloc(p, size);
  571 
  572         if (q != NULL)
  573             p = q;
  574         else {
  575             free(p);
  576             p = NULL;
  577         }
  578     } else
  579         p = malloc(size);
  580 
  581     if (p == NULL) {
  582         error_message(2, txt_out_of_memory, tin_progname, (unsigned long) size, file, line);
  583         giveup();
  584     }
  585     return p;
  586 }