"Fossies" - the Fresh Open Source Software Archive

Member "tin-2.6.1/src/memory.c" (22 Dec 2021, 14328 Bytes) of package /linux/misc/tin-2.6.1.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.0_vs_2.6.1.

    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  */
   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     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 */
  264     FreeIfNeeded(slashes_regex.re);
  265     FreeIfNeeded(slashes_regex.extra);
  266     FreeIfNeeded(stars_regex.re);
  267     FreeIfNeeded(stars_regex.extra);
  268     FreeIfNeeded(strokes_regex.re);
  269     FreeIfNeeded(strokes_regex.extra);
  270     FreeIfNeeded(underscores_regex.re);
  271     FreeIfNeeded(underscores_regex.extra);
  272     FreeIfNeeded(strip_re_regex.re);
  273     FreeIfNeeded(strip_re_regex.extra);
  274     FreeIfNeeded(strip_was_regex.re);
  275     FreeIfNeeded(strip_was_regex.extra);
  276     FreeIfNeeded(uubegin_regex.re);
  277     FreeIfNeeded(uubegin_regex.extra);
  278     FreeIfNeeded(uubody_regex.re);
  279     FreeIfNeeded(uubody_regex.extra);
  280     FreeIfNeeded(verbatim_begin_regex.re);
  281     FreeIfNeeded(verbatim_begin_regex.extra);
  282     FreeIfNeeded(verbatim_end_regex.re);
  283     FreeIfNeeded(verbatim_end_regex.extra);
  284     FreeIfNeeded(url_regex.re);
  285     FreeIfNeeded(url_regex.extra);
  286     FreeIfNeeded(mail_regex.re);
  287     FreeIfNeeded(mail_regex.extra);
  288     FreeIfNeeded(news_regex.re);
  289     FreeIfNeeded(news_regex.extra);
  290     FreeIfNeeded(shar_regex.re);
  291     FreeIfNeeded(shar_regex.extra);
  292 
  293     if (!batch_mode) {
  294         free_keymaps();
  295         free_input_history();
  296     }
  297 
  298     FreeAndNull(base);
  299 
  300     if (save != NULL) {
  301         free_save_array();
  302         FreeAndNull(save);
  303     }
  304 
  305     if (newnews != NULL) {
  306         free_newnews_array();
  307         FreeAndNull(newnews);
  308     }
  309 
  310     FreeAndNull(nntp_caps.headers_range);
  311     FreeAndNull(nntp_caps.headers_id);
  312     FreeAndNull(nntp_caps.implementation);
  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 
  328 void
  329 free_art_array(
  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;
  349         arts[i].thread = ART_EXPIRED;
  350         arts[i].prev = ART_NORMAL;
  351         arts[i].status = ART_UNREAD;
  352         arts[i].killed = ART_NOTKILLED;
  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  */
  362 static void
  363 free_if_not_default(
  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  */
  375 static void
  376 free_attributes(
  377     struct t_attribute *attributes)
  378 {
  379     free_if_not_default(&attributes->group_format, tinrc.group_format);
  380     free_if_not_default(&attributes->thread_format, tinrc.thread_format);
  381     free_if_not_default(&attributes->date_format, tinrc.date_format);
  382     free_if_not_default(&attributes->editor_format, tinrc.editor_format);
  383     FreeAndNull(attributes->fcc);
  384     free_if_not_default(&attributes->from, tinrc.mail_address);
  385     FreeAndNull(attributes->followup_to);
  386 #ifdef HAVE_ISPELL
  387     FreeAndNull(attributes->ispell);
  388 #endif /* HAVE_ISPELL */
  389     free_if_not_default(&attributes->maildir, tinrc.maildir);
  390     FreeAndNull(attributes->mailing_list);
  391     FreeAndNull(attributes->mime_types_to_save);
  392     free_if_not_default(&attributes->news_headers_to_display, tinrc.news_headers_to_display);
  393     free_if_not_default(&attributes->news_headers_to_not_display, tinrc.news_headers_to_not_display);
  394     if (attributes->headers_to_display) {
  395         if (attributes->headers_to_display->header)
  396             FreeIfNeeded(*attributes->headers_to_display->header);
  397         FreeAndNull(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)
  403             FreeIfNeeded(*attributes->headers_to_not_display->header);
  404         FreeAndNull(attributes->headers_to_not_display->header);
  405         free(attributes->headers_to_not_display);
  406         attributes->headers_to_not_display = (struct t_newsheader *) 0;
  407     }
  408     free_if_not_default(&attributes->news_quote_format, tinrc.news_quote_format);
  409     free_if_not_default(&attributes->organization, default_organization);
  410     FreeAndNull(attributes->quick_kill_scope);
  411     FreeAndNull(attributes->quick_select_scope);
  412     free_if_not_default(&attributes->quote_chars, tinrc.quote_chars);
  413     free_if_not_default(&attributes->savedir, tinrc.savedir);
  414     FreeAndNull(attributes->savefile);
  415     free_if_not_default(&attributes->sigfile, tinrc.sigfile);
  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 
  424 void
  425 free_scope(
  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 
  440 static void
  441 free_scopes_arrays(
  442     void)
  443 {
  444     while (num_scope > 0)
  445         free_scope(--num_scope);
  446     FreeAndNull(scopes);
  447     num_scope = -1;
  448 }
  449 
  450 
  451 static void
  452 free_active_arrays(
  453     void)
  454 {
  455     FreeAndNull(my_group);  /* my_group[] */
  456 
  457     if (active != NULL) {   /* active[] */
  458         int i;
  459 
  460         for_each_group(i) {
  461             FreeAndNull(active[i].name);
  462             FreeAndNull(active[i].description);
  463             FreeAndNull(active[i].aliasedto);
  464             if (active[i].type == GROUP_TYPE_MAIL || active[i].type == GROUP_TYPE_SAVE) {
  465                 FreeAndNull(active[i].spooldir);
  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         }
  473         FreeAndNull(active);
  474     }
  475     num_active = -1;
  476 }
  477 
  478 
  479 void
  480 free_save_array(
  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 
  495 static void
  496 free_newnews_array(
  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 
  508 static void
  509 free_input_history(
  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 
  522 void *
  523 my_malloc1(
  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  */
  546 void *
  547 my_calloc1(
  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 
  568 void *
  569 my_realloc1(
  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 }