home *** CD-ROM | disk | FTP | other *** search
- /* $Header: acttimes.c,v 1.1 91/11/02 18:38:29 davison Exp $
- **
- ** $Log: acttimes.c,v $
- */
-
- /* This program will maintain the file active.times if your news software
- ** doesn't already do this for you. The file contains a list of newsgroup
- ** names followed by the time of creation (in seconds since 1970) and the
- ** address of the creator. Since we can't tell who actually created the
- ** group, they will all indicate acttimes@DOMAIN.
- **
- ** Place this file in your NNTP support directory and change your
- ** common/conf.h to undef NGDATE_FILE and STAT_FILE, and define
- ** ACTIVE_TIMES_FILE. To make, you can replace every mention of
- ** "mkgrdates" in the support/Makefile with "acttimes" and then
- ** type "make".
- **
- ** To use this without having NNTP around, undefine the NNTP_SUPPORT
- ** define, edit the other defines that follow to indicate your setup,
- ** and compile it with something like "cc -O -o acttimes acttimes.c".
- **
- ** Use either "acttimes -d" to start a daemon process that wakes up every
- ** 10 minutes (by default) to check if the active file is a different
- ** size, or put "acttimes" into your cron file to be run periodically.
- */
-
- /*** OS2: no NNTP ***/
- #undef NNTP_SUPPORT /* comment out if not using NNTP */
- /*** OS2: there are links used in the source, but the
- OS/2-file-systems don't have them. We try to
- avoid them via the DosCopy-systemcall ***/
- #include <os2.h>
-
- /*** OS2: chdir does not change the workingdrive if required,
- but the news gcc-call _chdir2 does this. ***/
- #ifndef _CHDIR2_DEF
- #define _CHDIR2_DEF
- #define chdir _chdir2
- #define getcwd _getcwd2
- #endif
-
- #include <stdio.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <signal.h>
- #include <errno.h>
-
- /*** OS2: for the check of the uupc-rc-files, we need
- the os2patch-files ***/
- #include "os2patch.h"
-
- #ifdef NNTP_SUPPORT
- #include "../common/conf.h"
- #endif
- #ifdef USG
- #include <time.h>
- #else
- #include <sys/time.h>
- #endif
-
- /* ---------- Start of configuration defines ---------- */
-
- /*** OS2: yes, we have TERMIO ***/
- /*#ifndef USG*/
- #define TERMIO /* Is this is termio system? */
- /*#endif*/
-
- /* NNTP sites have the following already defined in ../common/conf.h */
-
- #ifndef DOMAIN /* our domain name */
- #define DOMAIN "local"
- #endif
-
- #ifndef ACTIVE_FILE /* the active file for your news system */
- /** OS2: patch **/
- #define ACTIVE_FILE uupc_rc_settings.active
- #endif
-
- #ifndef ACTIVE_OPT_FILE /* the active file for your news system */
- /** OS2: patch **/
- #define ACTIVE_OPT_FILE uupc_rc_settings.active_opt
- #endif
-
- #ifndef ACTIVE_TIMES_FILE /* the name of the file to update */
- /** OS2: patch **/
- #define ACTIVE_TIMES_FILE uupc_rc_settings.active_times
- #endif
-
- #ifndef SIGRET /* set this to "int" if you have problems */
- #define SIGRET void
- #endif
-
- #ifndef MAXPATHLEN /* you'll probably want to leave this alone */
- #define MAXPATHLEN 1024
- #endif
-
- /*#define index strchr /* uncomment these if you need them */
- /*#define rindex strrchr /* (i.e. if index is undefined) */
-
- /* ---------- End of configuration defines ---------- */
-
- #ifdef TERMIO
- #include <termio.h>
- #else
- #include <sgtty.h>
- #endif
-
- #define TIMER_FIRST 1
- #define TIMER_DEFAULT (10 * 60)
-
- #define strnEQ(x,y,n) (!strncmp((x),(y),(n)))
-
- extern errno;
-
- char *index(), *rindex(), *malloc();
- SIGRET alarm_handler(), quit_handler();
- void active_times(), free_lines(), wrap_it_up();
-
- typedef struct _active_line {
- struct _active_line *link;
- char *name;
- char type;
- } ACTIVE_LINE;
-
- ACTIVE_LINE *line_root = NULL, *last_line = NULL, *pline = NULL;
- long last_actsize;
- int daemon_delay = 0, kill_daemon = 0, old_groups = 0;
-
- FILE *fp_lock;
-
- struct stat filestat;
-
- char buf[MAXPATHLEN];
- char lockfile[MAXPATHLEN];
-
- main(argc, argv)
- int argc;
- char *argv[];
- {
- int fd;
- long pid;
- char *cp;
-
- /*** OS2: Now we load the settings out of the uupc-rc-files.
- This settings contain the information, which was
- previously hardcoded in the config.h-file by
- the Configure-shell-script. ***/
-
- if (!load_uupc_rc())
- { fprintf(stderr,"An error occurred while reading the uupc-rc-files!\n\
- The following settings must be defined in the UUPCSYSRC-file:\n\
- MailServ, NodeName, NewsDir, Domain, TempDir, MailDir, rmail\n");
- fprintf(stderr,"These settings must be defined in the UUPCUSRRC-file:\n\
- Mailbox, Signature, Name, Home, Organization, Editor\n");
- fprintf(stderr,"And these settings must be defined in the UUPCTRNRC-file:\n\
- Newsadmin, TrnLib, LocalDist, OrganizationDist, CityDist,\n\
- StateDist, Countrydist, ContinentDist\n");
- fprintf(stderr,"\nDon't forget, these settings are required, not optional!\n");
- fflush(stderr);
- exit(1);
- }
-
- while (--argc) {
- if (**++argv == '-') {
- while (*++*argv) {
- switch (**argv) {
- case 'd': /* run in daemon mode */
- /*** OS2: I'm sorry, but we will not run in daemon mode, because
- emx 0.8d does not support fork's at the moment. **/
- if (*++*argv <= '9' && **argv >= '0') {
- daemon_delay = atoi(*argv) * 60;
- while (*++*argv <= '9' && **argv >= '0') {
- ;
- }
- } else {
- daemon_delay = TIMER_DEFAULT;
- }
- --*argv;
- break;
- case 'k': /* kill running acttimes */
- kill_daemon++;
- break;
- default:
- fprintf(stderr, "Unknown option: '%c'\n", **argv);
- exit(1);
- }
- }
- } else {
- fprintf(stderr,
- "Usage: acttimes [-d<mins>]\nOr: acttimes -k\n");
- exit(1);
- }
- }
-
- /* Set up a nice friendly umask. */
- umask(002);
-
- /* Make sure we're not already running by creating a lock file. */
- strcpy(lockfile, ACTIVE_TIMES_FILE);
- if ((cp = rindex(lockfile, '/')) != 0) {
- cp++;
- } else {
- cp = lockfile;
- }
- *cp = '\0';
- sprintf(buf, "%sLOCK.%ld", lockfile, (long)getpid());
- if ((fp_lock = fos2open(buf, "w")) == 0) {
- fprintf(stderr, "Unable to create lock temporary `%s'.\n", buf);
- exit(1);
- }
- fprintf(fp_lock, "%ld\n", (long)getpid());
- fclose(fp_lock);
-
- /* Try to link to lock file. */
- strcat(lockfile, "LOCKacttimes");
- dolink:
- /*** OS2: This is a bit of a problem, because the DosCopy
- is perhaps not the solution for this link, but I
- think if there is no daemon mode, and if we don't
- run the program twice simultameously, the DosCopy will do ***/
- /* if (link(buf, lockfile) < 0) { */
- if (DosCopy(buf, lockfile, DCPY_EXISTING)) {
- long otherpid;
- /* Try to avoid possible race with daemon starting up. */
- sleep (5);
- if ((fp_lock = fos2open(lockfile, "r")) == 0) {
- fprintf(stderr, "unable to open %s\n", lockfile);
- unlink(buf);
- exit(1);
- }
- if (fscanf(fp_lock, "%ld", &otherpid) != 1) {
- fprintf(stderr, "unable to read pid from %s\n", lockfile);
- unlink(buf);
- fclose(fp_lock);
- exit(1);
- }
- fclose(fp_lock);
- if (kill(otherpid, kill_daemon ? SIGTERM : 0) == -1
- && errno == ESRCH) {
- if (unlink(lockfile) == -1) {
- fprintf(stderr, "unable to unlink lockfile %s\n", lockfile);
- unlink(buf);
- exit(1);
- }
- if (!kill_daemon) {
- goto dolink;
- }
- }
- unlink(buf);
- if (kill_daemon) {
- fprintf(stderr, "killing currently running acttimes.\n");
- exit(0);
- } else {
- fprintf(stderr, "acttimes is already running.\n");
- exit(1);
- }
- }
-
- unlink(buf); /* remove temporary LOCK.<pid> file */
-
- if (kill_daemon) {
- fprintf(stderr, "acttimes is not running.\n");
- wrap_it_up(1);
- }
-
- #ifdef SIGHUP
- if( signal( SIGHUP, SIG_IGN ) != SIG_IGN ) {
- signal( SIGHUP, quit_handler );
- }
- #endif
- if( signal( SIGINT, SIG_IGN ) != SIG_IGN ) {
- signal( SIGINT, quit_handler );
- }
- #ifdef SIGQUIT
- if( signal( SIGQUIT, SIG_IGN ) != SIG_IGN ) {
- signal( SIGQUIT, quit_handler );
- }
- #endif
- signal( SIGTERM, quit_handler );
- #ifdef SIGTTIN
- signal( SIGTTIN, SIG_IGN );
- signal( SIGTTOU, SIG_IGN );
- #endif
- signal( SIGALRM, SIG_IGN );
-
- /* If we're not in daemon mode, run through once and quit. */
- /*** OS2: we don't use daemon mode, because of the fork's ***/
- daemon_delay = 0;
- if (!daemon_delay) {
- active_times();
- } else {
- /* For daemon mode, we cut ourself off from anything tty-related and
- ** run in the background (involves forks, but no knives).
- */
- close(0);
- if (open("/dev/null", 2) != 0) {
- fprintf(stderr, "unable to open /dev/null!\n");
- wrap_it_up(1);
- }
- close(1);
- close(2);
- dup(0);
- dup(0);
- /*** OS2: no daemon, no fork ***/
- /* while ((pid = fork()) < 0) { */
- /* sleep(2); */
- /* } */
- /* if (pid) { */
- /* exit(0); */
- /* } */
- /*#ifdef TIOCNOTTY */
- /* if ((fd = open("/dev/tty", 1)) >= 0) { */
- /* ioctl(fd, TIOCNOTTY, (int*)0); */
- /* close(fd); */
- /* } */
- /*#else */
- /* (void) setpgrp(); */
- /* while ((pid = fork()) < 0) { */
- /* sleep(2); */
- /* } */
- /* if (pid) { */
- /* exit(0); */
- /* } */
- /*#endif */
- /* Put our pid in the lock file for death detection */
- if( (fp_lock = fos2open(lockfile, "w")) != 0) {
- fprintf(fp_lock, "%ld\n", (long)getpid());
- fclose(fp_lock);
- }
-
- signal(SIGALRM, alarm_handler);
-
- /* Start timer -- first interval is shorter than all others */
- alarm(TIMER_FIRST);
- for (;;) {
- /*** OS2: no daemon, no pause ***/
- /* pause(); /* let alarm go off */
- alarm(0);
-
- if (stat(ACTIVE_FILE, &filestat) < 0) {
- if (stat(ACTIVE_OPT_FILE, &filestat) < 0) {
- fprintf(stderr, "Unable to stat active file -- quitting.\n");
- wrap_it_up(1);
- }
- }
- if (filestat.st_size != last_actsize) {
- last_actsize = filestat.st_size;
- active_times();
- }
- alarm(daemon_delay);
- } /* for */
- }/* if */
-
- wrap_it_up(0);
- }
-
- SIGRET
- alarm_handler()
- {
- signal(SIGALRM, alarm_handler);
- }
-
- SIGRET
- quit_handler()
- {
- wrap_it_up(0);
- }
-
- void
- wrap_it_up(ret)
- {
- unlink(lockfile);
- exit(ret);
- }
-
- void
- active_times()
- {
- FILE *fp_active, *fp_date_r, *fp_date_w;
- register char *cp;
-
- if ((fp_active = fos2open(ACTIVE_FILE, "r")) == NULL) {
- if ((fp_active = fos2open(ACTIVE_OPT_FILE, "r")) == NULL) {
- if (!daemon_delay) {
- fprintf(stderr, "Unable to open active file.\n");
- }
- return;
- }
- }
- if ((fp_date_r = fos2open(ACTIVE_TIMES_FILE, "r")) == NULL) {
- if (!daemon_delay) {
- fprintf(stderr, "Creating active.times file.\n");
- }
- old_groups = 1;
- } else {
- old_groups = 0;
- }
- sprintf(buf, "%s.n", ACTIVE_TIMES_FILE);
- if ((fp_date_w = fos2open(buf, "w")) == NULL) {
- if (!daemon_delay) {
- fprintf(stderr, "Unable to create active.times file.\n");
- }
- return;
- }
-
- /* Loop through entire active file and remember each line. */
- while (fgets(buf, sizeof buf, fp_active)) {
- if (!(cp = index(buf, ' ')) || cp[1] == '\0') {
- continue;
- }
- cp[1] = '\0'; /* include trailing space */
- if (!(cp = rindex(cp + 2, ' '))) {
- continue;
- }
- pline = (ACTIVE_LINE*)malloc(sizeof (ACTIVE_LINE));
- if (!pline) {
- if (line_root) {
- last_line->link = NULL;
- free_lines();
- }
- bug_out:
- fclose(fp_active);
- fclose(fp_date_r);
- fclose(fp_date_w);
- return;
- }
- pline->name = malloc(strlen(buf) + 1);
- if (!pline->name) {
- if (line_root) {
- last_line->link = NULL;
- pline->name = NULL;
- free_lines();
- } else {
- free(pline);
- }
- goto bug_out;
- }
- strcpy(pline->name, buf);
- pline->type = cp[1];
- if (!last_line) {
- line_root = pline;
- } else {
- last_line->link = pline;
- }
- last_line = pline;
- }
- last_line->link = NULL;
- fclose(fp_active);
-
- if (fp_date_r) {
- /* Loop through date file, copying existing groups to new file. */
- while (fgets(buf, sizeof buf, fp_date_r)) {
- last_line = NULL;
- for (pline = line_root; pline; pline = pline->link) {
- if (strnEQ(buf, pline->name, strlen(pline->name))) {
- fputs(buf, fp_date_w);
- free(pline->name);
- if (last_line) {
- last_line->link = pline->link;
- } else {
- line_root = pline->link;
- }
- free(pline);
- break;
- }
- last_line = pline;
- }/* for */
- }
- }
- /* Remaining entries from active file are new groups. */
- for (pline = line_root; pline; pline = last_line) {
- if (pline->type != 'x' && pline->type != '=') {
- /* If it's not 'x'ed out, write it out with the current time. */
- fprintf(fp_date_w, "%s%ld acttimes@%s\n", pline->name,
- old_groups ? 30010440L : time(NULL), DOMAIN);
- }
- free(pline->name);
- last_line = pline->link;
- free(pline);
- }
- fclose(fp_date_w);
- if (fp_date_r != NULL) fclose(fp_date_r);
- line_root = NULL;
-
- /* rm active.times.o */
- sprintf(buf,"%s.o", ACTIVE_TIMES_FILE);
- unlink(buf);
- /* mv active.times active.times.o */
- /*** OS2: this is not very difficult to patch, the combination
- of link/unlink is a save rename. Use DosCopy or rename ***/
- /** link(ACTIVE_TIMES_FILE, buf); **/
- DosCopy(ACTIVE_TIMES_FILE, buf, DCPY_EXISTING);
- unlink(ACTIVE_TIMES_FILE);
- /* mv active.times.n active.times */
- sprintf(buf, "%s.n", ACTIVE_TIMES_FILE);
- /** link(buf, ACTIVE_TIMES_FILE); **/
- DosCopy(buf, ACTIVE_TIMES_FILE, DCPY_EXISTING);
- unlink(buf);
- }
-
- void
- free_lines()
- {
- for (pline = line_root; pline; pline = last_line) {
- if (pline->name) {
- free(pline->name);
- }
- last_line = pline->link;
- free(pline);
- }
- line_root = NULL;
- }
-