tin  2.6.1
About: TIN is a threaded NNTP and spool based UseNet newsreader.
  Fossies Dox: tin-2.6.1.tar.xz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

sigfile.c
Go to the documentation of this file.
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-2022 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
49static char sigfile[PATH_LEN];
50
51static FILE *open_random_sig(char *sigdir);
52static int thrashdir(char *sigdir);
53
54
55void
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
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
202static FILE *
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
228static int
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 */
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}
unsigned t_bool
Definition: bool.h:77
#define TRUE
Definition: bool.h:74
#define FALSE
Definition: bool.h:70
#define DEBUG_MISC
Definition: debug.h:54
char homedir[PATH_LEN]
Definition: init.c:78
char default_signature[PATH_LEN]
Definition: init.c:74
struct t_config tinrc
Definition: init.c:192
unsigned short debug
Definition: debug.c:51
t_bool read_news_via_nntp
Definition: init.c:151
static FILE * pipe_fp
Definition: feed.c:55
int errno
void error_message(unsigned int sdelay, const char *fmt,...)
Definition: screen.c:224
char * strstr(const char *text, const char *pattern)
Definition: string.c:334
t_bool copy_fp(FILE *fp_ip, FILE *fp_op)
Definition: misc.c:179
void joinpath(char *result, size_t result_size, const char *dir, const char *file)
Definition: joinpath.c:50
void get_cwd(char *buf)
Definition: misc.c:2046
int strfpath(const char *format, char *str, size_t maxsize, struct t_group *group, t_bool expand_all)
Definition: misc.c:1699
int strcasecmp(const char *p, const char *q)
Definition: string.c:475
#define strerror(n)
Definition: proto.h:700
static char sigfile[255]
Definition: sigfile.c:49
static FILE * open_random_sig(char *sigdir)
Definition: sigfile.c:203
#define MAXLOOPS
Definition: sigfile.c:45
static int thrashdir(char *sigdir)
Definition: sigfile.c:229
#define CURRENTDIR
Definition: sigfile.c:47
void msg_write_signature(FILE *fp, t_bool include_dot_signature, struct t_group *thisgroup)
Definition: sigfile.c:56
char * sigfile
Definition: tin.h:1616
unsigned sigdashes
Definition: tin.h:1675
char inews_prog[PATH_LEN]
Definition: tinrc.h:262
char sigfile[PATH_LEN]
Definition: tinrc.h:133
Definition: tin.h:1816
t_bool bogus
Definition: tin.h:1831
struct t_attribute * attribute
Definition: tin.h:1834
char * name
Definition: tin.h:1817
#define my_malloc(size)
Definition: tin.h:2245
#define S_ISDIR(m)
Definition: tin.h:2176
#define PATH_LEN
Definition: tin.h:843
#define INTERNAL_CMD
Definition: tin.h:574
#define SIGDASHES
Definition: tin.h:749
#define DIR_BUF
Definition: tin.h:383
#define CLOSEDIR(DIR)
Definition: tin.h:2398