"Fossies" - the Fresh Open Source Software Archive

Member "tin-2.4.5/src/memory.c" (1 Dec 2020, 14276 Bytes) of package /linux/misc/tin-2.4.5.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.4.4_vs_2.4.5.

    1 /*
    2  *  Project   : tin - a Usenet reader
    3  *  Module    : memory.c
    4  *  Author    : I. Lea & R. Skrenta
    5  *  Created   : 1991-04-01
    6  *  Updated   : 2020-05-19
    7  *  Notes     :
    8  *
    9  * Copyright (c) 1991-2021 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, 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) * max_active);
  101     newnews = my_malloc(sizeof(*newnews) * max_newnews);
  102     my_group = my_calloc(1, sizeof(int) * 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) * max_art);
  111     base = my_malloc(sizeof(t_artnum) * 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) * 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) * 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) * max_active);
  158         my_group = my_calloc(1, sizeof(int) * max_active);
  159     } else {
  160         active = my_realloc(active, sizeof(*active) * max_active);
  161         my_group = my_realloc(my_group, sizeof(int) * 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) * 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) * 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) * max_scope);
  191         num_scope = 0;
  192     } else {
  193         max_scope += max_scope >> 1;    /* increase by 50% */
  194         scopes = my_realloc(scopes, sizeof(*scopes) * 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) * 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) * 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) (cCOLS * MB_CUR_MAX + 2));
  221 #   else
  222             screen[i].col = my_malloc((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         if (arts[i].archive) {
  349             /* ->name is hashed */
  350             FreeAndNull(arts[i].archive->partnum);
  351             FreeAndNull(arts[i].archive);
  352         }
  353         arts[i].tagged = 0;
  354         arts[i].thread = ART_EXPIRED;
  355         arts[i].prev = ART_NORMAL;
  356         arts[i].status = ART_UNREAD;
  357         arts[i].killed = ART_NOTKILLED;
  358         arts[i].selected = FALSE;
  359     }
  360 }
  361 
  362 
  363 /*
  364  * Use this only for attributes that have a fixed default of a static string
  365  * in tinrc
  366  */
  367 static void
  368 free_if_not_default(
  369     char **attrib,
  370     char *deflt)
  371 {
  372     if (*attrib != deflt)
  373         FreeAndNull(*attrib);
  374 }
  375 
  376 
  377 /*
  378  * Free memory of one attributes struct only
  379  */
  380 static void
  381 free_attributes(
  382     struct t_attribute *attributes)
  383 {
  384     free_if_not_default(&attributes->group_format, tinrc.group_format);
  385     free_if_not_default(&attributes->thread_format, tinrc.thread_format);
  386     free_if_not_default(&attributes->date_format, tinrc.date_format);
  387     free_if_not_default(&attributes->editor_format, tinrc.editor_format);
  388     FreeAndNull(attributes->fcc);
  389     free_if_not_default(&attributes->from, tinrc.mail_address);
  390     FreeAndNull(attributes->followup_to);
  391 #ifdef HAVE_ISPELL
  392     FreeAndNull(attributes->ispell);
  393 #endif /* HAVE_ISPELL */
  394     free_if_not_default(&attributes->maildir, tinrc.maildir);
  395     FreeAndNull(attributes->mailing_list);
  396     FreeAndNull(attributes->mime_types_to_save);
  397     free_if_not_default(&attributes->news_headers_to_display, tinrc.news_headers_to_display);
  398     free_if_not_default(&attributes->news_headers_to_not_display, tinrc.news_headers_to_not_display);
  399     if (attributes->headers_to_display) {
  400         if (attributes->headers_to_display->header)
  401             FreeIfNeeded(*attributes->headers_to_display->header);
  402         FreeAndNull(attributes->headers_to_display->header);
  403         free(attributes->headers_to_display);
  404         attributes->headers_to_display = (struct t_newsheader *) 0;
  405     }
  406     if (attributes->headers_to_not_display) {
  407         if (attributes->headers_to_not_display->header)
  408             FreeIfNeeded(*attributes->headers_to_not_display->header);
  409         FreeAndNull(attributes->headers_to_not_display->header);
  410         free(attributes->headers_to_not_display);
  411         attributes->headers_to_not_display = (struct t_newsheader *) 0;
  412     }
  413     free_if_not_default(&attributes->news_quote_format, tinrc.news_quote_format);
  414     free_if_not_default(&attributes->organization, default_organization);
  415     FreeAndNull(attributes->quick_kill_scope);
  416     FreeAndNull(attributes->quick_select_scope);
  417     free_if_not_default(&attributes->quote_chars, tinrc.quote_chars);
  418     free_if_not_default(&attributes->savedir, tinrc.savedir);
  419     FreeAndNull(attributes->savefile);
  420     free_if_not_default(&attributes->sigfile, tinrc.sigfile);
  421 #ifdef CHARSET_CONVERSION
  422     FreeAndNull(attributes->undeclared_charset);
  423 #endif /* CHARSET_CONVERSION */
  424     FreeAndNull(attributes->x_headers);
  425     FreeAndNull(attributes->x_body);
  426 }
  427 
  428 
  429 void
  430 free_scope(
  431     int num)
  432 {
  433     struct t_scope *scope;
  434 
  435     scope = &scopes[num];
  436     FreeAndNull(scope->scope);
  437     free_attributes(scope->attribute);
  438     free(scope->attribute);
  439     scope->attribute = (struct t_attribute *) 0;
  440     free(scope->state);
  441     scope->state = (struct t_attribute_state *) 0;
  442 }
  443 
  444 
  445 static void
  446 free_scopes_arrays(
  447     void)
  448 {
  449     while (num_scope > 0)
  450         free_scope(--num_scope);
  451     FreeAndNull(scopes);
  452     num_scope = -1;
  453 }
  454 
  455 
  456 static void
  457 free_active_arrays(
  458     void)
  459 {
  460     FreeAndNull(my_group);  /* my_group[] */
  461 
  462     if (active != NULL) {   /* active[] */
  463         int i;
  464 
  465         for_each_group(i) {
  466             FreeAndNull(active[i].name);
  467             FreeAndNull(active[i].description);
  468             FreeAndNull(active[i].aliasedto);
  469             if (active[i].type == GROUP_TYPE_MAIL || active[i].type == GROUP_TYPE_SAVE) {
  470                 FreeAndNull(active[i].spooldir);
  471             }
  472             FreeAndNull(active[i].newsrc.xbitmap);
  473             if (active[i].attribute && !active[i].attribute->global) {
  474                 free(active[i].attribute);
  475                 active[i].attribute = (struct t_attribute *) 0;
  476             }
  477         }
  478         FreeAndNull(active);
  479     }
  480     num_active = -1;
  481 }
  482 
  483 
  484 void
  485 free_save_array(
  486     void)
  487 {
  488     int i;
  489 
  490     for (i = 0; i < num_save; i++) {
  491         FreeAndNull(save[i].path);
  492         /* file does NOT need to be freed */
  493         save[i].file = NULL;
  494         save[i].mailbox = FALSE;
  495     }
  496     num_save = 0;
  497 }
  498 
  499 
  500 static void
  501 free_newnews_array(
  502     void)
  503 {
  504     int i;
  505 
  506     for (i = 0; i < num_newnews; i++)
  507         FreeAndNull(newnews[i].host);
  508 
  509     num_newnews = 0;
  510 }
  511 
  512 
  513 static void
  514 free_input_history(
  515     void)
  516 {
  517     int his_w, his_e;
  518 
  519     for (his_w = 0; his_w <= HIST_MAXNUM; his_w++) {
  520         for (his_e = 0; his_e < HIST_SIZE; his_e++) {
  521             FreeIfNeeded(input_history[his_w][his_e]);
  522         }
  523     }
  524 }
  525 
  526 
  527 void *
  528 my_malloc1(
  529     const char *file,
  530     int line,
  531     size_t size)
  532 {
  533     void *p;
  534 
  535 #ifdef DEBUG
  536     if (debug & DEBUG_MEM)
  537         debug_print_malloc(TRUE, file, line, size);
  538 #endif /* DEBUG */
  539 
  540     if ((p = malloc(size)) == NULL) {
  541         error_message(2, txt_out_of_memory, tin_progname, (unsigned long) size, file, line);
  542         giveup();
  543     }
  544     return p;
  545 }
  546 
  547 
  548 /*
  549  * TODO: add fallback code with malloc(nmemb*size);memset(0,nmemb*size)?
  550  */
  551 void *
  552 my_calloc1(
  553     const char *file,
  554     int line,
  555     size_t nmemb,
  556     size_t size)
  557 {
  558     void *p;
  559 
  560 #ifdef DEBUG
  561     if (debug & DEBUG_MEM)
  562         debug_print_malloc(TRUE, file, line, nmemb * size);
  563 #endif /* DEBUG */
  564 
  565     if ((p = calloc(nmemb, size)) == NULL) {
  566         error_message(2, txt_out_of_memory, tin_progname, (unsigned long) (nmemb * size), file, line);
  567         giveup();
  568     }
  569     return p;
  570 }
  571 
  572 
  573 void *
  574 my_realloc1(
  575     const char *file,
  576     int line,
  577     void *p,
  578     size_t size)
  579 {
  580 #ifdef DEBUG
  581     if (debug & DEBUG_MEM)
  582         debug_print_malloc(FALSE, file, line, size);
  583 #endif /* DEBUG */
  584 
  585     if (!size) {
  586         if (p)
  587             free(p);
  588 
  589         return NULL;
  590     }
  591 
  592     if (p) {
  593         void *q = realloc(p, size);
  594 
  595         if (q != NULL)
  596              p = q;
  597         else {
  598             free(p);
  599             p = NULL;
  600         }
  601     } else
  602         p = malloc(size);
  603 
  604     if (p == NULL) {
  605         error_message(2, txt_out_of_memory, tin_progname, (unsigned long) size, file, line);
  606         giveup();
  607     }
  608     return p;
  609 }