"Fossies" - the Fresh Open Source Software Archive

Member "tin-2.6.2/src/sigfile.c" (9 Dec 2022, 8810 Bytes) of package /linux/misc/tin-2.6.2.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.6.1_vs_2.6.2.

    1 /*
    2  *  Project   : tin - a Usenet reader
    3  *  Module    : sigfile.c
    4  *  Author    : M. Gleason & I. Lea
    5  *  Created   : 1992-10-17
    6  *  Updated   : 2021-07-26
    7  *  Notes     : Generate random signature for posting/mailing etc.
    8  *
    9  * Copyright (c) 1992-2023 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 : "");
   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) + (size_t) 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 : "");
  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             if (chdir(cwd) == -1) {
  171 #ifdef DEBUG
  172                 int e = errno;
  173                 if (debug & DEBUG_MISC)
  174                     error_message(2, "chdir(%s): Error: %s", cwd, strerror(e));
  175 #endif /* DEBUG */
  176             }
  177             return;
  178         }
  179 
  180         if ((sigfp = fopen(path, "r")) != NULL) {
  181             fprintf(fp, "\n%s", thisgroup->attribute->sigdashes ? SIGDASHES : "");
  182             copy_fp(sigfp, fp);
  183             fclose(sigfp);
  184             return;
  185         }
  186 
  187         /*
  188          * Use ~/.signature as a last resort, but only if mailing or
  189          * using internal inews (external inews appends it automagically).
  190          */
  191         if ((sigfp = fopen(default_signature, "r")) != NULL) {
  192             if (include_dot_signature) {
  193                 fprintf(fp, "\n%s", thisgroup->attribute->sigdashes ? SIGDASHES : "");
  194                 copy_fp(sigfp, fp);
  195             }
  196             fclose(sigfp);
  197         }
  198     }
  199 }
  200 
  201 
  202 static FILE *
  203 open_random_sig(
  204     char *sigdir)
  205 {
  206     srand((unsigned int) time(NULL));
  207 
  208     if (chdir(sigdir) == 0) {
  209         if (thrashdir(sigdir) || !*sigfile) {
  210 #ifdef DEBUG
  211             if (debug & DEBUG_MISC)
  212                 error_message(2, "NO sigfile=[%s]", sigfile);
  213 #endif /* DEBUG */
  214             return (FILE *) 0;
  215         } else {
  216 #ifdef DEBUG
  217             if (debug & DEBUG_MISC)
  218                 error_message(2, "sigfile=[%s]", sigfile);
  219 #endif /* DEBUG */
  220             return fopen(sigfile, "r");
  221         }
  222     }
  223 
  224     return (FILE *) 0;
  225 }
  226 
  227 
  228 static int
  229 thrashdir(
  230     char *sigdir)
  231 {
  232     DIR *dirp;
  233     DIR_BUF *dp;
  234     char *cwd;
  235     int safeguard, recurse;
  236     int c = 0, numentries = 0, pick;
  237     struct stat st;
  238 
  239     sigfile[0] = '\0';
  240 
  241     if ((dirp = opendir(CURRENTDIR)) == NULL)
  242         return 1;
  243 
  244     while (readdir(dirp) != NULL)
  245         numentries++;
  246 
  247     /*
  248      * consider "." and ".." non-entries
  249      * consider all entries starting with "." non-entries
  250      */
  251     if (numentries < 3) {
  252         CLOSEDIR(dirp);
  253         return -1;
  254     }
  255 
  256     cwd = my_malloc(PATH_LEN);
  257 
  258     get_cwd(cwd);
  259     recurse = strcmp(cwd, sigdir);
  260 
  261     /*
  262      * If we are using the root sig directory, we don't want
  263      * to recurse, or else we might use a custom sig intended
  264      * for a specific newsgroup (and not this one).
  265      */
  266     for (safeguard = 0, dp = NULL; safeguard < MAXLOOPS && dp == NULL; safeguard++) {
  267 #ifdef DEBUG
  268         if (debug & DEBUG_MISC)
  269             error_message(2, "sig loop=[%d] recurse=[%d]", safeguard, recurse);
  270 #endif /* DEBUG */
  271 #ifdef HAVE_REWINDDIR
  272         rewinddir(dirp);
  273 #else
  274         CLOSEDIR(dirp);
  275         if ((dirp = opendir(CURRENTDIR)) == NULL) {
  276             free(cwd);
  277             return 1;
  278         }
  279 #endif /* HAVE_REWINDDIR */
  280         pick = rand() % numentries + 1;
  281         while (--pick >= 0) {
  282             if ((dp = readdir(dirp)) == NULL)
  283                 break;
  284         }
  285         if (dp != NULL) {   /* if we could open the dir entry */
  286             if (!strcmp(dp->d_name, CURRENTDIR) || (dp->d_name[0] == '.'))
  287                 dp = NULL;
  288             else {  /* if we have a non-dot entry */
  289                 if (stat(dp->d_name, &st) == -1) {
  290                     CLOSEDIR(dirp);
  291                     free(cwd);
  292                     return 1;
  293                 }
  294                 if (S_ISDIR(st.st_mode)) {
  295                     if (recurse) {
  296                         /*
  297                          * do subdirectories
  298                          */
  299                         if ((chdir(dp->d_name) < 0) || ((c = thrashdir(sigdir)) == 1)) {
  300                             CLOSEDIR(dirp);
  301                             free(cwd);
  302                             return 1;
  303                         }
  304                         if (c == -1) {
  305                             /*
  306                              * the one we picked was an
  307                              * empty dir so try again.
  308                              */
  309                             dp = NULL;
  310                             if (chdir(cwd) == -1) {
  311 #ifdef DEBUG
  312                                 int e = errno;
  313                                 if (debug & DEBUG_MISC)
  314                                     error_message(2, "chdir(%s): Error: %s", cwd, strerror(e));
  315 #endif /* DEBUG */
  316                             }
  317                         }
  318                     } else
  319                         dp = NULL;
  320                 } else {    /* end dir; we have a file */
  321                     get_cwd(sigfile);
  322                     strcat(sigfile, "/");
  323                     strcat(sigfile, dp->d_name);
  324 #ifdef DEBUG
  325                     if (debug & DEBUG_MISC)
  326                         error_message(2, "Found a file=[%s]", sigfile);
  327 #endif /* DEBUG */
  328                 }
  329             }
  330         }
  331     }
  332     free(cwd);
  333 #ifdef DEBUG
  334     if (debug & DEBUG_MISC)
  335         error_message(2, "return 0: sigfile=[%s]", sigfile);
  336 #endif /* DEBUG */
  337     CLOSEDIR(dirp);
  338 
  339     return 0;
  340 }