1 #include <config.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <ctype.h>
5
6 #ifdef HAVE_UNISTD_H
7 #include <unistd.h>
8 #endif
9
10 #ifdef HAVE_DIRENT_H
11 # include <dirent.h>
12 #else
13 # define dirent direct
14 # ifdef HAVE_SYS_NDIR_H
15 # include <sys/ndir.h>
16 # endif
17 # ifdef HAVE_SYS_DIR_H
18 # include <sys/dir.h>
19 # endif
20 #endif
21
22 #ifdef HAVE_LIMITS_H
23 #include <limits.h>
24 #endif
25
26 #include <string.h>
27 #include <sys/types.h>
28 #include <sys/stat.h>
29 #include <errno.h>
30 #include <signal.h>
31 #include <sys/syslimits.h>
32
33 #ifdef DMALLOC
34 #include <dmalloc.h>
35 #endif
36
37 #include "suck_config.h"
38 #include "both.h"
39 #include "phrases.h"
40 /*----------------------------------------------------*/
41 typedef struct {
42 char *group;
43 unsigned int lownr;
44 unsigned int highnr;
45 char active;
46 } Group, *PGroup;
47
48 /* Master Structure */
49 typedef struct {
50 FILE *msgs;
51 int nrgroups;
52 int debug;
53 int abort_exist; /* do we abort if article nr already exists */
54 int link_type;
55 PGroup groups;
56 char active_file[PATH_MAX+1];
57 const char *config_file;
58 char basedir[PATH_MAX+1];
59 const char *msgdir;
60 const char *phrases;
61 } Master, *PMaster;
62
63 enum { RETVAL_ERROR = -1, RETVAL_OK = 0 };
64 enum { LOCKFILE_LOCK, LOCKFILE_UNLOCK };
65 enum { LINK_SYM, LINK_HARD, LINK_NONE };
66
67 #define NEWSGROUP "Newsgroups: "
68 #define NEWSGROUP_LEN 12
69 #define GROUP_SEP ','
70 #define CONFIG_BASE "BASE="
71 #define CONFIG_ACTIVE "ACTIVE="
72 #define CONFIG_BASE_LEN 5
73 #define CONFIG_ACTIVE_LEN 7
74
75 /* for phrases stuff */
76 char **both_phrases = default_both_phrases;
77 char **lmove_phrases = default_lmove_phrases;
78 /*-------------------------------------------------------*/
79 /* function prototypes */
80 void scan_args(PMaster, int, char *[]);
81 void load_phrases(PMaster);
82 void free_phrases(void);
83 int load_active(PMaster);
84 int load_config(PMaster);
85 void free_active(PMaster);
86 int check_dirs(PMaster);
87 char *make_dirname(char *, char *);
88 int move_msgs(PMaster);
89 char *find_groups(PMaster, char *);
90 PGroup match_group(PMaster, char **);
91 int rewrite_active(PMaster);
92 int do_lockfile(PMaster, int);
93 /*--------------------------------------------------------------------------------*/
main(int argc,char * argv[])94 int main(int argc, char *argv[]) {
95
96 int retval = RETVAL_OK;
97 const char *ptr;
98 Master master;
99
100 /* set up defaults */
101 master.msgs = stdout;
102 master.nrgroups = 0;
103 master.debug = 0;
104 master.groups = NULL;
105 strcpy(master.active_file,N_LMOVE_ACTIVE);
106 master.config_file=N_LMOVE_CONFIG;
107 master.phrases = NULL;
108 master.basedir[0] = '\0';
109 master.msgdir = NULL;
110 master.abort_exist = TRUE;
111 master.link_type = LINK_NONE;
112
113 scan_args(&master, argc, argv);
114 load_phrases(&master); /* this has to be here so rest prints okay */
115
116 /* have to load this first so get basedir */
117 retval = load_config(&master);
118
119 if(master.debug == TRUE) {
120 do_debug("master.active_file = %s\n", (master.active_file == NULL) ? "NULL" : master.active_file);
121 do_debug("master.config_file = %s\n", (master.config_file == NULL) ? "NULL" : master.config_file);
122 do_debug("master.basedir = %s\n", master.basedir);
123 do_debug("master.msgdir = %s\n", (master.msgdir == NULL) ? "NULL" : master.msgdir);
124 do_debug("master.phrases = %s\n", (master.phrases == NULL) ? "NULL" :master.phrases);
125 ptr = "WHOOPS Wierd value for link_type";
126 switch (master.link_type) {
127 case LINK_SYM:
128 ptr = "SYMBOLIC";
129 break;
130 case LINK_HARD:
131 ptr = "HARD";
132 break;
133 case LINK_NONE:
134 ptr = "NO LINKS";
135 break;
136 }
137 do_debug("master.link_type = %s\n", ptr);
138
139 }
140 if(master.basedir == NULL || master.basedir[0] == '\0') {
141 error_log(ERRLOG_REPORT, lmove_phrases[5], NULL);
142 retval = RETVAL_ERROR;
143 }
144 if(master.msgdir == NULL || master.msgdir[0] == '\0') {
145 error_log(ERRLOG_REPORT, lmove_phrases[7], NULL);
146 retval = RETVAL_ERROR;
147 }
148
149 if(retval == RETVAL_OK) {
150
151 #ifdef LOCKFILE
152 if(do_lockfile(&master, LOCKFILE_LOCK) != RETVAL_OK) {
153 retval = RETVAL_ERROR;
154 }
155 else {
156 #endif
157 if((retval = load_active(&master)) == RETVAL_OK) {
158 /* check to make sure all our directories are there */
159 if((retval = check_dirs(&master)) == RETVAL_OK) {
160 retval = move_msgs(&master);
161 if(retval == RETVAL_OK) {
162 retval = rewrite_active(&master);
163 }
164 }
165 }
166 free_active(&master);
167 #ifdef LOCKFILE
168 do_lockfile(&master, LOCKFILE_UNLOCK);
169 }
170 #endif
171 }
172 free_phrases();
173 exit(retval);
174 }
175 /*-----------------------------------------------------------------------------------*/
rewrite_active(PMaster master)176 int rewrite_active(PMaster master) {
177 /* move old active to active.old and write active */
178 FILE *fpo;
179 char fname[PATH_MAX+1];
180 int i, retval = RETVAL_OK;
181
182 sprintf(fname, "%s.old", master->active_file);
183 if(rename(master->active_file, fname) != 0) {
184 MyPerror(fname);
185 retval = RETVAL_ERROR;
186 }
187 else if((fpo = fopen(master->active_file, "w")) == NULL) {
188 MyPerror(master->active_file);
189 retval = RETVAL_ERROR;
190 }
191 else {
192 for(i = 0; i < master->nrgroups && retval == RETVAL_OK ; i++) {
193 if(fprintf(fpo, "%s %u %u %c\n", master->groups[i].group, master->groups[i].highnr, master->groups[i].lownr, master->groups[i].active) <= 0) {
194 error_log(ERRLOG_REPORT, lmove_phrases[13], master->active_file, NULL);
195 retval = RETVAL_ERROR;
196 }
197 }
198 fclose(fpo);
199 if(chmod(master->active_file, LMOVE_ACTIVE_MODE) != 0) {
200 MyPerror(master->active_file);
201 }
202 }
203 return retval;
204 }
205 /*-----------------------------------------------------------------------------------*/
move_msgs(PMaster master)206 int move_msgs(PMaster master) {
207 /* go thru msg dir, and move the messages, based on "Newsgroups: subj line" */
208 /* into newsgroup directory */
209 struct dirent *entry;
210 DIR *dptr;
211 struct stat statbuf;
212 char *ptr;
213 PGroup group;
214 char o_fname[PATH_MAX+1], n_fname[PATH_MAX+1];
215 struct stat sbuf;
216 int quit = FALSE, retval = RETVAL_OK, count;
217 int (*linkit)(const char *, const char *);
218
219 /* which type of link will we create, symbolic or hard? Point to the right function */
220 /* this won't get used if link_type is NONE, so we don't handle that case */
221 #ifdef EMX /* OS-2 doesn't have link or symlink */
222 linkit = NULL;
223 master->link_type = LINK_NONE;
224 #else
225 linkit = (master->link_type == LINK_SYM) ? symlink : link;
226 #endif
227
228 if((dptr = opendir(master->msgdir)) == NULL) {
229 MyPerror(master->msgdir);
230 retval = RETVAL_ERROR;
231 }
232 else {
233 while(((entry = readdir(dptr)) != NULL) && quit == FALSE) {
234 sprintf(o_fname, "%s/%s", master->msgdir, entry->d_name); /* build full path */
235 if(stat(o_fname, &statbuf) == 0 && S_ISREG(statbuf.st_mode)) {
236 if((ptr = find_groups(master, o_fname)) == NULL) {
237 error_log(ERRLOG_REPORT, lmove_phrases[11], entry->d_name, NULL);
238 }
239 else {
240 count = 0; /* how many groups have we matched */
241 ptr += NEWSGROUP_LEN; /* skip header */
242 /* we pass a pointer to a pointer so that the subroutine can modify it */
243 /* and return where we left off, so we can do multiple groups on one line */
244 while(ptr != NULL && *ptr != '\0' && (group = match_group(master, &ptr)) != NULL) {
245 count++;
246 sprintf(n_fname, "%s/%d", make_dirname(master->basedir, group->group), group->highnr);
247 if(stat(n_fname, &sbuf) == 0) {
248 /* file exists */
249 if(master->abort_exist == TRUE) {
250 error_log(ERRLOG_REPORT, lmove_phrases[21], group->group, str_int(group->highnr), NULL);
251 quit = TRUE;
252 }
253 else {
254 while(stat(n_fname, &sbuf) == 0) {
255 /* up it and try again */
256 group->highnr++;
257 sprintf(n_fname, "%s/%d", make_dirname(master->basedir, group->group), group->highnr);
258 }
259 }
260 }
261 if(quit != TRUE) {
262 if(count == 1) {
263 /* first group gets the file */
264 if(rename(o_fname, n_fname) != 0) {
265 error_log(ERRLOG_REPORT, lmove_phrases[13], o_fname, n_fname, NULL);
266 MyPerror("");
267 }
268 else {
269 if(master->debug == TRUE) {
270 do_debug("Moved %s to %s\n", o_fname, n_fname, NULL);
271 }
272
273 group->highnr++;
274 strcpy(o_fname, n_fname); /* so we can link to this file */
275 }
276 }
277 else if (master->link_type == LINK_NONE) {
278 /* this will break the loop */
279 ptr = NULL;
280 }
281 else {
282 /* remainder of groups get links to first file */
283 /* call the function reffed earlier */
284 if(master->debug == TRUE) {
285 do_debug("linking %s to %s\n", n_fname, o_fname, NULL);
286 }
287
288 if((*linkit)(o_fname, n_fname) != 0) {
289 MyPerror(n_fname);
290 }
291 else {
292 group->highnr++;
293 }
294 }
295 }
296 }
297 if(count == 0) {
298 error_log(ERRLOG_REPORT, lmove_phrases[12], entry->d_name, NULL);
299 }
300 }
301 }
302 }
303 closedir(dptr);
304 }
305
306 return retval;
307 }
308 /*-----------------------------------------------------------------------------------*/
match_group(PMaster master,char ** newsgroups)309 PGroup match_group(PMaster master, char **newsgroups) {
310 PGroup retval = NULL;
311 int i;
312 char *ptr, *eptr, save;
313 /* this gets a null-terminated line of newsgroups */
314
315 ptr = eptr = *newsgroups; /* this is a pointer to a pointer, so can do multiple groups per line */
316
317 /* in case the newsgroup line is formatted badly, and has extra spaces in the front */
318 while (isspace(*ptr)) {
319 ptr++;
320 eptr++;
321 }
322 do {
323 /* first find end of this group or NULL */
324 /* the isspace handles the case where they use spaces either between */
325 /* groups, or at the end of the line. */
326 while(*eptr != GROUP_SEP && *eptr != '\0' && !isspace(*eptr) && *eptr) {
327 eptr++;
328 }
329 save = *eptr;
330 *eptr = '\0'; /* so can use ptr as group name */
331
332 for(i = 0 ; retval == NULL && i < master->nrgroups;i++) {
333 if(strcmp(master->groups[i].group, ptr) == 0) {
334 /* bingo */
335 if(master->debug == TRUE) {
336 do_debug("Matched group %s\n", ptr);
337 }
338 retval = &(master->groups[i]);
339 }
340 }
341 ptr = ++eptr; /* set up for next group */
342 } while( save != '\0' && retval == NULL);
343 /* the eptr -1 is because the ++eptr above puts us 1 beyond the EOL */
344 if(retval == NULL) {
345 /* if no matches , return EOL */
346 *newsgroups = eptr -1;
347 }
348 else {
349 /* if at end of line, return that, else return start of next group */
350 *newsgroups = (save == '\0') ? eptr-1 : eptr;
351 }
352 return retval;
353 }
354 /*-----------------------------------------------------------------------------------*/
find_groups(PMaster master,char * fname)355 char *find_groups(PMaster master, char *fname) {
356 FILE *fpi;
357 char *retval;
358 static char linein[LMOVE_MAXLINLEN+1];
359 int i;
360
361 retval = NULL;
362 if((fpi = fopen(fname, "r")) == NULL) {
363 MyPerror(fname);
364 }
365 else {
366 while(retval == NULL && fgets(linein, LMOVE_MAXLINLEN, fpi) != NULL) {
367 if(strncmp(linein, NEWSGROUP, NEWSGROUP_LEN) == 0) {
368 retval = linein;
369 /* now strip off NL off of EOL */
370 i = strlen(linein) - 1;
371 if(linein[i] == '\n') {
372 linein[i] = '\0';
373 }
374 if(master->debug == TRUE) {
375 do_debug("Found newsgroup line--%s--\n",linein, NULL);
376 }
377 }
378 }
379 fclose(fpi);
380 }
381 return retval;
382 }
383 /*-----------------------------------------------------------------------------------*/
load_config(PMaster master)384 int load_config(PMaster master) {
385 int i, retval = RETVAL_OK;
386 FILE *fpi;
387 char linein[MAXLINLEN+1];
388
389 if((fpi = fopen(master->config_file, "r")) == NULL) {
390 MyPerror(master->config_file);
391 retval = RETVAL_ERROR;
392 }
393 else {
394 while( fgets(linein, MAXLINLEN, fpi) != NULL) {
395 /* strip the nl */
396 i = strlen(linein);
397 if(linein[i-1] == '\n') {
398 linein[i-1] = '\0';
399 }
400
401 if(strncmp(linein, CONFIG_BASE, CONFIG_BASE_LEN) == 0) {
402 strcpy(master->basedir, &linein[CONFIG_BASE_LEN]);
403 }
404 else if(strncmp(linein, CONFIG_ACTIVE, CONFIG_ACTIVE_LEN) == 0) {
405 strcpy(master->active_file, &linein[CONFIG_ACTIVE_LEN]);
406 }
407 else {
408 error_log(ERRLOG_REPORT, lmove_phrases[20], NULL);
409 }
410 }
411
412 fclose(fpi);
413 }
414 return retval;
415 }
416 /*-----------------------------------------------------------------------------------*/
load_active(PMaster master)417 int load_active(PMaster master) {
418 int i, j, retval = RETVAL_OK;
419 unsigned int lownr, highnr;
420 FILE *fpi;
421 char linein[MAXLINLEN+1], group[MAXLINLEN+1], active_char;
422
423 /* each line in active is in the form group name high_msg_nr low_msg_nr active_char */
424
425 if((fpi = fopen(master->active_file, "r")) == NULL) {
426 MyPerror(master->active_file);
427 retval = RETVAL_ERROR;
428 }
429 else {
430 /* pass one, count the number of valid entries */
431 /* and get the BASE dir and MSG dir entries */
432 while((i = fscanf(fpi, "%s %u %u %c", linein,&highnr,&lownr,&active_char)) != EOF) {
433 if(i == 4) {
434 master->nrgroups++;
435 }
436 else {
437 error_log(ERRLOG_REPORT, lmove_phrases[9], linein, NULL);
438 }
439 }
440 if(master->debug == TRUE) {
441 do_debug("Nr of groups in active = %d\n", master->nrgroups);
442 }
443 fseek(fpi, 0L, SEEK_SET); /* rewind for pass two */
444 /* pass two, put them into the master->groups array */
445 if((master->groups = calloc(master->nrgroups, sizeof(Group))) == NULL) {
446 error_log(ERRLOG_REPORT, lmove_phrases[8], NULL);
447 retval = RETVAL_ERROR;
448 }
449 else {
450 i = 0;
451 while(retval == RETVAL_OK && fgets(linein, MAXLINLEN, fpi) != NULL) {
452 if(sscanf(linein, "%s %u %u %c", group, &highnr, &lownr, &active_char) == 4) {
453 if(highnr == 0) {
454 highnr = 1;
455 } /* so we start at 1 */
456 master->groups[i].lownr = lownr;
457 master->groups[i].highnr = highnr;
458 master->groups[i].active = active_char;
459 /* now check for dupe groups */
460 for(j = 0 ; j < i; j++) {
461 if(strcmp(master->groups[j].group, group) == 0) {
462 error_log(ERRLOG_REPORT, lmove_phrases[22], group, NULL);
463 retval = RETVAL_ERROR;
464 break; /* so we don't check any further */
465 }
466 }
467 if((retval == RETVAL_OK) && ((master->groups[i].group = malloc(strlen(group)+1)) == NULL)) {
468 error_log(ERRLOG_REPORT, lmove_phrases[8], NULL);
469 retval = RETVAL_ERROR;
470 }
471 else {
472 if(master->debug == TRUE) {
473 do_debug("Group %d = %s\n", i, group);
474 }
475 strcpy(master->groups[i].group, group);
476 i++;
477 }
478 }
479 }
480 }
481 fclose(fpi);
482 }
483 return retval;
484 }
485 /*------------------------------------------------------------------------------------*/
free_active(PMaster master)486 void free_active(PMaster master) {
487 int i;
488 for(i=0;i<master->nrgroups;i++) {
489 if(master->groups[i].group != NULL) {
490 free(master->groups[i].group);
491 }
492 }
493 free(master->groups);
494 master->groups = NULL;
495 }
496 /*------------------------------------------------------------------------------------*/
check_dirs(PMaster master)497 int check_dirs(PMaster master) {
498 /* check to make sure the base, msg, and all group dirs are available */
499
500 struct stat statbuf;
501 int i, y, retval = RETVAL_OK;
502 char *ptr, path[PATH_MAX+1];
503
504 if(stat(master->basedir, &statbuf) != 0 || ! S_ISDIR(statbuf.st_mode)) {
505 error_log(ERRLOG_REPORT, lmove_phrases[10], master->basedir);
506 retval = RETVAL_ERROR;
507 }
508 else if(stat(master->msgdir, &statbuf) != 0 || ! S_ISDIR(statbuf.st_mode)) {
509 error_log(ERRLOG_REPORT, lmove_phrases[10], master->msgdir, NULL);
510 retval = RETVAL_ERROR;
511 }
512 else {
513 for(i = 0 ; i < master->nrgroups && retval == RETVAL_OK ; i++) {
514 ptr = make_dirname(master->basedir, master->groups[i].group);
515 if(master->debug == TRUE) {
516 do_debug("Checking dir %s\n", ptr);
517 }
518 if(stat(ptr, &statbuf) != 0 && errno == ENOENT) {
519 /* it don't exist. try to make it*/
520 /* lets work our way down and try to make all dirs */
521 sprintf(path, "%s/", master->basedir);
522 y = strlen(path); /* start at end of string */
523 ptr = master->groups[i].group;
524 while(retval == RETVAL_OK && *ptr != '\0') {
525 /* copy til next dit or end */
526 while(*ptr != '.' && *ptr != '\0') {
527 path[y] = *ptr;
528 y++;
529 ptr++;
530 }
531 path[y] = '\0'; /* just to be on safe side */
532 if(master->debug == TRUE) {
533 do_debug("Trying to make dir %s : mode %o\n", path, LMOVE_DEFAULT_DIR_MODE);
534 }
535 umask(0); /* so mode defined is mode we actually get */
536 if(mkdir(path, LMOVE_DEFAULT_DIR_MODE) != 0 && errno != EEXIST) {
537 MyPerror(path);
538 retval = RETVAL_ERROR;
539 }
540 if(*ptr != '\0') {
541 /* move on to next */
542 path[y++] = '/';
543 ptr++;
544 }
545 }
546 }
547 /* one final check */
548 if(retval == RETVAL_OK) {
549 /* have to redo stat, since we might have made dirs above */
550 ptr = make_dirname(master->basedir, master->groups[i].group);
551 if(stat(ptr, &statbuf) != 0 || !S_ISDIR(statbuf.st_mode)) {
552 error_log(ERRLOG_REPORT, lmove_phrases[10], ptr, NULL);
553 retval = RETVAL_ERROR;
554 }
555 }
556 }
557 }
558
559 return retval;
560 }
561 /*------------------------------------------------------------------------------------*/
scan_args(PMaster master,int argc,char * argv[])562 void scan_args(PMaster master, int argc, char *argv[]) {
563
564 int loop;
565
566 for(loop = 1; loop < argc; loop++) {
567 if(argv[loop][0] != '-' || argv[loop][2] != '\0') {
568 error_log(ERRLOG_REPORT, lmove_phrases[0], argv[loop], NULL);
569 }
570 else {
571 switch(argv[loop][1]) {
572 case 'a': /* active file */
573 if(loop+1 == argc) {
574 error_log(ERRLOG_REPORT, lmove_phrases[6], NULL);
575 }
576 else {
577 strcpy(master->active_file,argv[++loop]);
578 }
579 break;
580 case 'A': /* don't abort if article nr already exists on disk */
581 master->abort_exist = FALSE;
582 break;
583 case 'c': /* config file */
584 if(loop+1 == argc) {
585 error_log(ERRLOG_REPORT, lmove_phrases[19], NULL);
586 }
587 else {
588 master->config_file =argv[++loop];
589 }
590 break;
591 case 'd': /* article directory */
592 if(loop+1 == argc) {
593 error_log(ERRLOG_REPORT, lmove_phrases[7], NULL);
594 }
595 else {
596 master->msgdir = argv[++loop];
597 }
598 break;
599 case 'D': /* debug */
600 master->debug = TRUE;
601 break;
602 case 'e': /* use default error log path */
603 error_log(ERRLOG_SET_FILE, ERROR_LOG,NULL);
604 break;
605 case 'E': /* error log path */
606 if(loop+1 == argc) {
607 error_log(ERRLOG_REPORT, "%s\n",lmove_phrases[1],NULL);
608 }
609 else {
610 error_log(ERRLOG_SET_FILE, argv[++loop], NULL);
611 }
612 break;
613 case 'h': /* use hard vice symbolic links */
614 master->link_type = LINK_HARD;
615 break;
616 case 'l': /* language phrase file */
617 if(loop+1 == argc) {
618 error_log(ERRLOG_REPORT, lmove_phrases[4],NULL);
619 }
620 else {
621 master->phrases = argv[++loop];
622 }
623 break;
624 case 's': /* do symbolic links */
625 master->link_type = LINK_SYM;
626 break;
627 default:
628 error_log(ERRLOG_REPORT, lmove_phrases[0], argv[loop],NULL);
629 break;
630
631 }
632 }
633 }
634 }
635 /*--------------------------------------------------------------------------------*/
make_dirname(char * base,char * group)636 char *make_dirname(char *base, char *group) {
637 static char path[PATH_MAX+1];
638 int i;
639 char *ptr;
640
641 /* take base dir & a group name, change all "." in group to "/" */
642 /* and return the full path */
643 i = strlen(base);
644 strcpy(path, base);
645
646 ptr = &path[i];
647 sprintf(path, "%s/%s", base, group);
648 while ( *ptr != '\0' ) {
649 if(*ptr == '.') {
650 *ptr = '/';
651 }
652 ptr++;
653 }
654 return path;
655 }
656 #ifdef LOCKFILE
657 /*--------------------------------------------------------------*/
do_lockfile(PMaster master,int option)658 int do_lockfile(PMaster master, int option) {
659
660 static char lockfile[PATH_MAX+1];
661 int retval;
662 FILE *f_lock;
663 pid_t pid;
664
665 retval = RETVAL_OK;
666 if(option == LOCKFILE_UNLOCK) {
667 unlink(lockfile);
668 }
669 else {
670 sprintf(lockfile, "%s/%s", master->basedir, N_LMOVE_LOCKFILE);
671 if((f_lock = fopen(lockfile, "r")) != NULL) {
672 /* okay, let's try and see if this sucker is truly alive */
673 long tmp = 0;
674 fscanf(f_lock, "%ld", &tmp);
675 fclose(f_lock);
676 pid = (pid_t)tmp;
677 if(pid <= 0) {
678 error_log(ERRLOG_REPORT, lmove_phrases[14], lockfile, NULL);
679 retval = RETVAL_ERROR;
680 }
681 /* this next technique borrowed from pppd, sys-linux.c (ppp2.2.0c) */
682 /* if the pid doesn't exist (can't send any signal to it), then try */
683 /* to remove the stale PID file so can recreate it. */
684 else if(kill(pid, 0) == -1 && errno == ESRCH) {
685 /* no pid found */
686 if(unlink(lockfile) == 0) {
687 /* this isn't error so don't put in error log */
688 print_phrases(master->msgs, lmove_phrases[15], lockfile, NULL);
689 }
690 else {
691 error_log(ERRLOG_REPORT, lmove_phrases[16], lockfile, NULL);
692 retval = RETVAL_ERROR;
693 }
694 }
695 else {
696 error_log(ERRLOG_REPORT, lmove_phrases[17], lockfile, NULL);
697 retval = RETVAL_ERROR;
698 }
699 }
700 if(retval == RETVAL_OK) {
701 if((f_lock = fopen(lockfile, "w")) != NULL) {
702 fprintf(f_lock, "%ld", (long) getpid());
703 fclose(f_lock);
704 }
705 else {
706 error_log(ERRLOG_REPORT, lmove_phrases[18], lockfile, NULL);
707 retval = RETVAL_ERROR;
708 }
709 }
710 }
711 return retval;
712 }
713 #endif
714
715 /*--------------------------------------------------------------------------------*/
716 /* THE strings in this routine is the only one not in the arrays, since */
717 /* we are in the middle of reading the arrays, and they may or may not be valid. */
718 /*--------------------------------------------------------------------------------*/
load_phrases(PMaster master)719 void load_phrases(PMaster master) {
720
721 int error=TRUE;
722 FILE *fpi;
723 char buf[MAXLINLEN];
724
725
726 if(master->phrases != NULL) {
727
728 if((fpi = fopen(master->phrases, "r")) == NULL) {
729 MyPerror(master->phrases);
730 }
731 else {
732 fgets(buf, MAXLINLEN, fpi);
733 if(strncmp( buf, SUCK_VERSION, strlen(SUCK_VERSION)) != 0) {
734 error_log(ERRLOG_REPORT, "Invalid Phrase File, wrong version\n", NULL);
735 }
736 else if((both_phrases = read_array(fpi, NR_BOTH_PHRASES, TRUE)) != NULL) {
737 read_array(fpi, NR_RPOST_PHRASES, FALSE); /* skip these */
738 read_array(fpi, NR_TEST_PHRASES, FALSE);
739 read_array(fpi, NR_SUCK_PHRASES, FALSE);
740 read_array(fpi, NR_TIMER_PHRASES, FALSE);
741 read_array(fpi, NR_CHKH_PHRASES, FALSE);
742 read_array(fpi, NR_DEDUPE_PHRASES, FALSE);
743 read_array(fpi, NR_KILLF_REASONS, FALSE);
744 read_array(fpi, NR_KILLF_PHRASES, FALSE);
745 read_array(fpi, NR_KILLP_PHRASES, FALSE);
746 if((lmove_phrases = read_array(fpi, NR_LMOVE_PHRASES, TRUE)) != NULL) {
747 error = FALSE;
748 }
749 }
750 }
751 fclose(fpi);
752 if(error == TRUE) {
753 /* reset back to default */
754 error_log(ERRLOG_REPORT, "Using default Language phrases\n",NULL);
755 lmove_phrases = default_lmove_phrases;
756 both_phrases = default_both_phrases;
757 }
758 }
759 }
760 /*--------------------------------------------------------------------------------*/
free_phrases(void)761 void free_phrases(void) {
762 /* free up the memory alloced in load_phrases() */
763 if(lmove_phrases != default_lmove_phrases) {
764 free_array(NR_LMOVE_PHRASES, lmove_phrases);
765 }
766 if(both_phrases != default_both_phrases) {
767 free_array(NR_BOTH_PHRASES, both_phrases);
768 }
769
770 }
771