home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 35 Internet / 35-Internet.zip / trn_12.zip / src / acttimes.c next >
C/C++ Source or Header  |  1993-11-08  |  15KB  |  513 lines

  1. /* $Header: acttimes.c,v 1.1 91/11/02 18:38:29 davison Exp $
  2. **
  3. ** $Log:    acttimes.c,v $
  4. */
  5.  
  6. /* This program will maintain the file active.times if your news software
  7. ** doesn't already do this for you.  The file contains a list of newsgroup
  8. ** names followed by the time of creation (in seconds since 1970) and the
  9. ** address of the creator.  Since we can't tell who actually created the
  10. ** group, they will all indicate acttimes@DOMAIN.
  11. **
  12. ** Place this file in your NNTP support directory and change your
  13. ** common/conf.h to undef NGDATE_FILE and STAT_FILE, and define
  14. ** ACTIVE_TIMES_FILE.  To make, you can replace every mention of
  15. ** "mkgrdates" in the support/Makefile with "acttimes" and then
  16. ** type "make".  
  17. **
  18. ** To use this without having NNTP around, undefine the NNTP_SUPPORT
  19. ** define, edit the other defines that follow to indicate your setup,
  20. ** and compile it with something like "cc -O -o acttimes acttimes.c".
  21. **
  22. ** Use either "acttimes -d" to start a daemon process that wakes up every
  23. ** 10 minutes (by default) to check if the active file is a different
  24. ** size, or put "acttimes" into your cron file to be run periodically.
  25. */
  26.  
  27. /*** OS2: no NNTP ***/
  28. #undef NNTP_SUPPORT        /* comment out if not using NNTP */
  29. /*** OS2: there are links used in the source, but the
  30.           OS/2-file-systems don't have them. We try to
  31.           avoid them via the DosCopy-systemcall ***/
  32. #include <os2.h>
  33.  
  34. /*** OS2: chdir does not change the workingdrive if required,
  35.           but the news gcc-call _chdir2 does this. ***/
  36. #ifndef _CHDIR2_DEF
  37. #define _CHDIR2_DEF
  38. #define chdir _chdir2
  39. #define getcwd _getcwd2
  40. #endif
  41.  
  42. #include <stdio.h>
  43. #include <sys/types.h>
  44. #include <sys/stat.h>
  45. #include <signal.h>
  46. #include <errno.h>
  47.  
  48. /*** OS2: for the check of the uupc-rc-files, we need
  49.           the os2patch-files ***/
  50. #include "os2patch.h"
  51.  
  52. #ifdef NNTP_SUPPORT
  53. #include "../common/conf.h"
  54. #endif
  55. #ifdef USG
  56. #include <time.h>
  57. #else
  58. #include <sys/time.h>
  59. #endif
  60.  
  61. /* ---------- Start of configuration defines ---------- */
  62.  
  63. /*** OS2: yes, we have TERMIO ***/
  64. /*#ifndef USG*/
  65. #define TERMIO            /* Is this is termio system? */
  66. /*#endif*/
  67.  
  68. /* NNTP sites have the following already defined in ../common/conf.h */
  69.  
  70. #ifndef DOMAIN            /* our domain name */
  71. #define DOMAIN    "local"
  72. #endif
  73.  
  74. #ifndef ACTIVE_FILE        /* the active file for your news system */
  75. /** OS2: patch **/
  76. #define ACTIVE_FILE uupc_rc_settings.active
  77. #endif
  78.  
  79. #ifndef ACTIVE_OPT_FILE        /* the active file for your news system */
  80. /** OS2: patch **/
  81. #define ACTIVE_OPT_FILE uupc_rc_settings.active_opt
  82. #endif
  83.  
  84. #ifndef ACTIVE_TIMES_FILE    /* the name of the file to update */
  85. /** OS2: patch **/
  86. #define ACTIVE_TIMES_FILE uupc_rc_settings.active_times
  87. #endif
  88.  
  89. #ifndef SIGRET            /* set this to "int" if you have problems */
  90. #define SIGRET void
  91. #endif
  92.  
  93. #ifndef MAXPATHLEN        /* you'll probably want to leave this alone */
  94. #define    MAXPATHLEN    1024
  95. #endif
  96.  
  97. /*#define index   strchr    /* uncomment these if you need them */
  98. /*#define rindex  strrchr    /* (i.e. if index is undefined) */
  99.  
  100. /* ---------- End of configuration defines ---------- */
  101.  
  102. #ifdef TERMIO
  103. #include <termio.h>
  104. #else
  105. #include <sgtty.h>
  106. #endif
  107.  
  108. #define TIMER_FIRST 1
  109. #define TIMER_DEFAULT (10 * 60)
  110.  
  111. #define strnEQ(x,y,n) (!strncmp((x),(y),(n)))
  112.  
  113. extern errno;
  114.  
  115. char *index(), *rindex(), *malloc();
  116. SIGRET alarm_handler(), quit_handler();
  117. void active_times(), free_lines(), wrap_it_up();
  118.  
  119. typedef struct _active_line {
  120.     struct _active_line *link;
  121.     char *name;
  122.     char type;
  123. } ACTIVE_LINE;
  124.  
  125. ACTIVE_LINE *line_root = NULL, *last_line = NULL, *pline = NULL;
  126. long last_actsize;
  127. int daemon_delay = 0, kill_daemon = 0, old_groups = 0;
  128.  
  129. FILE *fp_lock;
  130.  
  131. struct stat filestat;
  132.  
  133. char buf[MAXPATHLEN];
  134. char lockfile[MAXPATHLEN];
  135.  
  136. main(argc, argv)
  137. int argc;
  138. char *argv[];
  139. {
  140.     int fd;
  141.     long pid;
  142.     char *cp;
  143.  
  144. /*** OS2: Now we load the settings out of the uupc-rc-files.
  145.           This settings contain the information, which was
  146.           previously hardcoded in the config.h-file by
  147.           the Configure-shell-script.       ***/
  148.  
  149.     if (!load_uupc_rc())
  150.     {  fprintf(stderr,"An error occurred while reading the uupc-rc-files!\n\
  151. The following settings must be defined in the UUPCSYSRC-file:\n\
  152.        MailServ, NodeName, NewsDir, Domain, TempDir, MailDir, rmail\n");
  153.        fprintf(stderr,"These settings must be defined in the UUPCUSRRC-file:\n\
  154.        Mailbox, Signature, Name, Home, Organization, Editor\n");
  155.        fprintf(stderr,"And these settings must be defined in the UUPCTRNRC-file:\n\
  156.        Newsadmin, TrnLib, LocalDist, OrganizationDist, CityDist,\n\
  157.        StateDist, Countrydist, ContinentDist\n");
  158.        fprintf(stderr,"\nDon't forget, these settings are required, not optional!\n");
  159.        fflush(stderr);
  160.        exit(1);
  161.     }
  162.  
  163.     while (--argc) {
  164.     if (**++argv == '-') {
  165.         while (*++*argv) {
  166.         switch (**argv) {
  167.         case 'd':        /* run in daemon mode */
  168. /*** OS2: I'm sorry, but we will not run in daemon mode, because
  169.           emx 0.8d does not support fork's at the moment.    **/
  170.             if (*++*argv <= '9' && **argv >= '0') {
  171.             daemon_delay = atoi(*argv) * 60;
  172.             while (*++*argv <= '9' && **argv >= '0') {
  173.                 ;
  174.             }
  175.             } else {
  176.             daemon_delay = TIMER_DEFAULT;
  177.             }
  178.             --*argv;
  179.             break;
  180.         case 'k':        /* kill running acttimes */
  181.             kill_daemon++;
  182.             break;
  183.         default:
  184.             fprintf(stderr, "Unknown option: '%c'\n", **argv);
  185.             exit(1);
  186.         }
  187.         }
  188.     } else {
  189.         fprintf(stderr,
  190.         "Usage:  acttimes [-d<mins>]\nOr:     acttimes -k\n");
  191.         exit(1);
  192.     }
  193.     }
  194.  
  195.     /* Set up a nice friendly umask. */
  196.     umask(002);
  197.  
  198.     /* Make sure we're not already running by creating a lock file. */
  199.     strcpy(lockfile, ACTIVE_TIMES_FILE);
  200.     if ((cp = rindex(lockfile, '/')) != 0) {
  201.     cp++;
  202.     } else {
  203.     cp = lockfile;
  204.     }
  205.     *cp = '\0';
  206.     sprintf(buf, "%sLOCK.%ld", lockfile, (long)getpid());
  207.     if ((fp_lock = fos2open(buf, "w")) == 0) {
  208.     fprintf(stderr, "Unable to create lock temporary `%s'.\n", buf);
  209.     exit(1);
  210.     }
  211.     fprintf(fp_lock, "%ld\n", (long)getpid());
  212.     fclose(fp_lock);
  213.  
  214.     /* Try to link to lock file. */
  215.     strcat(lockfile, "LOCKacttimes");
  216.   dolink:
  217. /*** OS2: This is a bit of a problem, because the DosCopy
  218.           is perhaps not the solution for this link, but I
  219.           think if there is no daemon mode, and if we don't
  220.           run the program twice simultameously, the DosCopy will do ***/
  221. /*    if (link(buf, lockfile) < 0) {  */
  222.     if (DosCopy(buf, lockfile, DCPY_EXISTING)) {
  223.        long otherpid;
  224.     /* Try to avoid possible race with daemon starting up. */
  225.     sleep (5);
  226.     if ((fp_lock = fos2open(lockfile, "r")) == 0) {
  227.         fprintf(stderr, "unable to open %s\n", lockfile);
  228.         unlink(buf);
  229.         exit(1);
  230.     }
  231.     if (fscanf(fp_lock, "%ld", &otherpid) != 1) { 
  232.         fprintf(stderr, "unable to read pid from %s\n", lockfile);
  233.         unlink(buf);
  234.         fclose(fp_lock);
  235.         exit(1);
  236.     }
  237.     fclose(fp_lock);
  238.     if (kill(otherpid, kill_daemon ? SIGTERM : 0) == -1
  239.      && errno == ESRCH) {
  240.         if (unlink(lockfile) == -1) {
  241.         fprintf(stderr, "unable to unlink lockfile %s\n", lockfile);
  242.         unlink(buf);
  243.         exit(1);
  244.         }
  245.         if (!kill_daemon) {
  246.         goto dolink;
  247.         }
  248.     }
  249.     unlink(buf);
  250.     if (kill_daemon) {
  251.         fprintf(stderr, "killing currently running acttimes.\n");
  252.         exit(0);
  253.     } else {
  254.         fprintf(stderr, "acttimes is already running.\n");
  255.         exit(1);
  256.     }
  257.     }
  258.  
  259.     unlink(buf);            /* remove temporary LOCK.<pid> file */
  260.  
  261.     if (kill_daemon) {
  262.     fprintf(stderr, "acttimes is not running.\n");
  263.     wrap_it_up(1);
  264.     }
  265.  
  266. #ifdef SIGHUP
  267.     if( signal( SIGHUP, SIG_IGN ) != SIG_IGN ) {
  268.     signal( SIGHUP, quit_handler );
  269.     }
  270. #endif
  271.     if( signal( SIGINT, SIG_IGN ) != SIG_IGN ) {
  272.     signal( SIGINT, quit_handler );
  273.     }
  274. #ifdef SIGQUIT
  275.     if( signal( SIGQUIT, SIG_IGN ) != SIG_IGN ) {
  276.     signal( SIGQUIT, quit_handler );
  277.     }
  278. #endif
  279.     signal( SIGTERM, quit_handler );
  280. #ifdef SIGTTIN
  281.     signal( SIGTTIN, SIG_IGN );
  282.     signal( SIGTTOU, SIG_IGN );
  283. #endif
  284.     signal( SIGALRM, SIG_IGN );
  285.  
  286.     /* If we're not in daemon mode, run through once and quit. */
  287. /*** OS2: we don't use daemon mode, because of the fork's ***/
  288.     daemon_delay = 0;
  289.     if (!daemon_delay) {
  290.     active_times();
  291.     } else {
  292.     /* For daemon mode, we cut ourself off from anything tty-related and
  293.     ** run in the background (involves forks, but no knives).
  294.     */
  295.     close(0);
  296.     if (open("/dev/null", 2) != 0) {
  297.         fprintf(stderr, "unable to open /dev/null!\n");
  298.         wrap_it_up(1);
  299.     }
  300.     close(1);
  301.     close(2);
  302.     dup(0);
  303.     dup(0);
  304. /*** OS2: no daemon, no fork                    ***/
  305. /*    while ((pid = fork()) < 0) {                */
  306. /*        sleep(2);                               */
  307. /*    }                                           */
  308. /*    if (pid) {                                  */
  309. /*        exit(0);                                */
  310. /*    }                                           */
  311. /*#ifdef TIOCNOTTY                                */
  312. /*    if ((fd = open("/dev/tty", 1)) >= 0) {      */
  313. /*        ioctl(fd, TIOCNOTTY, (int*)0);          */
  314. /*        close(fd);                              */
  315. /*    }                                           */
  316. /*#else                                           */
  317. /*    (void) setpgrp();                           */
  318. /*    while ((pid = fork()) < 0) {                */
  319. /*        sleep(2);                               */
  320. /*    }                                           */
  321. /*    if (pid) {                                  */
  322. /*        exit(0);                                */
  323. /*    }                                           */
  324. /*#endif                                          */
  325.     /* Put our pid in the lock file for death detection */
  326.     if( (fp_lock = fos2open(lockfile, "w")) != 0) {
  327.         fprintf(fp_lock, "%ld\n", (long)getpid());
  328.         fclose(fp_lock);
  329.     }
  330.  
  331.     signal(SIGALRM, alarm_handler);
  332.  
  333.     /* Start timer -- first interval is shorter than all others */
  334.     alarm(TIMER_FIRST);
  335.     for (;;) {
  336. /*** OS2: no daemon, no pause ***/
  337. /*        pause();        /* let alarm go off */
  338.         alarm(0);
  339.  
  340.         if (stat(ACTIVE_FILE, &filestat) < 0) {
  341.             if (stat(ACTIVE_OPT_FILE, &filestat) < 0) {
  342.           fprintf(stderr, "Unable to stat active file -- quitting.\n");
  343.           wrap_it_up(1);
  344.         }
  345.         }
  346.         if (filestat.st_size != last_actsize) {
  347.         last_actsize = filestat.st_size;
  348.         active_times();
  349.         }
  350.         alarm(daemon_delay);
  351.     } /* for */
  352.     }/* if */
  353.  
  354.     wrap_it_up(0);
  355. }
  356.  
  357. SIGRET
  358. alarm_handler()
  359. {
  360.     signal(SIGALRM, alarm_handler);
  361. }
  362.  
  363. SIGRET
  364. quit_handler()
  365. {
  366.     wrap_it_up(0);
  367. }
  368.  
  369. void
  370. wrap_it_up(ret)
  371. {
  372.     unlink(lockfile);
  373.     exit(ret);
  374. }
  375.  
  376. void
  377. active_times()
  378. {
  379.     FILE *fp_active, *fp_date_r, *fp_date_w;
  380.     register char *cp;
  381.  
  382.     if ((fp_active = fos2open(ACTIVE_FILE, "r")) == NULL) {
  383.         if ((fp_active = fos2open(ACTIVE_OPT_FILE, "r")) == NULL) {
  384.         if (!daemon_delay) {
  385.             fprintf(stderr, "Unable to open active file.\n");
  386.         }
  387.         return;
  388.     }
  389.     }
  390.     if ((fp_date_r = fos2open(ACTIVE_TIMES_FILE, "r")) == NULL) {
  391.     if (!daemon_delay) {
  392.         fprintf(stderr, "Creating active.times file.\n");
  393.     }
  394.     old_groups = 1;
  395.     } else {
  396.     old_groups = 0;
  397.     }
  398.     sprintf(buf, "%s.n", ACTIVE_TIMES_FILE);
  399.     if ((fp_date_w = fos2open(buf, "w")) == NULL) {
  400.     if (!daemon_delay) {
  401.         fprintf(stderr, "Unable to create active.times file.\n");
  402.     }
  403.     return;
  404.     }
  405.  
  406.     /* Loop through entire active file and remember each line. */
  407.     while (fgets(buf, sizeof buf, fp_active)) {
  408.     if (!(cp = index(buf, ' ')) || cp[1] == '\0') {
  409.         continue;
  410.     }
  411.     cp[1] = '\0';        /* include trailing space */
  412.     if (!(cp = rindex(cp + 2, ' '))) {
  413.         continue;
  414.     }
  415.     pline = (ACTIVE_LINE*)malloc(sizeof (ACTIVE_LINE));
  416.     if (!pline) {
  417.         if (line_root) {
  418.         last_line->link = NULL;
  419.         free_lines();
  420.         }
  421.       bug_out:
  422.         fclose(fp_active);
  423.         fclose(fp_date_r);
  424.         fclose(fp_date_w);
  425.         return;
  426.     }
  427.     pline->name = malloc(strlen(buf) + 1);
  428.     if (!pline->name) {
  429.         if (line_root) {
  430.         last_line->link = NULL;
  431.         pline->name = NULL;
  432.         free_lines();
  433.         } else {
  434.         free(pline);
  435.         }
  436.         goto bug_out;
  437.     }
  438.     strcpy(pline->name, buf);
  439.     pline->type = cp[1];
  440.     if (!last_line) {
  441.         line_root = pline;
  442.     } else {
  443.         last_line->link = pline;
  444.     }
  445.     last_line = pline;
  446.     }
  447.     last_line->link = NULL;
  448.     fclose(fp_active);
  449.  
  450.     if (fp_date_r) {
  451.     /* Loop through date file, copying existing groups to new file. */
  452.     while (fgets(buf, sizeof buf, fp_date_r)) {
  453.         last_line = NULL;
  454.         for (pline = line_root; pline; pline = pline->link) {
  455.         if (strnEQ(buf, pline->name, strlen(pline->name))) {
  456.             fputs(buf, fp_date_w);
  457.             free(pline->name);
  458.             if (last_line) {
  459.             last_line->link = pline->link;
  460.             } else {
  461.             line_root = pline->link;
  462.             }
  463.             free(pline);
  464.             break;
  465.         }
  466.         last_line = pline;
  467.         }/* for */
  468.     }
  469.     }
  470.     /* Remaining entries from active file are new groups. */
  471.     for (pline = line_root; pline; pline = last_line) {
  472.     if (pline->type != 'x' && pline->type != '=') {
  473.         /* If it's not 'x'ed out, write it out with the current time. */
  474.         fprintf(fp_date_w, "%s%ld acttimes@%s\n", pline->name,
  475.         old_groups ? 30010440L : time(NULL), DOMAIN);
  476.     }
  477.     free(pline->name);
  478.     last_line = pline->link;
  479.     free(pline);
  480.     }
  481.     fclose(fp_date_w);
  482.     if (fp_date_r != NULL) fclose(fp_date_r);
  483.     line_root = NULL;
  484.  
  485.     /* rm active.times.o */
  486.     sprintf(buf,"%s.o", ACTIVE_TIMES_FILE);
  487.     unlink(buf);
  488.     /* mv active.times active.times.o */
  489. /*** OS2: this is not very difficult to patch, the combination
  490.           of link/unlink is a save rename. Use DosCopy or rename ***/
  491. /**    link(ACTIVE_TIMES_FILE, buf); **/
  492.     DosCopy(ACTIVE_TIMES_FILE, buf, DCPY_EXISTING);
  493.     unlink(ACTIVE_TIMES_FILE);
  494.     /* mv active.times.n active.times */
  495.     sprintf(buf, "%s.n", ACTIVE_TIMES_FILE);
  496. /**    link(buf, ACTIVE_TIMES_FILE); **/
  497.     DosCopy(buf, ACTIVE_TIMES_FILE, DCPY_EXISTING);
  498.     unlink(buf);
  499. }
  500.  
  501. void
  502. free_lines()
  503. {
  504.     for (pline = line_root; pline; pline = last_line) {
  505.     if (pline->name) {
  506.         free(pline->name);
  507.     }
  508.     last_line = pline->link;
  509.     free(pline);
  510.     }
  511.     line_root = NULL;
  512. }
  513.