"Fossies" - the Fresh Open Source Software Archive

Member "tin-2.4.4/src/sigfile.c" (20 Nov 2019, 8471 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 "sigfile.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    : sigfile.c
    4  *  Author    : M. Gleason & I. Lea
    5  *  Created   : 1992-10-17
    6  *  Updated   : 2019-07-17
    7  *  Notes     : Generate random signature for posting/mailing etc.
    8  *
    9  * Copyright (c) 1992-2020 Mike Gleason
   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 #define MAXLOOPS 1000
   46 
   47 #define CURRENTDIR "."
   48 
   49 static char sigfile[PATH_LEN];
   50 
   51 static FILE *open_random_sig(char *sigdir);
   52 static int thrashdir(char *sigdir);
   53 
   54 
   55 void
   56 msg_write_signature(
   57     FILE *fp,
   58     t_bool include_dot_signature,
   59     struct t_group *thisgroup)
   60 {
   61     FILE *fixfp;
   62     FILE *sigfp;
   63     char cwd[PATH_LEN];
   64     char path[PATH_LEN];
   65     char pathfixed[PATH_LEN];
   66 
   67 #ifdef NNTP_INEWS
   68     if (read_news_via_nntp && !strcasecmp(tinrc.inews_prog, INTERNAL_CMD))
   69         include_dot_signature = TRUE;
   70 #endif /* NNTP_INEWS */
   71 
   72     if (thisgroup && !thisgroup->bogus) {
   73         if (!strcmp(thisgroup->attribute->sigfile, "--none"))
   74             return;
   75 
   76         /*
   77          * TODO: handle DONT_HAVE_PIPING case
   78          *       use strfpath()?
   79          */
   80 #ifndef DONT_HAVE_PIPING
   81         if (thisgroup->attribute->sigfile[0] == '!') {
   82             FILE *pipe_fp;
   83             char *sigcmd, *sigattr, *ptr;
   84             char cmd[PATH_LEN];
   85 
   86             fprintf(fp, "\n%s", thisgroup->attribute->sigdashes ? SIGDASHES : "\n");
   87             sigattr = thisgroup->attribute->sigfile + 1;
   88 
   89             if ((ptr = strstr(sigattr, "%G"))) {
   90                 char *to, *grpname;
   91                 int cnt = 1;
   92 
   93                 /* check if %G occurs more than once */
   94                 while (strstr(++ptr, "%G"))
   95                     ++cnt;
   96 
   97                 /* sigattr - (cnt * '%G') + (cnt * '"groupname"') + '\0' */
   98                 sigcmd = my_malloc(strlen(sigattr) + cnt * strlen(thisgroup->name) + 1);
   99                 to = sigcmd;
  100 
  101                 while (*sigattr) {
  102                     if (*sigattr == '%' && *(sigattr + 1) == 'G') {
  103                         grpname = thisgroup->name;
  104                         *to++ = '"';
  105                         while (*grpname)
  106                             *to++ = *grpname++;
  107                         *to++ = '"';
  108                         sigattr += 2;
  109                     } else
  110                         *to++ = *sigattr++;
  111                 }
  112 
  113                 *to = '\0';
  114             } else {
  115                 sigcmd = my_malloc(strlen(sigattr) + 1);
  116                 sprintf(sigcmd, "%s", sigattr);
  117             }
  118 
  119             if ((pipe_fp = popen(sigcmd, "r")) != NULL) {
  120                 while (fgets(cmd, PATH_LEN, pipe_fp))
  121                     fputs(cmd, fp);
  122                 pclose(pipe_fp);
  123             } /* else issue an error-message? */
  124             free(sigcmd);
  125 
  126             return;
  127         }
  128 #endif /* !DONT_HAVE_PIPING */
  129         get_cwd(cwd);
  130 
  131         if (!strfpath(thisgroup->attribute->sigfile, path, sizeof(path), thisgroup, FALSE)) {
  132             if (!strfpath(tinrc.sigfile, path, sizeof(path), thisgroup, FALSE))
  133                 joinpath(path, sizeof(path), homedir, ".Sig");
  134         }
  135 
  136         /*
  137          * Check to see if sigfile is a directory & if it is
  138          * generate a random signature from sigs in sigdir. If
  139          * the file path/.sigfixed or ~/.sigfixed exists (fixed
  140          * part of random sig) then read it in first and append
  141          * the random sig part onto the end.
  142          */
  143         if ((sigfp = open_random_sig(path)) != NULL) {
  144 #ifdef DEBUG
  145             if (debug & DEBUG_MISC)
  146                 error_message(2, "USING random sig=[%s]", sigfile);
  147 #endif /* DEBUG */
  148             fprintf(fp, "\n%s", thisgroup->attribute->sigdashes ? SIGDASHES : "\n");
  149             joinpath(pathfixed, sizeof(pathfixed), path, ".sigfixed");
  150 #ifdef DEBUG
  151             if (debug & DEBUG_MISC)
  152                 error_message(2, "TRYING fixed sig=[%s]", pathfixed);
  153 #endif /* DEBUG */
  154             if ((fixfp = fopen(pathfixed, "r")) != NULL) {
  155                 copy_fp(fixfp, fp);
  156                 fclose(fixfp);
  157             } else {
  158                 joinpath(pathfixed, sizeof(pathfixed), homedir, ".sigfixed");
  159 #ifdef DEBUG
  160                 if (debug & DEBUG_MISC)
  161                     error_message(2, "TRYING fixed sig=[%s]", pathfixed);
  162 #endif /* DEBUG */
  163                 if ((fixfp = fopen(pathfixed, "r")) != NULL) {
  164                     copy_fp(fixfp, fp);
  165                     fclose(fixfp);
  166                 }
  167             }
  168             copy_fp(sigfp, fp);
  169             fclose(sigfp);
  170             chdir(cwd);
  171             return;
  172         }
  173 
  174         if ((sigfp = fopen(path, "r")) != NULL) {
  175             fprintf(fp, "\n%s", thisgroup->attribute->sigdashes ? SIGDASHES : "\n");
  176             copy_fp(sigfp, fp);
  177             fclose(sigfp);
  178             return;
  179         }
  180 
  181         /*
  182          * Use ~/.signature as a last resort, but only if mailing or
  183          * using internal inews (external inews appends it automagically).
  184          */
  185         if ((sigfp = fopen(default_signature, "r")) != NULL) {
  186             if (include_dot_signature) {
  187                 fprintf(fp, "\n%s", thisgroup->attribute->sigdashes ? SIGDASHES : "\n");
  188                 copy_fp(sigfp, fp);
  189             }
  190             fclose(sigfp);
  191         }
  192     }
  193 }
  194 
  195 
  196 static FILE *
  197 open_random_sig(
  198     char *sigdir)
  199 {
  200     srand((unsigned int) time(NULL));
  201 
  202     if (chdir(sigdir) == 0) {
  203         if (thrashdir(sigdir) || !*sigfile) {
  204 #ifdef DEBUG
  205             if (debug & DEBUG_MISC)
  206                 error_message(2, "NO sigfile=[%s]", sigfile);
  207 #endif /* DEBUG */
  208             return (FILE *) 0;
  209         } else {
  210 #ifdef DEBUG
  211             if (debug & DEBUG_MISC)
  212                 error_message(2, "sigfile=[%s]", sigfile);
  213 #endif /* DEBUG */
  214             return fopen(sigfile, "r");
  215         }
  216     }
  217 
  218     return (FILE *) 0;
  219 }
  220 
  221 
  222 static int
  223 thrashdir(
  224     char *sigdir)
  225 {
  226     DIR *dirp;
  227     DIR_BUF *dp;
  228     char *cwd;
  229     int safeguard, recurse;
  230     int c = 0, numentries = 0, pick;
  231     struct stat st;
  232 
  233     sigfile[0] = '\0';
  234 
  235     if ((dirp = opendir(CURRENTDIR)) == NULL)
  236         return 1;
  237 
  238     while (readdir(dirp) != NULL)
  239         numentries++;
  240 
  241     /*
  242      * consider "." and ".." non-entries
  243      * consider all entries starting with "." non-entries
  244      */
  245     if (numentries < 3) {
  246         CLOSEDIR(dirp);
  247         return -1;
  248     }
  249 
  250     cwd = my_malloc(PATH_LEN);
  251 
  252     get_cwd(cwd);
  253     recurse = strcmp(cwd, sigdir);
  254 
  255     /*
  256      * If we are using the root sig directory, we don't want
  257      * to recurse, or else we might use a custom sig intended
  258      * for a specific newsgroup (and not this one).
  259      */
  260     for (safeguard = 0, dp = NULL; safeguard < MAXLOOPS && dp == NULL; safeguard++) {
  261 #ifdef DEBUG
  262         if (debug & DEBUG_MISC)
  263             error_message(2, "sig loop=[%d] recurse=[%d]", safeguard, recurse);
  264 #endif /* DEBUG */
  265 #ifdef HAVE_REWINDDIR
  266         rewinddir(dirp);
  267 #else
  268         CLOSEDIR(dirp);
  269         if ((dirp = opendir(CURRENTDIR)) == NULL) {
  270             free(cwd);
  271             return 1;
  272         }
  273 #endif /* HAVE_REWINDDIR */
  274         pick = rand() % numentries + 1;
  275         while (--pick >= 0) {
  276             if ((dp = readdir(dirp)) == NULL)
  277                 break;
  278         }
  279         if (dp != NULL) {   /* if we could open the dir entry */
  280             if (!strcmp(dp->d_name, CURRENTDIR) || (dp->d_name[0] == '.'))
  281                 dp = NULL;
  282             else {  /* if we have a non-dot entry */
  283                 if (stat(dp->d_name, &st) == -1) {
  284                     CLOSEDIR(dirp);
  285                     free(cwd);
  286                     return 1;
  287                 }
  288                 if (S_ISDIR(st.st_mode)) {
  289                     if (recurse) {
  290                         /*
  291                          * do subdirectories
  292                          */
  293                         if ((chdir(dp->d_name) < 0) || ((c = thrashdir(sigdir)) == 1)) {
  294                             CLOSEDIR(dirp);
  295                             free(cwd);
  296                             return 1;
  297                         }
  298                         if (c == -1) {
  299                             /*
  300                              * the one we picked was an
  301                              * empty dir so try again.
  302                              */
  303                             dp = NULL;
  304                             chdir(cwd);
  305                         }
  306                     } else
  307                         dp = NULL;
  308                 } else {    /* end dir; we have a file */
  309                     get_cwd(sigfile);
  310                     strcat(sigfile, "/");
  311                     strcat(sigfile, dp->d_name);
  312 #ifdef DEBUG
  313                     if (debug & DEBUG_MISC)
  314                         error_message(2, "Found a file=[%s]", sigfile);
  315 #endif /* DEBUG */
  316                 }
  317             }
  318         }
  319     }
  320     free(cwd);
  321 #ifdef DEBUG
  322     if (debug & DEBUG_MISC)
  323         error_message(2, "return 0: sigfile=[%s]", sigfile);
  324 #endif /* DEBUG */
  325     CLOSEDIR(dirp);
  326 
  327     return 0;
  328 }