"Fossies" - the Fresh Open Source Software Archive

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