"Fossies" - the Fresh Open Source Software Archive

Member "tin-2.4.4/src/memory.c" (20 Nov 2019, 14116 Bytes) of package /linux/misc/tin-2.4.4.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.3_vs_2.4.4.

    1 /*
    2  *  Project   : tin - a Usenet reader
    3  *  Module    : memory.c
    4  *  Author    : I. Lea & R. Skrenta
    5  *  Created   : 1991-04-01
    6  *  Updated   : 2018-07-02
    7  *  Notes     :
    8  *
    9  * Copyright (c) 1991-2020 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     for (; i < max_art; i++)        /* use memset() instead? */
  143         arts[i].subject = arts[i].from = arts[i].xref = arts[i].path = arts[i].refs = arts[i].msgid = NULL;
  144 }
  145 
  146 
  147 void
  148 expand_active(
  149     void)
  150 {
  151     max_active += max_active >> 1;      /* increase by 50% */
  152     if (active == NULL) {
  153         active = my_malloc(sizeof(*active) * max_active);
  154         my_group = my_calloc(1, sizeof(int) * max_active);
  155     } else {
  156         active = my_realloc(active, sizeof(*active) * max_active);
  157         my_group = my_realloc(my_group, sizeof(int) * max_active);
  158     }
  159 }
  160 
  161 
  162 void
  163 expand_base(
  164     void)
  165 {
  166     max_base += max_base >> 1;      /* increase by 50% */
  167     base = my_realloc(base, sizeof(t_artnum) * max_base);
  168 }
  169 
  170 
  171 void
  172 expand_save(
  173     void)
  174 {
  175     max_save += max_save >> 1;      /* increase by 50% */
  176     save = my_realloc(save, sizeof(struct t_save) * max_save);
  177 }
  178 
  179 
  180 void
  181 expand_scope(
  182     void)
  183 {
  184     if ((scopes == NULL) || (num_scope < 0)) {
  185         if (scopes == NULL)
  186             scopes = my_malloc(sizeof(*scopes) * max_scope);
  187         num_scope = 0;
  188     } else {
  189         max_scope += max_scope >> 1;    /* increase by 50% */
  190         scopes = my_realloc(scopes, sizeof(*scopes) * max_scope);
  191     }
  192 }
  193 
  194 
  195 void
  196 expand_newnews(
  197     void)
  198 {
  199     max_newnews += max_newnews >> 1;            /* increase by 50% */
  200     newnews = my_realloc(newnews, sizeof(struct t_newnews) * max_newnews);
  201 }
  202 
  203 
  204 #ifndef USE_CURSES
  205 void
  206 init_screen_array(
  207     t_bool allocate)
  208 {
  209     int i;
  210 
  211     if (allocate) {
  212         screen = my_malloc(sizeof(struct t_screen) * cLINES + 1);
  213 
  214         for (i = 0; i < cLINES; i++)
  215 #   if defined(MULTIBYTE_ABLE) && !defined(NO_LOCALE)
  216             screen[i].col = my_malloc((size_t) (cCOLS * MB_CUR_MAX + 2));
  217 #   else
  218             screen[i].col = my_malloc((size_t) (cCOLS + 2));
  219 #   endif /* MULTIBYTE_ABLE && !NO_LOCALE */
  220     } else {
  221         if (screen != NULL) {
  222             for (i = 0; i < cLINES; i++)
  223                 FreeAndNull(screen[i].col);
  224 
  225             FreeAndNull(screen);
  226         }
  227     }
  228 }
  229 #endif /* !USE_CURSES */
  230 
  231 
  232 void
  233 free_all_arrays(
  234     void)
  235 {
  236     hash_reclaim();
  237 
  238 #ifndef USE_CURSES
  239     if (!batch_mode)
  240         init_screen_array(FALSE);
  241 #endif /* !USE_CURSES */
  242 
  243     free_art_array();
  244     free_msgids();
  245     FreeAndNull(arts);
  246     free_filter_array(&glob_filter);
  247     free_active_arrays();
  248     free_scopes_arrays();
  249 
  250 #ifdef HAVE_COLOR
  251     FreeIfNeeded(quote_regex.re);
  252     FreeIfNeeded(quote_regex.extra);
  253     FreeIfNeeded(quote_regex2.re);
  254     FreeIfNeeded(quote_regex2.extra);
  255     FreeIfNeeded(quote_regex3.re);
  256     FreeIfNeeded(quote_regex3.extra);
  257     FreeIfNeeded(extquote_regex.re);
  258     FreeIfNeeded(extquote_regex.extra);
  259 #endif /* HAVE_COLOR */
  260     FreeIfNeeded(slashes_regex.re);
  261     FreeIfNeeded(slashes_regex.extra);
  262     FreeIfNeeded(stars_regex.re);
  263     FreeIfNeeded(stars_regex.extra);
  264     FreeIfNeeded(strokes_regex.re);
  265     FreeIfNeeded(strokes_regex.extra);
  266     FreeIfNeeded(underscores_regex.re);
  267     FreeIfNeeded(underscores_regex.extra);
  268     FreeIfNeeded(strip_re_regex.re);
  269     FreeIfNeeded(strip_re_regex.extra);
  270     FreeIfNeeded(strip_was_regex.re);
  271     FreeIfNeeded(strip_was_regex.extra);
  272     FreeIfNeeded(uubegin_regex.re);
  273     FreeIfNeeded(uubegin_regex.extra);
  274     FreeIfNeeded(uubody_regex.re);
  275     FreeIfNeeded(uubody_regex.extra);
  276     FreeIfNeeded(verbatim_begin_regex.re);
  277     FreeIfNeeded(verbatim_begin_regex.extra);
  278     FreeIfNeeded(verbatim_end_regex.re);
  279     FreeIfNeeded(verbatim_end_regex.extra);
  280     FreeIfNeeded(url_regex.re);
  281     FreeIfNeeded(url_regex.extra);
  282     FreeIfNeeded(mail_regex.re);
  283     FreeIfNeeded(mail_regex.extra);
  284     FreeIfNeeded(news_regex.re);
  285     FreeIfNeeded(news_regex.extra);
  286     FreeIfNeeded(shar_regex.re);
  287     FreeIfNeeded(shar_regex.extra);
  288 
  289     if (!batch_mode) {
  290         free_keymaps();
  291         free_input_history();
  292     }
  293 
  294     FreeAndNull(base);
  295 
  296     if (save != NULL) {
  297         free_save_array();
  298         FreeAndNull(save);
  299     }
  300 
  301     if (newnews != NULL) {
  302         free_newnews_array();
  303         FreeAndNull(newnews);
  304     }
  305 
  306     FreeAndNull(nntp_caps.headers_range);
  307     FreeAndNull(nntp_caps.headers_id);
  308     FreeAndNull(nntp_caps.implementation);
  309 
  310     if (ofmt) { /* ofmt might not be allocated yet on early abort */
  311         int i;
  312         for (i = 0; ofmt[i].name; i++)
  313             free(ofmt[i].name);
  314         free(ofmt);
  315     }
  316 
  317     tin_fgets(NULL, FALSE);
  318     rfc1522_decode(NULL);
  319 
  320     free(tin_progname);
  321 }
  322 
  323 
  324 void
  325 free_art_array(
  326     void)
  327 {
  328     int i;
  329 
  330     for_each_art(i) {
  331         arts[i].artnum = T_ARTNUM_CONST(0);
  332         arts[i].date = (time_t) 0;
  333         FreeAndNull(arts[i].xref);
  334         FreeAndNull(arts[i].path);
  335 
  336         /*
  337          * .refs & .msgid are usually free()d in build_references()
  338          * nevertheless we try to free() it here in case tin_done()
  339          * was called before build_references()
  340          */
  341         FreeAndNull(arts[i].refs);
  342         FreeAndNull(arts[i].msgid);
  343 
  344         if (arts[i].archive) {
  345             /* ->name is hashed */
  346             FreeAndNull(arts[i].archive->partnum);
  347             FreeAndNull(arts[i].archive);
  348         }
  349         arts[i].tagged = 0;
  350         arts[i].thread = ART_EXPIRED;
  351         arts[i].prev = ART_NORMAL;
  352         arts[i].status = ART_UNREAD;
  353         arts[i].killed = ART_NOTKILLED;
  354         arts[i].selected = FALSE;
  355     }
  356 }
  357 
  358 
  359 /*
  360  * Use this only for attributes that have a fixed default of a static string
  361  * in tinrc
  362  */
  363 static void
  364 free_if_not_default(
  365     char **attrib,
  366     char *deflt)
  367 {
  368     if (*attrib != deflt)
  369         FreeAndNull(*attrib);
  370 }
  371 
  372 
  373 /*
  374  * Free memory of one attributes struct only
  375  */
  376 static void
  377 free_attributes(
  378     struct t_attribute *attributes)
  379 {
  380     free_if_not_default(&attributes->group_format, tinrc.group_format);
  381     free_if_not_default(&attributes->thread_format, tinrc.thread_format);
  382     free_if_not_default(&attributes->date_format, tinrc.date_format);
  383     free_if_not_default(&attributes->editor_format, tinrc.editor_format);
  384     FreeAndNull(attributes->fcc);
  385     free_if_not_default(&attributes->from, tinrc.mail_address);
  386     FreeAndNull(attributes->followup_to);
  387 #ifdef HAVE_ISPELL
  388     FreeAndNull(attributes->ispell);
  389 #endif /* HAVE_ISPELL */
  390     free_if_not_default(&attributes->maildir, tinrc.maildir);
  391     FreeAndNull(attributes->mailing_list);
  392     FreeAndNull(attributes->mime_types_to_save);
  393     free_if_not_default(&attributes->news_headers_to_display, tinrc.news_headers_to_display);
  394     free_if_not_default(&attributes->news_headers_to_not_display, tinrc.news_headers_to_not_display);
  395     if (attributes->headers_to_display) {
  396         if (attributes->headers_to_display->header)
  397             FreeIfNeeded(*attributes->headers_to_display->header);
  398         FreeAndNull(attributes->headers_to_display->header);
  399         free(attributes->headers_to_display);
  400         attributes->headers_to_display = (struct t_newsheader *) 0;
  401     }
  402     if (attributes->headers_to_not_display) {
  403         if (attributes->headers_to_not_display->header)
  404             FreeIfNeeded(*attributes->headers_to_not_display->header);
  405         FreeAndNull(attributes->headers_to_not_display->header);
  406         free(attributes->headers_to_not_display);
  407         attributes->headers_to_not_display = (struct t_newsheader *) 0;
  408     }
  409     free_if_not_default(&attributes->news_quote_format, tinrc.news_quote_format);
  410     free_if_not_default(&attributes->organization, default_organization);
  411     FreeAndNull(attributes->quick_kill_scope);
  412     FreeAndNull(attributes->quick_select_scope);
  413     free_if_not_default(&attributes->quote_chars, tinrc.quote_chars);
  414     free_if_not_default(&attributes->savedir, tinrc.savedir);
  415     FreeAndNull(attributes->savefile);
  416     free_if_not_default(&attributes->sigfile, tinrc.sigfile);
  417 #ifdef CHARSET_CONVERSION
  418     FreeAndNull(attributes->undeclared_charset);
  419 #endif /* CHARSET_CONVERSION */
  420     FreeAndNull(attributes->x_headers);
  421     FreeAndNull(attributes->x_body);
  422 }
  423 
  424 
  425 void
  426 free_scope(
  427     int num)
  428 {
  429     struct t_scope *scope;
  430 
  431     scope = &scopes[num];
  432     FreeAndNull(scope->scope);
  433     free_attributes(scope->attribute);
  434     free(scope->attribute);
  435     scope->attribute = (struct t_attribute *) 0;
  436     free(scope->state);
  437     scope->state = (struct t_attribute_state *) 0;
  438 }
  439 
  440 
  441 static void
  442 free_scopes_arrays(
  443     void)
  444 {
  445     while (num_scope > 0)
  446         free_scope(--num_scope);
  447     FreeAndNull(scopes);
  448     num_scope = -1;
  449 }
  450 
  451 
  452 static void
  453 free_active_arrays(
  454     void)
  455 {
  456     FreeAndNull(my_group);  /* my_group[] */
  457 
  458     if (active != NULL) {   /* active[] */
  459         int i;
  460 
  461         for_each_group(i) {
  462             FreeAndNull(active[i].name);
  463             FreeAndNull(active[i].description);
  464             FreeAndNull(active[i].aliasedto);
  465             if (active[i].type == GROUP_TYPE_MAIL || active[i].type == GROUP_TYPE_SAVE) {
  466                 FreeAndNull(active[i].spooldir);
  467             }
  468             FreeAndNull(active[i].newsrc.xbitmap);
  469             if (active[i].attribute && !active[i].attribute->global) {
  470                 free(active[i].attribute);
  471                 active[i].attribute = (struct t_attribute *) 0;
  472             }
  473         }
  474         FreeAndNull(active);
  475     }
  476     num_active = -1;
  477 }
  478 
  479 
  480 void
  481 free_save_array(
  482     void)
  483 {
  484     int i;
  485 
  486     for (i = 0; i < num_save; i++) {
  487         FreeAndNull(save[i].path);
  488         /* file does NOT need to be freed */
  489         save[i].file = NULL;
  490         save[i].mailbox = FALSE;
  491     }
  492     num_save = 0;
  493 }
  494 
  495 
  496 static void
  497 free_newnews_array(
  498     void)
  499 {
  500     int i;
  501 
  502     for (i = 0; i < num_newnews; i++)
  503         FreeAndNull(newnews[i].host);
  504 
  505     num_newnews = 0;
  506 }
  507 
  508 
  509 static void
  510 free_input_history(
  511     void)
  512 {
  513     int his_w, his_e;
  514 
  515     for (his_w = 0; his_w <= HIST_MAXNUM; his_w++) {
  516         for (his_e = 0; his_e < HIST_SIZE; his_e++) {
  517             FreeIfNeeded(input_history[his_w][his_e]);
  518         }
  519     }
  520 }
  521 
  522 
  523 void *
  524 my_malloc1(
  525     const char *file,
  526     int line,
  527     size_t size)
  528 {
  529     void *p;
  530 
  531 #ifdef DEBUG
  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     debug_print_malloc(TRUE, file, line, nmemb * size);
  557 #endif /* DEBUG */
  558 
  559     if ((p = calloc(nmemb, size)) == NULL) {
  560         error_message(2, txt_out_of_memory, tin_progname, (unsigned long) (nmemb * size), file, line);
  561         giveup();
  562     }
  563     return p;
  564 }
  565 
  566 
  567 void *
  568 my_realloc1(
  569     const char *file,
  570     int line,
  571     void *p,
  572     size_t size)
  573 {
  574 #ifdef DEBUG
  575     debug_print_malloc(FALSE, file, line, size);
  576 #endif /* DEBUG */
  577 
  578     if (!size) {
  579         if (p)
  580             free(p);
  581 
  582         return NULL;
  583     }
  584 
  585     if (p) {
  586         void *q = realloc(p, size);
  587 
  588         if (q != NULL)
  589              p = q;
  590         else {
  591             free(p);
  592             p = NULL;
  593         }
  594     } else
  595         p = malloc(size);
  596 
  597     if (p == NULL) {
  598         error_message(2, txt_out_of_memory, tin_progname, (unsigned long) size, file, line);
  599         giveup();
  600     }
  601     return p;
  602 }