"Fossies" - the Fresh Open Source Software Archive

Member "tin-2.4.3/src/memory.c" (23 Nov 2018, 14014 Bytes) of package /linux/misc/tin-2.4.3.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.2_vs_2.4.3.

    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-2019 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  * 1. Redistributions of source code must retain the above copyright
   16  *    notice, this list of conditions and the following disclaimer.
   17  * 2. Redistributions in binary form must reproduce the above copyright
   18  *    notice, this list of conditions and the following disclaimer in the
   19  *    documentation and/or other materials provided with the distribution.
   20  * 3. The name of the author may not be used to endorse or promote
   21  *    products derived from this software without specific prior written
   22  *    permission.
   23  *
   24  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
   25  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   26  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
   28  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
   30  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   31  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
   32  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
   33  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
   34  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   35  */
   36 
   37 
   38 #ifndef TIN_H
   39 #   include "tin.h"
   40 #endif /* !TIN_H */
   41 
   42 
   43 /*
   44  * Dynamic arrays maximum (initialized in init_alloc()) & current sizes
   45  * num_* values are one past top of used part of array
   46  */
   47 int max_active;
   48 int num_active = -1;
   49 int max_newnews;
   50 int num_newnews = 0;
   51 int max_art;
   52 int max_base;
   53 int max_save;
   54 int num_save = 0;
   55 int max_scope;
   56 int num_scope = -1;
   57 
   58 /*
   59  * Dynamic arrays
   60  */
   61 int *my_group;              /* .newsrc --> active[] */
   62 t_artnum *base;             /* base articles for each thread */
   63 struct t_group *active;         /* active newsgroups */
   64 struct t_scope *scopes = NULL;  /* attributes stores in .tin/attributes */
   65 struct t_newnews *newnews;      /* active file sizes on different servers */
   66 struct t_article *arts;         /* articles headers in current group */
   67 struct t_save *save;            /* sorts articles before saving them */
   68 
   69 /*
   70  * Local prototypes
   71  */
   72 static void free_active_arrays(void);
   73 static void free_attributes(struct t_attribute *attributes);
   74 static void free_scopes_arrays(void);
   75 static void free_newnews_array(void);
   76 static void free_if_not_default(char **attrib, char *deflt);
   77 static void free_input_history(void);
   78 
   79 
   80 /*
   81  * Dynamic table management
   82  * These settings are memory conservative: small initial allocations
   83  * and a 50% expansion on table overflow. A fast vm system with
   84  * much memory might want to start with higher initial allocations
   85  * and a 100% expansion on overflow, especially for the arts[] array.
   86  */
   87 void
   88 init_alloc(
   89     void)
   90 {
   91     /*
   92      * active file arrays
   93      */
   94     max_active = DEFAULT_ACTIVE_NUM;
   95     max_newnews = DEFAULT_NEWNEWS_NUM;
   96 
   97     active = my_malloc(sizeof(*active) * max_active);
   98     newnews = my_malloc(sizeof(*newnews) * max_newnews);
   99     my_group = my_calloc(1, sizeof(int) * max_active);
  100 
  101     /*
  102      * article headers array
  103      */
  104     max_art = DEFAULT_ARTICLE_NUM;
  105     max_base = DEFAULT_ARTICLE_NUM;
  106 
  107     arts = my_calloc(1, sizeof(*arts) * max_art);
  108     base = my_malloc(sizeof(t_artnum) * max_base);
  109 
  110     ofmt = my_calloc(1, sizeof(*ofmt) * 9); /* initial number of overview fields */
  111 
  112     /*
  113      * save file array
  114      */
  115     max_save = DEFAULT_SAVE_NUM;
  116 
  117     save = my_malloc(sizeof(*save) * max_save);
  118 
  119     /*
  120      * scope array
  121      */
  122     max_scope = DEFAULT_SCOPE_NUM;
  123     expand_scope();
  124 
  125 #ifndef USE_CURSES
  126     screen = (struct t_screen *) 0;
  127 #endif /* !USE_CURSES */
  128 }
  129 
  130 
  131 void
  132 expand_art(
  133     void)
  134 {
  135     int i = max_art;
  136 
  137     max_art += max_art >> 1;        /* increase by 50% */
  138     arts = my_realloc(arts, sizeof(*arts) * max_art);
  139     for (; i < max_art; i++)        /* use memset() instead? */
  140         arts[i].subject = arts[i].from = arts[i].xref = arts[i].path = arts[i].refs = arts[i].msgid = NULL;
  141 }
  142 
  143 
  144 void
  145 expand_active(
  146     void)
  147 {
  148     max_active += max_active >> 1;      /* increase by 50% */
  149     if (active == NULL) {
  150         active = my_malloc(sizeof(*active) * max_active);
  151         my_group = my_calloc(1, sizeof(int) * max_active);
  152     } else {
  153         active = my_realloc(active, sizeof(*active) * max_active);
  154         my_group = my_realloc(my_group, sizeof(int) * max_active);
  155     }
  156 }
  157 
  158 
  159 void
  160 expand_base(
  161     void)
  162 {
  163     max_base += max_base >> 1;      /* increase by 50% */
  164     base = my_realloc(base, sizeof(t_artnum) * max_base);
  165 }
  166 
  167 
  168 void
  169 expand_save(
  170     void)
  171 {
  172     max_save += max_save >> 1;      /* increase by 50% */
  173     save = my_realloc(save, sizeof(struct t_save) * max_save);
  174 }
  175 
  176 
  177 void
  178 expand_scope(
  179     void)
  180 {
  181     if ((scopes == NULL) || (num_scope < 0)) {
  182         if (scopes == NULL)
  183             scopes = my_malloc(sizeof(*scopes) * max_scope);
  184         num_scope = 0;
  185     } else {
  186         max_scope += max_scope >> 1;    /* increase by 50% */
  187         scopes = my_realloc(scopes, sizeof(*scopes) * max_scope);
  188     }
  189 }
  190 
  191 
  192 void
  193 expand_newnews(
  194     void)
  195 {
  196     max_newnews += max_newnews >> 1;            /* increase by 50% */
  197     newnews = my_realloc(newnews, sizeof(struct t_newnews) * max_newnews);
  198 }
  199 
  200 
  201 #ifndef USE_CURSES
  202 void
  203 init_screen_array(
  204     t_bool allocate)
  205 {
  206     int i;
  207 
  208     if (allocate) {
  209         screen = my_malloc(sizeof(struct t_screen) * cLINES + 1);
  210 
  211         for (i = 0; i < cLINES; i++)
  212 #   if defined(MULTIBYTE_ABLE) && !defined(NO_LOCALE)
  213             screen[i].col = my_malloc((size_t) (cCOLS * MB_CUR_MAX + 2));
  214 #   else
  215             screen[i].col = my_malloc((size_t) (cCOLS + 2));
  216 #   endif /* MULTIBYTE_ABLE && !NO_LOCALE */
  217     } else {
  218         if (screen != NULL) {
  219             for (i = 0; i < cLINES; i++)
  220                 FreeAndNull(screen[i].col);
  221 
  222             FreeAndNull(screen);
  223         }
  224     }
  225 }
  226 #endif /* !USE_CURSES */
  227 
  228 
  229 void
  230 free_all_arrays(
  231     void)
  232 {
  233     hash_reclaim();
  234 
  235 #ifndef USE_CURSES
  236     if (!batch_mode)
  237         init_screen_array(FALSE);
  238 #endif /* !USE_CURSES */
  239 
  240     free_art_array();
  241     free_msgids();
  242     FreeAndNull(arts);
  243     free_filter_array(&glob_filter);
  244     free_active_arrays();
  245     free_scopes_arrays();
  246 
  247 #ifdef HAVE_COLOR
  248     FreeIfNeeded(quote_regex.re);
  249     FreeIfNeeded(quote_regex.extra);
  250     FreeIfNeeded(quote_regex2.re);
  251     FreeIfNeeded(quote_regex2.extra);
  252     FreeIfNeeded(quote_regex3.re);
  253     FreeIfNeeded(quote_regex3.extra);
  254     FreeIfNeeded(extquote_regex.re);
  255     FreeIfNeeded(extquote_regex.extra);
  256 #endif /* HAVE_COLOR */
  257     FreeIfNeeded(slashes_regex.re);
  258     FreeIfNeeded(slashes_regex.extra);
  259     FreeIfNeeded(stars_regex.re);
  260     FreeIfNeeded(stars_regex.extra);
  261     FreeIfNeeded(strokes_regex.re);
  262     FreeIfNeeded(strokes_regex.extra);
  263     FreeIfNeeded(underscores_regex.re);
  264     FreeIfNeeded(underscores_regex.extra);
  265     FreeIfNeeded(strip_re_regex.re);
  266     FreeIfNeeded(strip_re_regex.extra);
  267     FreeIfNeeded(strip_was_regex.re);
  268     FreeIfNeeded(strip_was_regex.extra);
  269     FreeIfNeeded(uubegin_regex.re);
  270     FreeIfNeeded(uubegin_regex.extra);
  271     FreeIfNeeded(uubody_regex.re);
  272     FreeIfNeeded(uubody_regex.extra);
  273     FreeIfNeeded(verbatim_begin_regex.re);
  274     FreeIfNeeded(verbatim_begin_regex.extra);
  275     FreeIfNeeded(verbatim_end_regex.re);
  276     FreeIfNeeded(verbatim_end_regex.extra);
  277     FreeIfNeeded(url_regex.re);
  278     FreeIfNeeded(url_regex.extra);
  279     FreeIfNeeded(mail_regex.re);
  280     FreeIfNeeded(mail_regex.extra);
  281     FreeIfNeeded(news_regex.re);
  282     FreeIfNeeded(news_regex.extra);
  283     FreeIfNeeded(shar_regex.re);
  284     FreeIfNeeded(shar_regex.extra);
  285 
  286     if (!batch_mode) {
  287         free_keymaps();
  288         free_input_history();
  289     }
  290 
  291     FreeAndNull(base);
  292 
  293     if (save != NULL) {
  294         free_save_array();
  295         FreeAndNull(save);
  296     }
  297 
  298     if (newnews != NULL) {
  299         free_newnews_array();
  300         FreeAndNull(newnews);
  301     }
  302 
  303     FreeAndNull(nntp_caps.headers_range);
  304     FreeAndNull(nntp_caps.headers_id);
  305     FreeAndNull(nntp_caps.implementation);
  306 
  307     if (ofmt) { /* ofmt might not be allocated yet on early abort */
  308         int i;
  309         for (i = 0; ofmt[i].name; i++)
  310             free(ofmt[i].name);
  311         free(ofmt);
  312     }
  313 
  314     tin_fgets(NULL, FALSE);
  315     rfc1522_decode(NULL);
  316 
  317     free(tin_progname);
  318 }
  319 
  320 
  321 void
  322 free_art_array(
  323     void)
  324 {
  325     int i;
  326 
  327     for_each_art(i) {
  328         arts[i].artnum = T_ARTNUM_CONST(0);
  329         arts[i].date = (time_t) 0;
  330         FreeAndNull(arts[i].xref);
  331         FreeAndNull(arts[i].path);
  332 
  333         /*
  334          * .refs & .msgid are usually free()d in build_references()
  335          * nevertheless we try to free() it here in case tin_done()
  336          * was called before build_references()
  337          */
  338         FreeAndNull(arts[i].refs);
  339         FreeAndNull(arts[i].msgid);
  340 
  341         if (arts[i].archive) {
  342             /* ->name is hashed */
  343             FreeAndNull(arts[i].archive->partnum);
  344             FreeAndNull(arts[i].archive);
  345         }
  346         arts[i].tagged = 0;
  347         arts[i].thread = ART_EXPIRED;
  348         arts[i].prev = ART_NORMAL;
  349         arts[i].status = ART_UNREAD;
  350         arts[i].killed = ART_NOTKILLED;
  351         arts[i].selected = FALSE;
  352     }
  353 }
  354 
  355 
  356 /*
  357  * Use this only for attributes that have a fixed default of a static string
  358  * in tinrc
  359  */
  360 static void
  361 free_if_not_default(
  362     char **attrib,
  363     char *deflt)
  364 {
  365     if (*attrib != deflt)
  366         FreeAndNull(*attrib);
  367 }
  368 
  369 
  370 /*
  371  * Free memory of one attributes struct only
  372  */
  373 static void
  374 free_attributes(
  375     struct t_attribute *attributes)
  376 {
  377     free_if_not_default(&attributes->group_format, tinrc.group_format);
  378     free_if_not_default(&attributes->thread_format, tinrc.thread_format);
  379     free_if_not_default(&attributes->date_format, tinrc.date_format);
  380     free_if_not_default(&attributes->editor_format, tinrc.editor_format);
  381     FreeAndNull(attributes->fcc);
  382     free_if_not_default(&attributes->from, tinrc.mail_address);
  383     FreeAndNull(attributes->followup_to);
  384 #ifdef HAVE_ISPELL
  385     FreeAndNull(attributes->ispell);
  386 #endif /* HAVE_ISPELL */
  387     free_if_not_default(&attributes->maildir, tinrc.maildir);
  388     FreeAndNull(attributes->mailing_list);
  389     FreeAndNull(attributes->mime_types_to_save);
  390     free_if_not_default(&attributes->news_headers_to_display, tinrc.news_headers_to_display);
  391     free_if_not_default(&attributes->news_headers_to_not_display, tinrc.news_headers_to_not_display);
  392     if (attributes->headers_to_display) {
  393         if (attributes->headers_to_display->header)
  394             FreeIfNeeded(*attributes->headers_to_display->header);
  395         FreeAndNull(attributes->headers_to_display->header);
  396         free(attributes->headers_to_display);
  397         attributes->headers_to_display = (struct t_newsheader *) 0;
  398     }
  399     if (attributes->headers_to_not_display) {
  400         if (attributes->headers_to_not_display->header)
  401             FreeIfNeeded(*attributes->headers_to_not_display->header);
  402         FreeAndNull(attributes->headers_to_not_display->header);
  403         free(attributes->headers_to_not_display);
  404         attributes->headers_to_not_display = (struct t_newsheader *) 0;
  405     }
  406     free_if_not_default(&attributes->news_quote_format, tinrc.news_quote_format);
  407     free_if_not_default(&attributes->organization, default_organization);
  408     FreeAndNull(attributes->quick_kill_scope);
  409     FreeAndNull(attributes->quick_select_scope);
  410     free_if_not_default(&attributes->quote_chars, tinrc.quote_chars);
  411     free_if_not_default(&attributes->savedir, tinrc.savedir);
  412     FreeAndNull(attributes->savefile);
  413     free_if_not_default(&attributes->sigfile, tinrc.sigfile);
  414 #ifdef CHARSET_CONVERSION
  415     FreeAndNull(attributes->undeclared_charset);
  416 #endif /* CHARSET_CONVERSION */
  417     FreeAndNull(attributes->x_headers);
  418     FreeAndNull(attributes->x_body);
  419 }
  420 
  421 
  422 void
  423 free_scope(
  424     int num)
  425 {
  426     struct t_scope *scope;
  427 
  428     scope = &scopes[num];
  429     FreeAndNull(scope->scope);
  430     free_attributes(scope->attribute);
  431     free(scope->attribute);
  432     scope->attribute = (struct t_attribute *) 0;
  433     free(scope->state);
  434     scope->state = (struct t_attribute_state *) 0;
  435 }
  436 
  437 
  438 static void
  439 free_scopes_arrays(
  440     void)
  441 {
  442     while (num_scope > 0)
  443         free_scope(--num_scope);
  444     FreeAndNull(scopes);
  445     num_scope = -1;
  446 }
  447 
  448 
  449 static void
  450 free_active_arrays(
  451     void)
  452 {
  453     FreeAndNull(my_group);  /* my_group[] */
  454 
  455     if (active != NULL) {   /* active[] */
  456         int i;
  457 
  458         for_each_group(i) {
  459             FreeAndNull(active[i].name);
  460             FreeAndNull(active[i].description);
  461             FreeAndNull(active[i].aliasedto);
  462             if (active[i].type == GROUP_TYPE_MAIL || active[i].type == GROUP_TYPE_SAVE) {
  463                 FreeAndNull(active[i].spooldir);
  464             }
  465             FreeAndNull(active[i].newsrc.xbitmap);
  466             if (active[i].attribute && !active[i].attribute->global) {
  467                 free(active[i].attribute);
  468                 active[i].attribute = (struct t_attribute *) 0;
  469             }
  470         }
  471         FreeAndNull(active);
  472     }
  473     num_active = -1;
  474 }
  475 
  476 
  477 void
  478 free_save_array(
  479     void)
  480 {
  481     int i;
  482 
  483     for (i = 0; i < num_save; i++) {
  484         FreeAndNull(save[i].path);
  485         /* file does NOT need to be freed */
  486         save[i].file = NULL;
  487         save[i].mailbox = FALSE;
  488     }
  489     num_save = 0;
  490 }
  491 
  492 
  493 static void
  494 free_newnews_array(
  495     void)
  496 {
  497     int i;
  498 
  499     for (i = 0; i < num_newnews; i++)
  500         FreeAndNull(newnews[i].host);
  501 
  502     num_newnews = 0;
  503 }
  504 
  505 
  506 static void
  507 free_input_history(
  508     void)
  509 {
  510     int his_w, his_e;
  511 
  512     for (his_w = 0; his_w <= HIST_MAXNUM; his_w++) {
  513         for (his_e = 0; his_e < HIST_SIZE; his_e++) {
  514             FreeIfNeeded(input_history[his_w][his_e]);
  515         }
  516     }
  517 }
  518 
  519 
  520 void *
  521 my_malloc1(
  522     const char *file,
  523     int line,
  524     size_t size)
  525 {
  526     void *p;
  527 
  528 #ifdef DEBUG
  529     debug_print_malloc(TRUE, file, line, size);
  530 #endif /* DEBUG */
  531 
  532     if ((p = malloc(size)) == NULL) {
  533         error_message(2, txt_out_of_memory, tin_progname, (unsigned long) size, file, line);
  534         giveup();
  535     }
  536     return p;
  537 }
  538 
  539 
  540 /*
  541  * TODO: add fallback code with malloc(nmemb*size);memset(0,nmemb*size)?
  542  */
  543 void *
  544 my_calloc1(
  545     const char *file,
  546     int line,
  547     size_t nmemb,
  548     size_t size)
  549 {
  550     void *p;
  551 
  552 #ifdef DEBUG
  553     debug_print_malloc(TRUE, file, line, nmemb * size);
  554 #endif /* DEBUG */
  555 
  556     if ((p = calloc(nmemb, size)) == NULL) {
  557         error_message(2, txt_out_of_memory, tin_progname, (unsigned long) (nmemb * size), file, line);
  558         giveup();
  559     }
  560     return p;
  561 }
  562 
  563 
  564 void *
  565 my_realloc1(
  566     const char *file,
  567     int line,
  568     void *p,
  569     size_t size)
  570 {
  571 #ifdef DEBUG
  572     debug_print_malloc(FALSE, file, line, size);
  573 #endif /* DEBUG */
  574 
  575     if (!size) {
  576         if (p)
  577             free(p);
  578 
  579         return NULL;
  580     }
  581 
  582     if (p) {
  583         void *q = realloc(p, size);
  584 
  585         if (q != NULL)
  586              p = q;
  587         else {
  588             free(p);
  589             p = NULL;
  590         }
  591     } else
  592         p = malloc(size);
  593 
  594     if (p == NULL) {
  595         error_message(2, txt_out_of_memory, tin_progname, (unsigned long) size, file, line);
  596         giveup();
  597     }
  598     return p;
  599 }