Ø•”~ TIN-1_22.BCKlŽÐ TIN-1_22.BCKHBACKUP/LOG [SRC.TIN-1_22...]*.*; $1$DUA4:[ANONYMOUS.TIN]TIN-1_22.BCK/SAV MCQUILLIN /€@[Ï]“—V5.5 _HOBBES::  _$1$DUA4: V5.5-2 ~ yð*[SRC.TIN-1_22]$M$AKEFILE.;1+,e.-//€ 4-- -d0@î123KÿPWO.56`D.t…—7ÐU^1—89€]V‚—G/€HªJÿZ# Makefile for tin - for tin compiler flag options read INSTALL and README. # # Options that may need changing. For advanced options read the INSTALL file. # CC = cc COPTS = -c -O #CC = gcc #COPTS = -c -g # LD has to be changed to ln for AmigaDOS LD = $(CC) YACC = yacc #YACC = bison -y #DEBUG = DEBUG = -g -DDEBUG # Where are your news libdir & spooldir? LIBDIR = /usr/lib/news SPOOLDIR= /usr/spool/news NOVROOTDIR= $(SPOOLDIR) # Where do you want the binary & manual page installed? INS_BINARY_DIR = /usr/local/bin INS_DAEMON_DIR = $(LIBDIR) INS_MANUAL_DIR = /usr/local/man/man INS_MANUAL_EXT = 1 # From: address in posted articles (don't use both - read the INSTALL file) NNTP_INEWS_GATEWAY= NNTP_INEWS_DOMAIN= #.erlm.siemens.de # Default nntp server (can be overridden by NNTPSERVER environment variable) NNTP_DEFAULT_SERVER=# news.erlm.siemens.de # Use INN clientlibs config functions (add -DUSE_INN_NNTPLIB to COPTS line) INN_NNTPLIB= AMIGA_COPTS=-so -wc -m0s -DM_AMIGA -DSYSV -DSLOW_SCREEN_UPDATE \ -DNO_PIPING -DNO_SHELL_ESCAPE -DAMIGA_BBS -DLIBDIR=""uulib:"" \ -DSPOOLDIR=""uunews:"" PROJECT = tin EXE = tin EXED = tind MAKE = make SHELL = /bin/sh STRIP = strip STRIP2 = mcs -d #ROFF = nroff -man ROFF = groff -Tascii -man #BASE_VER= 1.21/tin-1.21 BASE_VER= 170993 VER = 1.22 MAIL_ADDR = "iain.lea@erlm.siemens.de" HFILES = config.h tin.h extern.h nntplib.h proto.h stpwatch.h amiga.h os_2.h \ win32.h CFILES = active.c amiga.c art.c curses.c debug.c envarg.c feed.c getline.c \ group.c hashstr.c help.c inews.c init.c kill.c lang.c mail.c \ main.c memory.c misc.c newsrc.c nntplib.c open.c os_2.c page.c \ parsdate.y post.c prompt.c rcfile.c save.c screen.c search.c \ select.c sigfile.c signal.c spooldir.c strftime.c thread.c \ wildmat.c win32.c xref.c OFILES = active.o amiga.o art.o curses.o debug.o envarg.o feed.o getline.o \ group.o hashstr.o help.o inews.o init.o kill.o lang.o mail.o \ main.o memory.o misc.o newsrc.o nntplib.o open.o os_2.o page.o \ parsdate.o post.o prompt.o rcfile.o save.o screen.o search.o \ select.o sigfile.o signal.o spooldir.o strftime.o thread.o \ wildmat.o win32.o xref.o SUPPORT = Makefile Makefile.ami Makefile.bcc Makefile.icc MANIFEST README \ README.AMI README.OS2 CHANGES INSTALL HACKERS TODO FTP \ *.[13] $(EXE).nrf $(EXE).lsm actived.c NNTP_PATCH = README.NNTP INSTALL.NNTP common.patch server.patch xindex.c \ xmotd.c xoverview.c xuser.c ALL_FILES = $(SUPPORT) $(NNTP_PATCH) $(HFILES) patchlev.h $(CFILES) LINTFLAGS=-a -c -h -n -x all: @echo "Makefile for the TIN v$(VER) Usenet newsreader. Configuration:" @echo " " @echo " Compiler=[$(CC)] Copts=[$(COPTS)] INN Lib=[$(INN_NNTPLIB)]" @echo " Install Bindir=[$(INS_BINARY_DIR)] Mandir=[$(INS_MANUAL_DIR)$(INS_MANUAL_EXT)] Manext=[$(INS_MANUAL_EXT)]" @echo " News Lib=[$(LIBDIR)] Spool=[$(SPOOLDIR)] Nov=[$(NOVROOTDIR)]" @echo " News Gateway=[$(NNTP_INEWS_GATEWAY)] Domain=[$(NNTP_INEWS_DOMAIN)] Server=[$(NNTP_DEFAULT_SERVER)]" @echo " " @echo "If the above options are OK make one of the following targets:" @echo " " @echo " make bsd [ BSD[I] / DGUX / NeXT / OSF1 / Pyramid / SunOS / Ultrix (nntp)]" @echo " make sysv [ SysV / HPUX 7&8 ] make sysvr4 [ SysVR4 / HPUX 9 ]" @echo " make aix [ IBM AIX (nntp) ] make amiga [ AmigaDOS ]" @echo " make apollo [ Apollo DomainOS ] make coherent [ Coherent 4.0 ]" @echo " make dynix [ Sequent DYNIX (nntp) ] make irix [ SGI Irix ]" @echo " make linux [ Linux (nntp) ] make minix [ Minix 386 ]" @echo " make mips [ Mips / CDC EPIX ] make ptx [ Sequent PTX ]" @echo " make qnx [ QNX 4.1 ] make sco [ SCO Unix ]" @echo " make sinix [ SNI Sinix ] make tower [ NCR Tower]" @echo " make xenix [ SCO Xenix 386 ]" @echo " " @echo "Note that targets marked with '(nntp)' have -DNNTP_ABLE defined automatically." @echo " " .c.o: $(CC) $(CFLAGS) $*.c # Uncomment for COHERENT os #.c.y: # $(YACC) $*.y # For IBM AIX aix: @echo "Compiling $(EXE) v$(VER) for IBM AIX..." @$(MAKE) CC=$(CC) CFLAGS='$(COPTS) -DSYSV -DRS6000 \ -DNNTP_INEWS_GATEWAY=\"$(NNTP_INEWS_GATEWAY)\" \ -DNNTP_INEWS_DOMAIN=\"$(NNTP_INEWS_DOMAIN)\" \ -DNNTP_DEFAULT_SERVER=\"$(NNTP_DEFAULT_SERVER)\" \ -DLIBDIR=\"$(LIBDIR)\" \ -DSPOOLDIR=\"$(SPOOLDIR)\" \ -DNOVROOTDIR=\"$(NOVROOTDIR)\"' \ LIBS="-lcurses -ltermcap $(INN_NNTPLIB)" \ EXE=tin linkit # For Commodore AmigaOS amiga: @echo "Compiling $(EXE) v$(VER) for AmigaDOS (Manx-C 5.2)..." $(MAKE) CC=$(CC) "CFLAGS=$(AMIGA_COPTS)" LIBS=-lc EXE=tin linkit # For Apollo apollo: @echo "Compiling $(EXE) v$(VER) for Apollo..." @$(MAKE) CC=$(CC) CFLAGS='$(COPTS) \ -DNNTP_INEWS_GATEWAY=\"$(NNTP_INEWS_GATEWAY)\" \ -DNNTP_INEWS_DOMAIN=\"$(NNTP_INEWS_DOMAIN)\" \ -DNNTP_DEFAULT_SERVER=\"$(NNTP_DEFAULT_SERVER)\" \ -DLIBDIR=\"$(LIBDIR)\" \ -DSPOOLDIR=\"$(SPOOLDIR)\" \ -DNOVROOTDIR=\"$(NOVROOTDIR)\"' \ LIBS="-lcurses -ltermcap $(INN_NNTPLIB)" \ EXE=tin linkit # For BSD-derived systems bsd: @echo "Compiling $(EXE) v$(VER) for BSD/BSDI/DGUX/NeXT/OSF1/Pyramid/SunOS/Ultrix..." @$(MAKE) CC=$(CC) CFLAGS='$(COPTS) -DBSD \ -DNNTP_INEWS_GATEWAY=\"$(NNTP_INEWS_GATEWAY)\" \ -DNNTP_INEWS_DOMAIN=\"$(NNTP_INEWS_DOMAIN)\" \ -DNNTP_DEFAULT_SERVER=\"$(NNTP_DEFAULT_SERVER)\" \ -DLIBDIR=\"$(LIBDIR)\" \ -DSPOOLDIR=\"$(SPOOLDIR)\" \ -DNOVROOTDIR=\"$(NOVROOTDIR)\"' \ LIBS="-lcurses -ltermcap $(INN_NNTPLIB)" \ EXE=tin linkit # For Coherent 4.0 # NETLIBS="-lsocket" \ # coherent: @echo "Compiling $(EXE) v$(VER) for Coherent 4.0..." @$(MAKE) CC=$(CC) CFLAGS='-c -DSYSV \ -DNNTP_INEWS_GATEWAY=\"$(NNTP_INEWS_GATEWAY)\" \ -DNNTP_INEWS_DOMAIN=\"$(NNTP_INEWS_DOMAIN)\" \ -DNNTP_DEFAULT_SERVER=\"$(NNTP_DEFAULT_SERVER)\" \ -DLIBDIR=\"$(LIBDIR)\" \ -DSPOOLDIR=\"$(SPOOLDIR)\" \ -DNOVROOTDIR=\"$(NOVROOTDIR)\"' \ LIBS="-lterm $(INN_NNTPLIB)" \ LFLAGS= EXE=tin linkit # For Sequent DYNIX dynix: @echo "Compiling $(EXE) v$(VER) for Sequent DYNIX..." @$(MAKE) CC=$(CC) CFLAGS='$(COPTS) -DBSD \ -DNNTP_INEWS_GATEWAY=\"$(NNTP_INEWS_GATEWAY)\" \ -DNNTP_INEWS_DOMAIN=\"$(NNTP_INEWS_DOMAIN)\" \ -DNNTP_DEFAULT_SERVER=\"$(NNTP_DEFAULT_SERVER)\" \ -DLIBDIR=\"$(LIBDIR)\" \ -DSPOOLDIR=\"$(SPOOLDIR)\" \ -DNOVROOTDIR=\"$(NOVROOTDIR)\"' \ LIBS="-lcurses -ltermcap -lseq $(INN_NNTPLIB)" \ EXE=tin linkit # For SGI Irix irix: @echo "Compiling $(EXE) v$(VER) for SGI Irix..." @$(MAKE) CC=$(CC) CFLAGS='$(COPTS) -cckr -DSYSV \ -DNNTP_INEWS_GATEWAY=\"$(NNTP_INEWS_GATEWAY)\" \ -DNNTP_INEWS_DOMAIN=\"$(NNTP_INEWS_DOMAIN)\" \ -DNNTP_DEFAULT_SERVER=\"$(NNTP_DEFAULT_SERVER)\" \ -DLIBDIR=\"$(LIBDIR)\" \ -DSPOOLDIR=\"$(SPOOLDIR)\" \ -DNOVROOTDIR=\"$(NOVROOTDIR)\"' \ LIBS="-lsun -lcurses -ltermcap $(INN_NNTPLIB)" \ EXE=tin linkit # For Linux linux: @echo "Compiling $(EXE) v$(VER) for Linux (NNTP Ready)..." @$(MAKE) CC=$(CC) CFLAGS='$(COPTS) -static -DSYSV \ -DNNTP_INEWS_GATEWAY=\"$(NNTP_INEWS_GATEWAY)\" \ -DNNTP_INEWS_DOMAIN=\"$(NNTP_INEWS_DOMAIN)\" \ -DNNTP_DEFAULT_SERVER=\"$(NNTP_DEFAULT_SERVER)\" \ -DLIBDIR=\"$(LIBDIR)\" \ -DSPOOLDIR=\"$(SPOOLDIR)\" \ -DNOVROOTDIR=\"$(NOVROOTDIR)\"' \ LIBS="-lcurses -ltermcap $(INN_NNTPLIB)" \ EXE=tin linkit # For Minix 386 minix: @echo "Compiling $(EXE) v$(VER) for Minix 386..." @$(MAKE) CC=$(CC) CFLAGS='$(COPTS) -DMINIX -D_POSIX_SOURCE \ -DNNTP_INEWS_GATEWAY=\"$(NNTP_INEWS_GATEWAY)\" \ -DNNTP_INEWS_DOMAIN=\"$(NNTP_INEWS_DOMAIN)\" \ -DNNTP_DEFAULT_SERVER=\"$(NNTP_DEFAULT_SERVER)\" \ -DLIBDIR=\"$(LIBDIR)\" \ -DSPOOLDIR=\"$(SPOOLDIR)\" \ -DNOVROOTDIR=\"$(NOVROOTDIR)\"' \ LIBS="-lcurses $(INN_NNTPLIB)" \ EXE=tin linkit chmem +131072 $(EXE) # For Mips/CDC EPIX mips: @echo "Compiling $(EXE) v$(VER) for Mips/CDC EPIX..." @$(MAKE) CC=$(CC) CFLAGS='$(COPTS) -DBSD -DEPIX -systype bsd43 \ -DNNTP_INEWS_GATEWAY=\"$(NNTP_INEWS_GATEWAY)\" \ -DNNTP_INEWS_DOMAIN=\"$(NNTP_INEWS_DOMAIN)\" \ -DNNTP_DEFAULT_SERVER=\"$(NNTP_DEFAULT_SERVER)\" \ -DLIBDIR=\"$(LIBDIR)\" \ -DSPOOLDIR=\"$(SPOOLDIR)\" \ -DNOVROOTDIR=\"$(NOVROOTDIR)\"' \ LIBS="-L/bsd43/usr/lib -lcurses -ltermcap -lc $(INN_NNTPLIB)" \ EXE=tin linkit # For Sequent PTX ptx: @echo "Compiling $(EXE) v$(VER) for Sequent PTX..." @$(MAKE) CC=$(CC) CFLAGS='$(COPTS) -DPTX \ -DNNTP_INEWS_GATEWAY=\"$(NNTP_INEWS_GATEWAY)\" \ -DNNTP_INEWS_DOMAIN=\"$(NNTP_INEWS_DOMAIN)\" \ -DNNTP_DEFAULT_SERVER=\"$(NNTP_DEFAULT_SERVER)\" \ -DLIBDIR=\"$(LIBDIR)\" \ -DSPOOLDIR=\"$(SPOOLDIR)\" \ -DNOVROOTDIR=\"$(NOVROOTDIR)\"' \ LIBS="-lcurses -ltermcap" \ NETLIBS="-lsocket -linet -lnsl_s $(INN_NNTPLIB)" \ EXE=tin linkit # For QNX qnx: @echo "Compiling $(EXE) v$(VER) for QNX 4.1 (Watcom C 8.5E)..." @$(MAKE) CC=$(CC) CFLAGS='$(COPTS) -2 -ml -M -fi=unix.h -Wc,-zt200 -D_POSIX_SOURCE_ -DQNX4 \ -DNNTP_INEWS_GATEWAY=\"$(NNTP_INEWS_GATEWAY)\" \ -DNNTP_INEWS_DOMAIN=\"$(NNTP_INEWS_DOMAIN)\" \ -DNNTP_DEFAULT_SERVER=\"$(NNTP_DEFAULT_SERVER)\" \ -DLIBDIR=\"$(LIBDIR)\" \ -DSPOOLDIR=\"$(SPOOLDIR)\" \ -DNOVROOTDIR=\"$(NOVROOTDIR)\"' \ LIBS="-lcurses $(INN_NNTPLIB)" \ LFLAGS="-Wc,-zt200 -2 -ml -M -N24K '-Wl,op H=1k'" \ EXE=tin linkit # For SCO Unix # NETLIBS="-lnsl_s -lsocket" \ # sco: @echo "Compiling $(EXE) v$(VER) for SCO Unix..." @$(MAKE) CC=$(CC) CFLAGS='$(COPTS) -DSYSV -DSCO_UNIX -UM_XENIX \ -DNNTP_INEWS_GATEWAY=\"$(NNTP_INEWS_GATEWAY)\" \ -DNNTP_INEWS_DOMAIN=\"$(NNTP_INEWS_DOMAIN)\" \ -DNNTP_DEFAULT_SERVER=\"$(NNTP_DEFAULT_SERVER)\" \ -DLIBDIR=\"$(LIBDIR)\" \ -DSPOOLDIR=\"$(SPOOLDIR)\" \ -DNOVROOTDIR=\"$(NOVROOTDIR)\"' \ LIBS="-lcurses -lgen -lc_s $(INN_NNTPLIB)" \ EXE=tin linkit # For SNI Sinix sinix: @echo "Compiling $(EXE) v$(VER) for SNI Sinix..." @$(MAKE) CC=$(CC) CFLAGS='$(COPTS) \ -DNNTP_INEWS_GATEWAY="\\"$(NNTP_INEWS_GATEWAY)\\" \ -DNNTP_INEWS_DOMAIN="\\"$(NNTP_INEWS_DOMAIN)\\" \ -DNNTP_DEFAULT_SERVER=\"$(NNTP_DEFAULT_SERVER)\" \ -DLIBDIR=\\"$(LIBDIR)\\" \ -DSPOOLDIR=\\"$(SPOOLDIR)\\" \ -DNOVROOTDIR=\\"$(NOVROOTDIR)\\"' \ LIBS="-lcurses $(INN_NNTPLIB)" \ EXE=tin linkit # For System V # NETLIBS="-lnet -lnsl_s" \ # sysv: @echo "Compiling $(EXE) v$(VER) for System V..." @$(MAKE) CC=$(CC) CFLAGS='$(COPTS) -DSYSV \ -DNNTP_INEWS_GATEWAY=\"$(NNTP_INEWS_GATEWAY)\" \ -DNNTP_INEWS_DOMAIN=\"$(NNTP_INEWS_DOMAIN)\" \ -DNNTP_DEFAULT_SERVER=\"$(NNTP_DEFAULT_SERVER)\" \ -DLIBDIR=\"$(LIBDIR)\" \ -DSPOOLDIR=\"$(SPOOLDIR)\" \ -DNOVROOTDIR=\"$(NOVROOTDIR)\"' \ LIBS="-lcurses -ltermcap $(INN_NNTPLIB)" \ EXE=tin linkit # For System V Release 4 # NETLIBS="-lnsl -lsocket" \ # sysvr4: @echo "Compiling $(EXE) v$(VER) for System V Release 4..." @$(MAKE) CC=$(CC) CFLAGS='$(COPTS) -DSVR4 \ -DNNTP_INEWS_GATEWAY=\"$(NNTP_INEWS_GATEWAY)\" \ -DNNTP_INEWS_DOMAIN=\"$(NNTP_INEWS_DOMAIN)\" \ -DNNTP_DEFAULT_SERVER=\"$(NNTP_DEFAULT_SERVER)\" \ -DLIBDIR=\"$(LIBDIR)\" \ -DSPOOLDIR=\"$(SPOOLDIR)\" \ -DNOVROOTDIR=\"$(NOVROOTDIR)\"' \ LIBS="-lcurses -ltermcap $(INN_NNTPLIB)" \ EXE=tin linkit # For NCR Tower # NETLIBS="-lnet -lnsl_s" \ # tower: @echo "Compiling $(EXE) v$(VER) for NCR Tower..." @$(MAKE) CC=$(CC) CFLAGS='$(COPTS) -DSYSV -DNCR -DISTRING \ -DNNTP_INEWS_GATEWAY=\"$(NNTP_INEWS_GATEWAY)\" \ -DNNTP_INEWS_DOMAIN=\"$(NNTP_INEWS_DOMAIN)\" \ -DNNTP_DEFAULT_SERVER=\"$(NNTP_DEFAULT_SERVER)\" \ -DLIBDIR=\"$(LIBDIR)\" \ -DSPOOLDIR=\"$(SPOOLDIR)\" \ -DNOVROOTDIR=\"$(NOVROOTDIR)\"' \ LIBS="-lcurses -ltermcap $(INN_NNTPLIB)" \ EXE=tin linkit # For Xenix 386 # NETLIBS="-lsocket" \ # xenix: @echo "Compiling $(EXE) v$(VER) for Xenix 386..." @$(MAKE) CC=$(CC) CFLAGS='-c -Zi -DSYSV \ -DNNTP_INEWS_GATEWAY="\\"$(NNTP_INEWS_GATEWAY)\\" \ -DNNTP_INEWS_DOMAIN="\\"$(NNTP_INEWS_DOMAIN)\\" \ -DNNTP_DEFAULT_SERVER="\\"$(NNTP_DEFAULT_SERVER)\\" \ -DLIBDIR=\\"$(LIBDIR)\\" \ -DSPOOLDIR=\\"$(SPOOLDIR)\\" \ -DNOVROOTDIR=\\"$(NOVROOTDIR)\\"' \ LIBS="-lcurses -ltinfo -lx $(INN_NNTPLIB)" \ LFLAGS=-Zi EXE=tin linkit # !!! THE FOLLOWING ARE SITE SPECIFIC - IGNORE !!! ccenter_obj: @echo "Compiling a CL target for SUN01 with NNTP ONLY..." #setopt program_name $(EXE) #setopt sys_load_flags -Dsun -Dsparc -I/usr/include -I. -L/usr/lib -lcurses -ltermcap #load -c -g -DBSD -DNNTP_ABLE -DNNTP_ONLY -lcurses -ltermcap $(CFILES) #link # @$(MAKE) CC=gcc CFLAGS='-c -O2 -Wall -DSYSV -DHAVE_ISPELL -DNNTP_ABLE -DDONT_HAVE_NNTP_EXTS -DNNTP_INEWS_GATEWAY=\"$(NNTP_INEWS_GATEWAY)\" -DNNTP_INEWS_DOMAIN=\"$(NNTP_INEWS_DOMAIN)\" -DDEBUG' \ # anl433: @echo "Compiling $(EXE) v$(VER) for ANL433 with NNTP..." @$(MAKE) CC=gcc CFLAGS='-c -O -Wall -DSYSV -DHAVE_MAIL_HANDLING -DHAVE_ISPELL -DNNTP_ABLE -DDEBUG \ -DDONT_HAVE_NNTP_EXTS \ -DNNTP_INEWS_GATEWAY=\"$(NNTP_INEWS_GATEWAY)\" \ -DNNTP_INEWS_DOMAIN=\"$(NNTP_INEWS_DOMAIN)\" \ -DNNTP_DEFAULT_SERVER=\"$(NNTP_DEFAULT_SERVER)\" \ -DLIBDIR=\"$(LIBDIR)\" \ -DSPOOLDIR=\"$(SPOOLDIR)\" \ -DNOVROOTDIR=\"$(NOVROOTDIR)\"' \ LIBS="-lcurses -ltermcap $(INN_NNTPLIB)" \ NETLIBS="-linet -lnsl_s" \ EXE=tin linkit daemon: @echo "Compiling $(EXE) v$(VER) for ANL433 with INDEX DAEMON..." @$(MAKE) CC=gcc CFLAGS='-c -O2 -DSYSV -DINDEX_DAEMON -DDEBUG' \ EXE=$(EXED) linkit dg01: @echo "Compiling $(EXE) v$(VER) for DG01 with NNTP ONLY..." @$(MAKE) CC=$(CC) CFLAGS='$(COPTS) -DBSD -DNNTP_ONLY -DDEBUG \ -DNNTP_INEWS_GATEWAY=\"$(NNTP_INEWS_GATEWAY)\" \ -DNNTP_INEWS_DOMAIN=\"$(NNTP_INEWS_DOMAIN)\" \ -DNNTP_DEFAULT_SERVER=\"$(NNTP_DEFAULT_SERVER)\" \ -DLIBDIR=\"$(LIBDIR)\" \ -DSPOOLDIR=\"$(SPOOLDIR)\" \ -DNOVROOTDIR=\"$(NOVROOTDIR)\"' \ LIBS="-lcurses -ltermcap $(INN_NNTPLIB)" \ EXE=tin linkit idefix: @echo "Compiling $(EXE) v$(VER) for IDEFIX with NNTP ONLY..." @$(MAKE) CC=$(CC) CFLAGS='$(COPTS) -DSYSV -DSCO_UNIX -UM_XENIX -DNNTP_ONLY \ -DNNTP_INEWS_GATEWAY=\"$(NNTP_INEWS_GATEWAY)\" \ -DNNTP_INEWS_DOMAIN=\"$(NNTP_INEWS_DOMAIN)\" \ -DNNTP_DEFAULT_SERVER=\"$(NNTP_DEFAULT_SERVER)\" \ -DLIBDIR=\"$(LIBDIR)\" \ -DSPOOLDIR=\"$(SPOOLDIR)\" \ -DNOVROOTDIR=\"$(NOVROOTDIR)\"' \ NETLIBS="-lnsl_s -lsocket" \ LIBS="-lcurses -lgen -lc_s $(INN_NNTPLIB)" \ EXE=tin linkit os2unix: @echo "Compiling $(EXE) v$(VER) for OS2UNIX with NNTP ONLY..." @$(MAKE) CC=$(CC) CFLAGS='$(COPTS) -DSYSV -DNNTP_ONLY -DDEBUG \ -DNNTP_INEWS_GATEWAY=\"$(NNTP_INEWS_GATEWAY)\" \ -DNNTP_INEWS_DOMAIN=\"$(NNTP_INEWS_DOMAIN)\" \ -DNNTP_DEFAULT_SERVER=\"$(NNTP_DEFAULT_SERVER)\" \ -DLIBDIR=\"$(LIBDIR)\" \ -DSPOOLDIR=\"$(SPOOLDIR)\" \ -DNOVROOTDIR=\"$(NOVROOTDIR)\"' \ LIBS="-lcurses -ltermcap -lx $(INN_NNTPLIB)" \ NETLIBS="-linet -lnsl_s" \ EXE=tin linkit mx331: @echo "Compiling $(EXE) v$(VER) for MX331 with NNTP ONLY..." @$(MAKE) CC=$(CC) CFLAGS='$(COPTS) -DSYSV -DNNTP_ONLY \ -DNNTP_INEWS_GATEWAY=\"$(NNTP_INEWS_GATEWAY)\" \ -DNNTP_INEWS_DOMAIN=\"$(NNTP_INEWS_DOMAIN)\" \ -DNNTP_DEFAULT_SERVER=\"$(NNTP_DEFAULT_SERVER)\" \ -DLIBDIR=\"$(LIBDIR)\" \ -DSPOOLDIR=\"$(SPOOLDIR)\" \ -DNOVROOTDIR=\"$(NOVROOTDIR)\"' \ LIBS="-lcurses $(INN_NNTPLIB)" \ EXE=tin linkit mx351: @echo "Compiling $(EXE) v$(VER) for MX351 with NNTP ONLY..." @$(MAKE) CC=$(CC) CFLAGS='$(COPTS) -DSVR4 -DNNTP_ONLY \ -DNNTP_INEWS_GATEWAY=\"$(NNTP_INEWS_GATEWAY)\" \ -DNNTP_INEWS_DOMAIN=\"$(NNTP_INEWS_DOMAIN)\" \ -DNNTP_DEFAULT_SERVER=\"$(NNTP_DEFAULT_SERVER)\" \ -DLIBDIR=\"$(LIBDIR)\" \ -DSPOOLDIR=\"$(SPOOLDIR)\" \ -DNOVROOTDIR=\"$(NOVROOTDIR)\"' \ NETLIBS="-lnsl -lsocket" \ LIBS="-lcurses -ltermlib $(INN_NNTPLIB)" \ EXE=tin linkit sparc10_1: @echo "Compiling $(EXE) v$(VER) for SPARC10 with NNTP ONLY..." @$(MAKE) CC=$(CC) CFLAGS='$(COPTS) -DBSD -DNNTP_ONLY \ -DNNTP_INEWS_GATEWAY=\"$(NNTP_INEWS_GATEWAY)\" \ -DNNTP_INEWS_DOMAIN=\"$(NNTP_INEWS_DOMAIN)\" \ -DNNTP_DEFAULT_SERVER=\"$(NNTP_DEFAULT_SERVER)\" \ -DLIBDIR=\"$(LIBDIR)\" \ -DSPOOLDIR=\"$(SPOOLDIR)\" \ -DNOVROOTDIR=\"$(NOVROOTDIR)\"' \ LIBS="-lcurses -ltermcap $(INN_NNTPLIB)" \ EXE=tin linkit sparc10cd: @echo "Compiling $(EXE) v$(VER) for SPARC10 with CDROM ABLE..." @$(MAKE) CC=$(CC) CFLAGS='$(COPTS) -DBSD -DCDROM_ABLE -DDEBUG' \ NNTPLIB="$(CDLIB)" \ LIBS="-lcurses -ltermcap $(INN_NNTPLIB)" \ EXE=cdtin linkit linkit: $(OFILES) @echo "Linking $(EXE) v$(VER)..." $(LD) $(LFLAGS) -o $(EXE) $(OFILES) $(NNTPLIB) $(NETLIBS) $(LIBS) @ls -l $(EXE) install: @echo "Installing $(EXE) v$(VER)..." @$(STRIP) $(EXE) @-$(STRIP2) $(EXE) @-mv $(EXE) $(INS_BINARY_DIR) @-rm $(INS_BINARY_DIR)/r$(EXE) @ln $(INS_BINARY_DIR)/$(EXE) $(INS_BINARY_DIR)/r$(EXE) @chmod 755 $(INS_BINARY_DIR)/$(EXE) @ls -l $(INS_BINARY_DIR)/$(EXE) $(INS_BINARY_DIR)/r$(EXE) @cp $(EXE).1 $(INS_MANUAL_DIR)$(INS_MANUAL_EXT)/$(EXE).$(INS_MANUAL_EXT) @chmod 644 $(INS_MANUAL_DIR)$(INS_MANUAL_EXT)/$(EXE).$(INS_MANUAL_EXT) install_setuid: @echo "Installing SETUID $(EXE) v$(VER)..." @$(STRIP) $(EXE) @-$(STRIP2) $(EXE) @-mv $(EXE) $(INS_BINARY_DIR) @chown news $(INS_BINARY_DIR)/$(EXE) @chgrp news $(INS_BINARY_DIR)/$(EXE) @-rm $(INS_BINARY_DIR)/r$(EXE) @ln $(INS_BINARY_DIR)/$(EXE) $(INS_BINARY_DIR)/r$(EXE) @su news -c "chmod 6755 $(INS_BINARY_DIR)/$(EXE)" @ls -l $(INS_BINARY_DIR)/$(EXE) $(INS_BINARY_DIR)/r$(EXE) @cp $(EXE).1 $(INS_MANUAL_DIR)$(INS_MANUAL_EXT)/$(EXE).$(INS_MANUAL_EXT) @chmod 644 $(INS_MANUAL_DIR)$(INS_MANUAL_EXT)/$(EXE).$(INS_MANUAL_EXT) install_daemon: @echo "Installing index daemon $(EXED) v$(VER)..." @$(STRIP) $(EXED) @-$(STRIP2) $(EXED) @-mv $(EXED) $(INS_DAEMON_DIR) @chown news $(INS_DAEMON_DIR)/$(EXED) @chmod 0755 $(INS_DAEMON_DIR)/$(EXED) @ls -l $(INS_DAEMON_DIR)/$(EXED) proto: @echo "Generating function prototypes for proto.h..." @echo "#if __STDC__" > PROTO.H @echo " " >> PROTO.H @cproto -e $(CFILES) >> PROTO.H @echo " " >> PROTO.H @echo "#else" >> PROTO.H @echo " " >> PROTO.H @cproto -e -f1 $(CFILES) >> PROTO.H @echo " " >> PROTO.H @echo "#endif" >> PROTO.H @-mv PROTO.H proto.h nroff: @echo "Creating nroff man page..." @-$(ROFF) $(EXE).1 > $(EXE).nrf manifest: @echo "Creating MANIFEST..." @echo "MANIFEST for $(PROJECT)-$(VER) (`date`)" > MANIFEST @echo "----------------------------------------------------" >> MANIFEST @wc -c $(ALL_FILES) >> MANIFEST shar: @echo "Generating shell archive..." @$(MAKE) nroff @$(MAKE) manifest @$(MAKE) chmod @shar -a -F -L75 -n $(PROJECT)-$(VER) -s $(MAIL_ADDR) \ -o ../$(PROJECT)-$(VER) $(ALL_FILES) uuencode: @$(MAKE) tar @echo "Uuencoding $(PROJECT).tar.Z..." @uuencode $(PROJECT).tar.Z $(PROJECT).tar.Z > $(PROJECT).tar.Z.uue @ls -l $(PROJECT).tar.Z.uue diff: @echo "Generating diffs against $(PROJECT)-$(BASE_VER)..." @$(MAKE) nroff @$(MAKE) manifest @$(MAKE) chmod @-mv -f $(PROJECT)-$(VER).diff $(PROJECT)-$(VER).diff- @-diff -rus ../$(BASE_VER) . > $(PROJECT)-$(VER).diff # @-diff -rcs ../$(BASE_VER) . > $(PROJECT)-$(VER).diff @ls -l $(PROJECT)-$(VER).diff patch: @$(MAKE) diff @echo "Generating patch against $(PROJECT)-$(BASE_VER)..." @-mv $(PROJECT)-$(VER).diff $(PROJECT)-$(VER).patch @shar -a -n $(PROJECT)-$(VER) -s $(MAIL_ADDR) -L75 \ -o ../patch-$(VER) $(PROJECT)-$(VER).patch @ls -l ../patch-$(VER).* tar: @echo "Generating compressed tar file..." @-rm $(PROJECT).tar $(PROJECT).tar.Z > /dev/null 2>&1 $(MAKE) chmod @tar cvf $(PROJECT).tar $(ALL_FILES) @echo "Compressing $(PROJECT).tar..." @compress $(PROJECT).tar @ls -l $(PROJECT).tar.Z gtar: @echo "Generating gzipped tar file..." @-rm $(PROJECT).t $(PROJECT).t.[gz] > /dev/null 2>&1 $(MAKE) chmod @tar cvf $(PROJECT).t $(ALL_FILES) @echo "Gzipping $(PROJECT).t..." @gzip $(PROJECT).t @ls -l $(PROJECT).t.[gz] ftptar: @echo "Creating FTP tar file with a directory of $(PROJECT)-$(VER)..." @-mkdir $(PROJECT)-$(VER) @chmod 755 $(PROJECT)-$(VER) @$(MAKE) chmod @cp $(ALL_FILES) $(PROJECT)-$(VER) @tar cvf $(PROJECT)-$(VER).tar $(PROJECT)-$(VER) @echo "Compressing $(PROJECT)-$(VER).tar..." @compress $(PROJECT)-$(VER).tar @ls -l $(PROJECT)-$(VER).tar.Z chmod: @chmod 644 $(ALL_FILES) zip: @echo "Generating zip archive file..." @-rm $(PROJECT).zip > /dev/null 2>&1 @zip $(PROJECT).zip $(ALL_FILES) @ls -l $(PROJECT).zip zoo: @echo "Generating zoo archive file..." @-rm $(PROJECT).zoo > /dev/null 2>&1 @zoo ah $(PROJECT).zoo $(ALL_FILES) @ls -l $(PROJECT).zoo tags: @echo "Generating tags (results in ./tags)..." @-rm tags @ctags $(HFILES) patchlev.h $(CFILES) lint: @echo "Linting source (results in ./LINT)..." @lint $(LINTFLAGS) -DNNTP_ABLE $(CFILES) > LINT clean: @echo "Cleaning..." -/bin/rm -f $(OFILES) clobber: @echo "Clobbering..." /bin/rm -f $(OFILES) $(EXE) tags cflow: @echo "Creating cflow for $(PROJECT)..." @cflow $(CFILES) > cflow.$(PROJECT) & cscope: @echo "Creating cscope database $(PROJECT)..." @cscope $(ALL_FILES) man: @echo "Printing $(EXE) manual..." @$(ROFF) $(EXE).1 | lpr print: for FILE in $(HFILES) patchlev.h $(CFILES) $(SUPPORT); do \ echo "Printing $$FILE..."; \ a2ps $$FILE | lpr; \ done actived: @echo "Compiling actived for AmigaDOS (Manx-C 5.2)..." $(CC) CFLAGS=$(AMIGA_COPTS) actived $(LD) actived -lc active.o: active.c $(HFILES) amiga.o: amiga.c $(HFILES) art.o: art.c $(HFILES) curses.o: curses.c $(HFILES) debug.o: debug.c $(HFILES) envarg.o: envarg.c $(HFILES) feed.o: feed.c $(HFILES) getline.o: getline.c $(HFILES) group.o: group.c $(HFILES) hashstr.o: hashstr.c $(HFILES) help.o: help.c $(HFILES) inews.o: inews.c $(HFILES) init.o: init.c $(HFILES) kill.o: kill.c $(HFILES) lang.o: lang.c $(HFILES) mail.o: mail.c $(HFILES) patchlev.h main.o: main.c $(HFILES) patchlev.h memory.o: memory.c $(HFILES) misc.o: misc.c $(HFILES) newsrc.o: newsrc.c $(HFILES) nntplib.o: nntplib.c $(HFILES) open.o: open.c $(HFILES) patchlev.h os_2.o: os_2.c $(HFILES) page.o: page.c $(HFILES) parsdate.o: parsdate.y $(HFILES) post.o: post.c $(HFILES) patchlev.h prompt.o: prompt.c $(HFILES) rcfile.o: rcfile.c $(HFILES) save.o: save.c $(HFILES) screen.o: screen.c $(HFILES) search.o: search.c $(HFILES) select.o: select.c $(HFILES) sigfile.o: sigfile.c $(HFILES) signal.o: signal.c $(HFILES) spooldir.o: spooldir.c $(HFILES) strftime.o: strftime.c $(HFILES) thread.o: thread.c $(HFILES) wildmat.o: wildmat.c win32.o: win32.c win32.h xref.o: xref.c $(HFILES) ð*[SRC.TIN-1_22]$M$AKEFILE.AMI;1+,f.//€ 4o-d0@î123KÿPWO56 yt…—7ÐU^1—89€]V‚—G/€HªJÿ CC = sc LD = $(CC) LFLAGS = link startup=cres EXE = tin MAKE = smake VER = 1.21 LIBS = CFLAGS = optimize stringmerge nostkchk parm=register optinlocal gst=tin.gst \ DEFINE M_AMIGA DEFINE SYSV DEFINE NO_SHELL_ESCAPE DEFINE NO_PIPING \ DEFINE SLOW_SCREEN_UPDATE DEFINE AMIGA_BBS DEFINE LIBDIR="uulib:" \ DEFINE DONT_LOG_USER DEFINE SPOOLDIR="uunews:" HFILES1 = config.h tin.h extern.h nntplib.h proto.h amiga.h os_2.h win32.h HFILES = tin.gst $(HFILES1) CFILES = active.c amiga.c art.c curses.c debug.c envarg.c feed.c getline.c \ group.c hashstr.c help.c inews.c init.c kill.c lang.c mail.c \ main.c memory.c misc.c newsrc.c nntplib.c open.c os_2.c page.c \ parsdate.y post.c prompt.c rcfile.c save.c screen.c search.c \ select.c sigfile.c signal.c spooldir.c strftime.c thread.c \ wildmat.c win32.c xref.c OFILES = active.o amiga.o art.o curses.o debug.o envarg.o feed.o getline.o \ group.o hashstr.o help.o inews.o init.o kill.o lang.o mail.o \ main.o memory.o misc.o newsrc.o nntplib.o open.o os_2.o page.o \ parsdate.o post.o prompt.o rcfile.o save.o screen.o search.o \ select.o sigfile.o signal.o spooldir.o strftime.o thread.o \ wildmat.o win32.o xref.o .c.o: $(CC) $(CFLAGS) $*.c tin: $(OFILES) @echo "Linking $(EXE) v$(VER)..." $(LD) $(LFLAGS) pname=$(EXE) $(OFILES) $(LIBS) @ls -l $(EXE) actived: @echo "Compiling actived for AmigaDOS ..." $(CC) CFLAGS=$(AMIGA_COPTS) actived $(LD) actived $(LIBS) tin.gst: $(HFILES1) $(CC) $(CFLAGS) makegst=tin.gst gst.h active.o: active.c $(HFILES) amiga.o: amiga.c $(HFILES) art.o: art.c $(HFILES) curses.o: curses.c $(HFILES) debug.o: debug.c $(HFILES) envarg.o: envarg.c $(HFILES) feed.o: feed.c $(HFILES) getline.o: getline.c $(HFILES) group.o: group.c $(HFILES) hashstr.o: hashstr.c $(HFILES) help.o: help.c $(HFILES) inews.o: inews.c $(HFILES) init.o: init.c $(HFILES) kill.o: kill.c $(HFILES) lang.o: lang.c $(HFILES) mail.o: mail.c $(HFILES) patchlev.h main.o: main.c $(HFILES) patchlev.h memory.o: memory.c $(HFILES) misc.o: misc.c $(HFILES) newsrc.o: newsrc.c $(HFILES) nntplib.o: nntplib.c $(HFILES) open.o: open.c $(HFILES) patchlev.h os_2.o: os_2.c $(HFILES) page.o: page.c $(HFILES) parsdate.o: parsdate.y $(HFILES) post.o: post.c $(HFILES) patchlev.h prompt.o: prompt.c $(HFILES) rcfile.o: rcfile.c $(HFILES) save.o: save.c $(HFILES) screen.o: screen.c $(HFILES) search.o: search.c $(HFILES) select.o: select.c $(HFILES) sigfile.o: sigfile.c $(HFILES) signal.o: signal.c $(HFILES) spooldir.o: spooldir.c $(HFILES) strftime.o: strftime.c $(HFILES) thread.o: thread.c $(HFILES) wildmat.o: wildmat.c win32.o: win32.c win32.h xref.o: xref.c $(HFILES) ð*[SRC.TIN-1_22]$M$AKEFILE.BCC;1+,g. //€ 4 -d0@î123KÿPWO 56`V¨t…—7ÐU^1—89€]V‚—G/€HªJÿ#============================================================= # # TIN.MAK - Makefile for project C:\tin\tin.prj # Created on 05/30/93 at 20:25 # #============================================================= .AUTODEPEND #============================================================= # Translator Definitions #============================================================= CC = bcc +TIN.CFG TASM = tasm.exe TLIB = tlib.exe TLINK = tlink LINK = link386 RC = brcc.exe RB = rc.exe LIBPATH = C:\BCOS2\LIB INCLUDEPATH = C:\BCOS2\INCLUDE;c:\curses;c:\tcpip\include;c:\tin #============================================================= # Implicit Rules #============================================================= .c.obj: $(CC) -c {$< } .cpp.obj: $(CC) -c {$< } .asm.obj: $(TASM) -Mx $*.asm,$*.obj .rc.res: $(RC) -r $*.rc #============================================================= # List Macros #============================================================= EXE_DEPENDENCIES = \ \curses\curseso.lib \ parsdate.obj \ curses.obj \ xref.obj \ win32.obj \ wildmat.obj \ thread.obj \ strftime.obj \ spooldir.obj \ signal.obj \ sigfile.obj \ select.obj \ search.obj \ screen.obj \ save.obj \ rcfile.obj \ prompt.obj \ post.obj \ page.obj \ os_2.obj \ open.obj \ nntplib.obj \ newsrc.obj \ misc.obj \ memory.obj \ main.obj \ mail.obj \ lang.obj \ kill.obj \ init.obj \ inews.obj \ help.obj \ hashstr.obj \ group.obj \ getline.obj \ feed.obj \ envarg.obj \ debug.obj \ art.obj \ active.obj #============================================================= # Explicit Rules #============================================================= tin.exe: tin.cfg $(EXE_DEPENDENCIES) $(TLINK) /s /c /Toe /ap /L$(LIBPATH) @&&| C:\BCOS2\LIB\C02.OBJ+ parsdate.obj+ curses.obj+ xref.obj+ win32.obj+ wildmat.obj+ thread.obj+ strftime.obj+ spooldir.obj+ signal.obj+ sigfile.obj+ select.obj+ search.obj+ screen.obj+ save.obj+ rcfile.obj+ prompt.obj+ post.obj+ page.obj+ os_2.obj+ open.obj+ nntplib.obj+ newsrc.obj+ misc.obj+ memory.obj+ main.obj+ mail.obj+ lang.obj+ kill.obj+ init.obj+ inews.obj+ help.obj+ hashstr.obj+ group.obj+ getline.obj+ feed.obj+ envarg.obj+ debug.obj+ art.obj+ active.obj tin,tin C:\BCOS2\LIB\C2.LIB+ C:\BCOS2\LIB\OS2.LIB+ c:\curses\curseso.lib+ C:\TCPIP\LIB\TCPIPDLL.LIB | #============================================================= # Individual File Dependencies #============================================================= parsdate.obj: tin.cfg parsdate.c curses.obj: tin.cfg curses.c xref.obj: tin.cfg xref.c win32.obj: tin.cfg win32.c wildmat.obj: tin.cfg wildmat.c thread.obj: tin.cfg thread.c strftime.obj: tin.cfg strftime.c spooldir.obj: tin.cfg spooldir.c signal.obj: tin.cfg signal.c sigfile.obj: tin.cfg sigfile.c select.obj: tin.cfg select.c search.obj: tin.cfg search.c screen.obj: tin.cfg screen.c save.obj: tin.cfg save.c rcfile.obj: tin.cfg rcfile.c prompt.obj: tin.cfg prompt.c post.obj: tin.cfg post.c page.obj: tin.cfg page.c os_2.obj: tin.cfg os_2.c open.obj: tin.cfg open.c nntplib.obj: tin.cfg nntplib.c newsrc.obj: tin.cfg newsrc.c misc.obj: tin.cfg misc.c memory.obj: tin.cfg memory.c main.obj: tin.cfg main.c mail.obj: tin.cfg mail.c lang.obj: tin.cfg lang.c kill.obj: tin.cfg kill.c init.obj: tin.cfg init.c inews.obj: tin.cfg inews.c help.obj: tin.cfg help.c hashstr.obj: tin.cfg hashstr.c group.obj: tin.cfg group.c getline.obj: tin.cfg getline.c feed.obj: tin.cfg feed.c envarg.obj: tin.cfg envarg.c debug.obj: tin.cfg debug.c art.obj: tin.cfg art.c active.obj: tin.cfg active.c pwd.obj: tin.cfg pwd.c #============================================================= # Compiler Configuration File #============================================================= tin.cfg: copy &&| -L$(LIBPATH) -I$(INCLUDEPATH) -vi- -DM_OS2 -DNNTP_ABLE -DDONT_REREAD_ACTIVE_FILE -DDEBUG -w-par -w-pro -w-pia -w-aus -w-rvl -w-rch | tin.cfg à,'5±~ TIN-1_22.BCKhd[SRC.TIN-1_22]$M$AKEFILE.ICC;1 øð*[SRC.TIN-1_22]$M$AKEFILE.ICC;1+,h.//€ 4ÿ-d0@î123KÿPWO56€Ëàt…—7€fî^1—89€]V‚—G/€HªJÿ*# IBM Developer's Workframe/2 Make File Creation run at 22:01:04 on 06/04/93 # Make File Creation run in directory: # C:\TIN; .SUFFIXES: .SUFFIXES: .c tin.exe: \ active.OBJ \ art.OBJ \ curses.OBJ \ debug.OBJ \ envarg.OBJ \ feed.OBJ \ getline.OBJ \ group.OBJ \ hashstr.OBJ \ help.OBJ \ inews.OBJ \ init.OBJ \ kill.OBJ \ lang.OBJ \ mail.OBJ \ main.OBJ \ memory.OBJ \ misc.OBJ \ newsrc.OBJ \ nntplib.OBJ \ open.OBJ \ os_2.OBJ \ page.OBJ \ parsdate.OBJ \ post.OBJ \ prompt.OBJ \ rcfile.OBJ \ save.OBJ \ screen.OBJ \ search.OBJ \ select.OBJ \ sigfile.OBJ \ signal.OBJ \ spooldir.OBJ \ strftime.OBJ \ thread.OBJ \ wildmat.OBJ \ win32.OBJ \ xref.OBJ \ MAKEFILE @REM @< active[] */ int reread_active_file = FALSE; int active_index = -1; /* * Compare two pointers to "group_t" structures - used in qsort. */ int cmp_group_p (group1, group2) group_p *group1; group_p *group2; { return (strcmp ((*group1)->name, (*group2)->name)); } /* * Compare two pointers to "notify_t" structures - used in qsort. */ int cmp_notify_p (notify1, notify2) notify_p *notify1; notify_p *notify2; { return (strcmp ((*notify1)->name, (*notify2)->name)); } /* * Get default array size for active[] from environment (AmigaDOS) * or just return the standard default. */ int get_active_num () { #ifdef ENV_VAR_GROUPS char *ptr; int num; ptr = getenv (ENV_VAR_GROUPS); if (ptr != (char *) 0) { num = atoi (ptr); return (num ? num : DEFAULT_ACTIVE_NUM); } #endif return DEFAULT_ACTIVE_NUM; } /* * Resync active file when SIGALRM signal received that * is triggered by alarm (reread_active_file_secs) call. */ void resync_active_file () { char old_group[PATH_LEN]; if (reread_active_file) { if (cur_groupnum >= 0 && group_top) { strcpy (old_group, active[my_group[cur_groupnum]].name); } else { old_group[0] = '\0'; } free_active_arrays (); max_active = get_active_num (); expand_active (); read_mail_active_file (); read_news_active_file (); read_attributes_file (); read_mailgroups_file (); read_newsgroups_file (); if (! read_cmd_line_groups ()) { read_newsrc (TRUE); toggle_my_groups (show_only_unread_groups, old_group); } set_groupname_len (FALSE); set_alarm_signal (); mail_setup (); group_selection_page (); } } /* * Find group name in active[] array and return index otherwise -1 */ int find_group_index (group) char *group; { int i = -1; long h; h = hash_groupname (group); i = group_hash[h]; /* * hash linked list chaining */ while (i >= 0) { if (strncmp (group, active[i].name, strlen (active[i].name)) == 0) { return (i); } i = active[i].next; } return (-1); } /* * parse line from news or mail active files */ int parse_active_line (line, max, min, moderated) char *line; long *max; long *min; char *moderated; { char *p, *q, *r; if (line[0] == '#' || line[0] == '\n') { return FALSE; } for (p = line; *p && *p != ' ' && *p != '\n'; p++) { continue; } if (*p != ' ') { error_message (txt_bad_active_file, line); return FALSE; } *p++ = '\0'; for (q = p; *q && *q != ' '; q++) { continue; } if (*q != ' ') { error_message (txt_bad_active_file, line); return FALSE;; } *q++ = '\0'; for (r = q; *r && *r != ' '; r++) { continue; } if (*r != ' ') { error_message (txt_bad_active_file, line); return FALSE; } *r++ = '\0'; if (*r) { strcpy (moderated, r); r = (char *) strchr (moderated, '\n'); if (*r) { *r = '\0'; } } *max = (long) atol (p); *min = (long) atol (q); return TRUE; } int parse_newsrc_active_line (fp, max, min, moderated, group) FILE *fp; long *max; long *min; char *moderated; char *group; { char *ptr, *s; char line[NNTP_STRLEN]; char buf[LEN]; while (fgets (buf, sizeof (buf), fp) != (char *) 0) { ptr = my_strpbrk (buf, ":!"); if (! ptr || *ptr != ':') { continue; } *ptr = '\0'; sprintf (line, "group %s", buf); put_server (line); debug_nntp ("parse_newsrc_active_line", buf); get_server (line, sizeof (line)); debug_nntp ("parse_newsrc_active_line", line); ptr = strchr (line, ' '); if (! ptr) { continue; } *ptr++ = '\0'; if (atoi (line) != OK_GROUP) { continue; } ptr = strchr (s=ptr, ' '); if (! ptr) { continue; } *ptr++ = '\0'; /* s now points to num of articles */ ptr = strchr (s=ptr, ' '); if (! ptr) { continue; } *ptr++ = '\0'; /* s now points to minimum article */ *min = atol (s); ptr = strchr (s=ptr, ' '); if (! ptr) { continue; } *ptr++ = '\0'; /* s now points to maximum article */ *max = atol (s); strcpy (group, ptr); strcpy (moderated, "n"); return TRUE; } return FALSE; } /* * Load the news active file into active[] and create copy * of active ~/.tin/active */ void read_news_active_file () { FILE *fp; char buf[LEN]; char moderated[PATH_LEN]; int i; long h, min, max; if ((update && update_fork) || ! update) { wait_message (txt_reading_news_active_file); } if (newsrc_active) { if ((fp = fopen (newsrc, "r")) == NULL) { if (cmd_line) { fputc ('\n', stderr); } error_message (txt_cannot_open, news_active_file); tin_done(1); } } else { if ((fp = open_news_active_fp ()) == NULL) { if (compiled_with_nntp) { sprintf (msg, txt_cannot_open_active_file, news_active_file, progname); error_message (msg, ""); } else { if (cmd_line) { fputc ('\n', stderr); } error_message (txt_cannot_open, news_active_file); } tin_done (1); } } if (num_active == -1) { num_active = 0; for (i = 0; i < TABLE_SIZE; i++) { group_hash[i] = -1; } } strcpy (moderated, "y"); while (1) { if (newsrc_active) { if (! parse_newsrc_active_line (fp, &max, &min, moderated, buf)) { break; } } else { if (fgets (buf, sizeof (buf), fp) == NULL) { break; } if (! parse_active_line (buf, &max, &min, moderated)) { continue; } } /* * Don't load group into active[] from active file if * 'x' junked group * '=' aliased group */ if (moderated[0] != 'x' && moderated[0] != '=') { /* * Load group into group hash table */ if (num_active >= max_active) { expand_active (); } h = hash_groupname (buf); if (group_hash[h] == -1) { group_hash[h] = num_active; } else { /* hash linked list chaining */ for (i=group_hash[h]; active[i].next >= 0; i=active[i].next) { if (strcmp(active[i].name, buf) == 0) { goto read_news_active_continue; /* kill dups */ } } if (strcmp(active[i].name, buf) == 0) goto read_news_active_continue; active[i].next = num_active; } /* * Load group info. */ active[num_active].type = GROUP_TYPE_NEWS; active[num_active].name = str_dup (buf); active[num_active].spooldir = spooldir; active[num_active].description = (char *) 0; active[num_active].max = max; active[num_active].min = min; active[num_active].moderated = moderated[0]; active[num_active].next = -1; /* hash chaining */ active[num_active].my_group = UNSUBSCRIBED; /* not in my_group[] yet */ active[num_active].unread = 0; active[num_active].newsrcmax = max; active[num_active].newsrcmin = min; active[num_active].newsrcsize = 0; active[num_active].newsrcupdate = FALSE; active[num_active].newsrc = NULL; #ifdef INDEX_DAEMON active[num_active].last_updated_time = 0L; #endif num_active++; } read_news_active_continue:; } fclose (fp); /* * exit if active file is empty */ if (! num_active) { error_message (txt_active_file_is_empty, news_active_file); tin_done (1); } if ((cmd_line && ! update && ! verbose) || (update && update_fork)) { wait_message ("\n"); } check_for_any_new_groups (); } /* * create ~/.tin/active if it does not exist (local news only) */ void backup_active (create) int create; { char buf[PATH_LEN]; FILE *fp; register int i; struct stat sb; joinpath (buf, rcdir, "active"); if (create) { if (stat (buf, &sb) != -1) { return; } } #ifdef VMS if ((fp = fopen (buf, "w", "fop=cif")) != (FILE *) 0) { #else if ((fp = fopen (buf, "w")) != (FILE *) 0) { #endif for (i = 0; i < num_active ; i++) { /* for each group */ fprintf (fp, "%s\n", active[i].name); } fclose (fp); chmod (buf, 0644); } } /* * Check for any newly created newsgroups. * * If reading news locally stat() the active file to get its * size otherwise do a LIST NEWGROUPS to the NNTP server */ void check_for_any_new_groups () { char old_active_file_server[LEN]; char old_active_file_attribute[LEN]; char buf[LEN], *ptr; FILE *fp = (FILE *) 0; group_p *sorted_active = (group_p *) 0; int group_not_found; int ch, num = 0; /* num == num_old_active groups */ int ch_default = 'n'; int update_old_active = FALSE; int max_old_active; int new_active_size; int old_active_size; long epoch; int compared; notify_p old_active = (notify_p) 0; notify_p *sorted_old_active = (notify_p *) 0; char *autosubscribe, *autounsubscribe; register int i, j; struct stat sb; struct tm *tm; if ((! check_for_new_newsgroups || (update && ! update_fork))) { return; } /* * reading news locally (local) or via NNTP (server name) */ if (read_news_via_nntp) { time (&epoch); tm = localtime (&epoch); sprintf (new_active_file_attribute, "%02d%02d%02d %02d%02d%02d", tm->tm_year, tm->tm_mon+1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); strcpy (new_active_file_server, nntp_server); max_old_active = 16; } else { backup_active (TRUE); strcpy (new_active_file_server, "local"); max_old_active = num_active; if (stat (news_active_file, &sb) >= 0) { sprintf (new_active_file_attribute, "%ld", sb.st_size); } } /* * find out if we have read news from here before otherwise -1 */ active_index = find_active_size_index (new_active_file_server); if (debug == 2) { if (active_index >= 0) { strcpy (old_active_file_server, active_size[active_index].server); strcpy (old_active_file_attribute, active_size[active_index].attribute); } else { strcpy (old_active_file_server, "UNKNOWN"); strcpy (old_active_file_attribute, "UNKNOWN"); } sprintf (msg, "Active size index=[%d] old=[%s %s] new=[%s %s]", active_index, old_active_file_server, old_active_file_attribute, new_active_file_server, new_active_file_attribute); error_message (msg, ""); sleep (2); } if (! read_news_via_nntp && active_index >= 0) { new_active_size = atoi (new_active_file_attribute); old_active_size = atoi (active_size[active_index].attribute); if (new_active_size <= old_active_size) { goto notify_groups_done; } } /* * Only check if spooldir is active news feed */ if (strcmp (spooldir_alias, "news") != 0) { goto notify_groups_done; } if ((fp = open_newgroups_fp (active_index)) == (FILE *) 0) { goto notify_groups_done; } Raw (TRUE); old_active = (notify_p) my_malloc ((unsigned) sizeof (struct t_notify) * max_old_active); if (old_active == (notify_p) 0) { error_message (txt_out_of_memory, progname); goto notify_groups_done; } while (fgets (buf, sizeof (buf), fp) != NULL) { if (buf[0] == '.') { break; } strncpy (old_active[num].name, buf, sizeof (old_active[num].name)); ptr = old_active[num].name; while (*ptr && *ptr != ' ' && *ptr != '\n') { ptr++; } *ptr = '\0'; old_active[num].visited = FALSE; num++; if (num >= max_old_active) { max_old_active= max_old_active + (max_old_active / 2); old_active= (notify_p) my_realloc( (char *) old_active, (unsigned) sizeof(struct t_notify) * max_old_active); if (old_active == (notify_p) 0) { error_message (txt_out_of_memory, progname); goto notify_groups_done; } } } /* * Check if there are user-set groups to be * automatically subscribed or unsubscribed. */ autosubscribe = getenv ("AUTOSUBSCRIBE"); autounsubscribe = getenv ("AUTOUNSUBSCRIBE"); if (read_news_via_nntp) { for (i = 0 ; i < num ; i++) { if (find_group_index (old_active[i].name) == -1) { continue; } if (! prompt_subscribe_group (old_active[i].name, autosubscribe, autounsubscribe)) { if (cmd_line) { printf ("\r\n"); fflush (stdout); } goto notify_groups_done; } } } else { wait_message (txt_checking_active_file); /* * The following code replaces the original check for new newsgroups, * a source of much aggravation. * * The original algorithm compared each group name in active to (on * average) 1/2 the groups in old_active, for ~N*N/2 string compares. * This works out to ~~ 8,000,000 comparisons for 4000 newsgroups. * * The new algorithm allocates an array of pointers to the active * and old_active array elements, sorts each pointer array with * quicksort, then scans through the two arrays in 1 pass; this takes * 2*N*Log2(N) string compares for the sorts, N for the final pass. * This should work out to ~~ 100,000 comparisons for the same 4000 * newsgroups, a BIG, BIG win. */ /* * Allocate arrays to be sorted */ sorted_active = (group_p *) my_malloc ( (unsigned) sizeof (group_p) * num_active); if (sorted_active == (group_p *) 0) { error_message (txt_out_of_memory, progname); goto notify_groups_done; } sorted_old_active = (notify_p *) my_malloc ( (unsigned) sizeof (notify_p) * num); if (sorted_old_active == (notify_p *) 0) { error_message (txt_out_of_memory, progname); goto notify_groups_done; } /* * Fill arrays to be sorted */ for (i = 0 ; i < num_active ; i++) { sorted_active[i] = &active[i]; } for (j = 0 ; j < num ; j++) { sorted_old_active[j] = &old_active[j]; } /* * Sort the arrays */ qsort (sorted_active, num_active, sizeof (group_p), cmp_group_p); qsort (sorted_old_active, num, sizeof (notify_p), cmp_notify_p); /* * Now do the pass through both arrays at once */ for (i = 0, j = 0 ; i < num_active ; i++) { group_not_found = TRUE; compared = 1; while ((j < num) && (0 > (compared = strcmp ( sorted_old_active[j]->name, sorted_active[i]->name)))) { j++; } if (compared == 0) { /* * found it so read in next group */ group_not_found = FALSE; sorted_old_active[j]->visited = TRUE; j++; } if (group_not_found == FALSE) { continue; } update_old_active = TRUE; /* * auto-subscribe/unsubscribe logic */ if (! prompt_subscribe_group (sorted_active[i]->name, autosubscribe, autounsubscribe)) { if (cmd_line) { printf ("\r\n"); fflush (stdout); } goto notify_groups_done; } } } if (cmd_line) { fputc ('\r', stdout); fflush (stdout); } CleartoEOLN(); if (! read_news_via_nntp) { /* * Look for bogus groups */ ch_default = 'y'; for (j = 0 ; j < num ; j++) { if (old_active[j].visited) { continue; } do { update_old_active= 1; fputc ('\r', stdout); CleartoEOLN (); printf (txt_delete_bogus_group, old_active[j].name, ch_default); fflush (stdout); ch = ReadCh (); if (ch == CR) { ch = ch_default; } } while (! strchr ("nqy\033", ch)); switch (ch) { case 'y': delete_group (old_active[j].name); break; case 'q': case ESC: goto notify_groups_done; case 'n': default: break; } printf ("\r\n"); fflush (stdout); } } /* * write active[] to ~/.tin/active (local spooldir) */ if (! read_news_via_nntp && update_old_active) { backup_active (FALSE); } notify_groups_done: if (fp != (FILE *) 0) { fclose (fp); } /* * update attribute field/create new entry with new size/date */ if (active_index >= 0) { if (active_size[active_index].attribute != (char *) 0) { free (active_size[active_index].attribute); active_size[active_index].attribute = (char *) 0; } active_size[active_index].attribute = str_dup (new_active_file_attribute); } else { sprintf (buf, "%s[%s]", new_active_file_server, new_active_file_attribute); load_active_size_info (buf); } /* * Free malloc'd arrays */ if (old_active != (notify_p) 0) { free ((char *) old_active); old_active = (notify_p) 0; } if (sorted_old_active != (notify_p *) 0) { free ((char *) sorted_old_active); sorted_old_active = (notify_p *) 0; } if (sorted_active != (group_p *) 0) { free ((char *) sorted_active); sorted_active = (group_p *) 0; } if (cmd_line) { Raw (FALSE); } } /* * prompt user if new group should be subscribed to */ int prompt_subscribe_group (group, autosubscribe, autounsubscribe) char *group; char *autosubscribe; char *autounsubscribe; { int ch, ch_default = 'n'; int idx; if ((autosubscribe != (char *) 0) && match_group_list (group, autosubscribe)) { idx = add_group (group, TRUE); subscribe (active[my_group[idx]].name, ':', my_group[idx], FALSE); return TRUE; } else if ((autounsubscribe != (char *) 0) && match_group_list (group, autounsubscribe)) { /* ignore this group */ return TRUE; } do { if (cmd_line) { fputc ('\r', stdout); CleartoEOLN (); } else { clear_message (); } printf (txt_subscribe_to_new_group, group, ch_default); fflush (stdout); ch = ReadCh (); if (ch == CR) { ch = ch_default; } } while (! strchr ("nqy\033", ch)); fputc (ch, stdout); fflush (stdout); switch (ch) { case 'y': idx = add_group (group, TRUE); subscribe (active[my_group[idx]].name, ':', my_group[idx], FALSE); break; case 'q': case ESC: return FALSE; case 'n': default: break; } if (cmd_line) { printf ("\r\n%s", txt_checking); fflush (stdout); } else { wait_message (txt_checking); } return TRUE; } int match_group_list (group, group_list) char *group; char *group_list; { char *separator; char pattern[LEN]; int accept, negate, list_len, group_len; accept = FALSE; list_len = strlen (group_list); /* * walk through comma-separated entries in list */ while (list_len > 0) { /* * find end/length of this entry */ separator = strchr (group_list, ','); if (separator != (char *) 0) { group_len = separator-group_list; } else { group_len = list_len; } if ((negate = ('!' == *group_list))) { /* * a '!' before the pattern inverts sense of match */ group_list++; group_len--; list_len--; } /* * copy out the entry and terminate it properly */ strncpy (pattern, group_list, group_len); pattern[group_len] = (char) 0; /* * do a regexp match using routines used in kill.c */ if (STR_MATCH(group, pattern)) { accept = ! negate; /* matched! */ } /* * now examine next entry if any */ if ((char) 0 != group_list[group_len]) { group_len++; /* skip the separator */ } group_list += group_len; list_len -= group_len; } return (accept); } /* * Per group attributes */ void set_default_attributes () { #ifndef INDEX_DAEMON register int i; for (i = 0; i < num_active ; i++) { active[i].attribute.maildir = default_maildir; active[i].attribute.savedir = default_savedir; active[i].attribute.sigfile = default_sigfile; active[i].attribute.organization = (default_organization[0] ? default_organization : (char *) 0); active[i].attribute.followup_to = (char *) 0; active[i].attribute.printer = default_printer; active[i].attribute.read_during_session = FALSE; active[i].attribute.show_only_unread = default_show_only_unread; active[i].attribute.thread_arts = default_thread_arts; active[i].attribute.sort_art_type = default_sort_art_type; active[i].attribute.show_author = default_show_author; active[i].attribute.auto_save= default_auto_save; active[i].attribute.batch_save = default_batch_save; active[i].attribute.delete_tmp_files = FALSE; active[i].attribute.post_proc_type = default_post_proc_type; } #endif /* INDEX_DAEMON */ } /* * Load the group attributes into active[].attribute from ~/.tin/attributes * * attribute.maildir = STRING * attribute.savedir = STRING * attribute.organization = STRING * attribute.sigfile = STRING * attribute.followup_to = STRING * attribute.printer = STRING * attribute.auto_save = ON/OFF * attribute.batch_save = ON/OFF * attribute.delete_tmp_files = ON/OFFЃ^vu~ TIN-1_22.BCK$d[SRC.TIN-1_22]ACTIVE.C;2Bx|0) * attribute.show_only_unread = ON/OFF * attribute.thread_arts = ON/OFF * attribute.show_author = NUM * 0=none, 1=name, 2=addr, 3=both * attribute.sort_art_type = NUM * 0=none, 1=subj descend, 2=subj ascend * 3=from descend, 4=from ascend * 5=date descend, 6=date ascend * attribute.post_proc_type = NUM * 0=none, 1=unshar, 2=uudecode * 3=uudecode & list zoo (unix) / lha (AmigaDOS) archive * 4=uudecode & extract zoo (unix) / lha (AmigaDOS) archive * 5=uudecode & list zip archive * 6=uudecode & extract zip archive */ void read_attributes_file () { #ifndef INDEX_DAEMON char buf[PATH_LEN]; char line[PATH_LEN]; FILE *fp; int num; int index = -1; set_default_attributes (); if ((fp = fopen (attributes_file, "r")) == (FILE *) 0) { return; } if ((update && update_fork) || ! update) { wait_message (txt_reading_attributes_file); } while (fgets (line, sizeof (line), fp) != NULL) { if (line[0] == '#' || line[0] == '\n') { continue; } if (match_string (line, "newsgroup=", buf, sizeof (buf))) { if (debug == 2) { error_message("group=[%s]",buf); } index = find_group_index (buf); continue; } if (match_string (line, "maildir=", buf, sizeof (buf))) { if (index >= 0) { active[index].attribute.maildir = str_dup (buf); if (debug == 2) { sprintf (msg, "maildir=[%s]", active[index].attribute.maildir); error_message (msg, ""); } } continue; } if (match_string (line, "savedir=", buf, sizeof (buf))) { if (index >= 0) { active[index].attribute.savedir = str_dup (buf); if (debug == 2) { sprintf (msg, "savedir=[%s]", active[index].attribute.savedir); error_message (msg, ""); } } continue; } if (match_string (line, "sigfile=", buf, sizeof (buf))) { if (index >= 0) { active[index].attribute.sigfile = str_dup (buf); if (debug == 2) { sprintf (msg, "sigfile=[%s]", active[index].attribute.sigfile); error_message (msg, ""); } } continue; } if (match_string (line, "organization=", buf, sizeof (buf))) { if (index >= 0) { active[index].attribute.organization = str_dup (buf); if (debug == 2) { error_message("organization=[%s]",active[index].attribute.organization); } } continue; } if (match_string (line, "followup_to=", buf, sizeof (buf))) { if (index >= 0) { active[index].attribute.followup_to = str_dup (buf); if (debug == 2) { error_message("followup_to=[%s]",active[index].attribute.followup_to); } } continue; } if (match_string (line, "printer=", buf, sizeof (buf))) { if (index >= 0) { active[index].attribute.printer = str_dup (buf); if (debug == 2) { error_message("printer=[%s]",active[index].attribute.printer); } } continue; } if (match_boolean (line, "show_only_unread=", &num)) { if (index >= 0) { active[index].attribute.show_only_unread = num; } continue; } if (match_boolean (line, "thread_arts=", &num)) { if (index >= 0) { active[index].attribute.thread_arts = num; } continue; } if (match_boolean (line, "auto_save=", &num)) { if (index >= 0) { active[index].attribute.auto_save = num; } continue; } if (match_boolean (line, "batch_save=", &num)) { if (index >= 0) { active[index].attribute.batch_save = num; } continue; } if (match_boolean (line, "delete_tmp_files=", &num)) { if (index >= 0) { active[index].attribute.delete_tmp_files = num; } continue; } if (match_number (line, "sort_art_type=", &num)) { if (index >= 0) { active[index].attribute.sort_art_type = num; } continue; } if (match_number (line, "show_author=", &num)) { if (index >= 0) { active[index].attribute.show_author = num; } continue; } if (match_number (line, "post_proc_type=", &num)) { if (index >= 0) { active[index].attribute.post_proc_type = num; } continue; } } fclose (fp); if ((cmd_line && ! update && ! verbose) || (update && update_fork)) { wait_message ("\n"); } #endif /* INDEX_DAEMON */ } /* * Save the group attributes from active[].attribute to ~/.tin/attributes */ void write_attributes_file () { #ifndef INDEX_DAEMON FILE *fp; register int i; #ifdef VMS if ((fp = fopen (attributes_file, "w", "fop=cif")) == (FILE *) 0) { #else if ((fp = fopen (attributes_file, "w")) == (FILE *) 0) { #endif return; } if (! cmd_line) { if ((update && update_fork) || ! update) { wait_message (txt_writing_attributes_file); } } fprintf (fp, "# Group attributes file\n#\n"); fprintf (fp, "# newsgroup=STRING (ie. alt.sources) [mandatory]\n#\n"); fprintf (fp, "# maildir=STRING (ie. ~/Mail)\n"); fprintf (fp, "# savedir=STRING (ie. ~user/News)\n"); fprintf (fp, "# organization=STRING\n"); fprintf (fp, "# sigfile=STRING (ie. $var/sig)\n"); fprintf (fp, "# followup_to=STRING\n"); fprintf (fp, "# printer=STRING\n"); fprintf (fp, "# auto_save=ON/OFF\n"); fprintf (fp, "# batch_save=ON/OFF\n"); fprintf (fp, "# delete_tmp_files=ON/OFF\n"); fprintf (fp, "# show_only_unread=ON/OFF\n"); fprintf (fp, "# thread_arts=ON/OFF\n#\n"); fprintf (fp, "# show_author=NUM\n"); fprintf (fp, "# 0=none, 1=name, 2=addr, 3=both\n#\n"); fprintf (fp, "# sort_art_type=NUM\n"); fprintf (fp, "# 0=none, 1=subj descend, 2=subj ascend,\n"); fprintf (fp, "# 3=from descend, 4=from ascend,\n"); fprintf (fp, "# 5=date descend, 6=date ascend\n#\n"); fprintf (fp, "# post_proc_type=NUM\n"); fprintf (fp, "# 0=none, 1=unshar, 2=uudecode,\n"); #ifdef M_AMIGA fprintf (fp, "# 3=uudecode & list lha archive,\n"); fprintf (fp, "# 4=uudecode & extract lha archive\n"); #else fprintf (fp, "# 3=uudecode & list zoo archive,\n"); fprintf (fp, "# 4=uudecode & extract zoo archive\n"); #endif fprintf (fp, "# 5=uudecode & list zip archive,\n"); fprintf (fp, "# 6=uudecode & extract zip archive\n\n"); for (i = 0 ; i < num_active ; i++) { fprintf (fp, "newsgroup=%s\n", active[i].name); fprintf (fp, "maildir=%s\n", active[i].attribute.maildir); fprintf (fp, "savedir=%s\n", active[i].attribute.savedir); fprintf (fp, "organization=%s\n", active[i].attribute.organization); fprintf (fp, "sigfile=%s\n", active[i].attribute.sigfile); fprintf (fp, "followup_to=%s\n", active[i].attribute.followup_to); fprintf (fp, "printer=%s\n", active[i].attribute.printer); fprintf (fp, "show_only_unread=%s\n", (active[i].attribute.show_only_unread ? "ON" : "OFF")); fprintf (fp, "thread_arts=%s\n", (active[i].attribute.thread_arts ? "ON" : "OFF")); fprintf (fp, "auto_save=%s\n", (active[i].attribute.auto_save ? "ON" : "OFF")); fprintf (fp, "batch_save=%s\n", (active[i].attribute.batch_save ? "ON" : "OFF")); fprintf (fp, "delete_tmp_files=%s\n", (active[i].attribute.delete_tmp_files ? "ON" : "OFF")); fprintf (fp, "sort_art_type=%d\n", active[i].attribute.sort_art_type); fprintf (fp, "show_author=%d\n", active[i].attribute.show_author); fprintf (fp, "post_proc_type=%d\n", active[i].attribute.post_proc_type); } fclose (fp); #endif /* INDEX_DAEMON */ } /* * Load the last updated time for each group in the active file so that * tind is more efficient and only has to stat the group dir and compare * the last changed time with the time read from the ~/.tin/active.times * file to determine if the group needs updating. * * alt.sources 71234589 * comp.archives 71234890 */ void read_active_times_file () { #ifdef INDEX_DAEMON char *p, *q; char buf[LEN]; char group[PATH_LEN]; FILE *fp; int i; long updated_time; if ((fp = fopen (active_times_file, "r")) == (FILE *) 0) { return; } while (fgets (buf, sizeof (buf), fp) != NULL) { /* * read the group name */ for (p = buf, q = group ; *p && *p != ' ' && *p != '\t' ; p++, q++) { *q = *p; } *q = '\0'; /* * read the last updated time */ updated_time = atol (p); /* * find the group in active[] and set updated time */ i = find_group_index (group); if (i >= 0) { active[i].last_updated_time = updated_time; } if (debug == 2) { printf ("group=[%-40.40s] [%ld]\n", active[i].name, active[i].last_updated_time); } } fclose (fp); #endif /* INDEX_DAEMON */ } /* * Save the last updated time for each group to ~/.tin/active.times */ void write_active_times_file () { #ifdef INDEX_DAEMON char buf[LEN]; char group[PATH_LEN]; FILE *fp; register int i; #ifdef VMS if ((fp = fopen (active_times_file, "w", "fop=cif")) == (FILE *) 0) { #else if ((fp = fopen (active_times_file, "w")) == (FILE *) 0) { #endif return; } for (i = 0 ; i < num_active ; i++) { fprintf (fp, "%s %ld\n", active[i].name, active[i].last_updated_time); } fclose (fp); #endif /* INDEX_DAEMON */ } void load_active_size_info (info) char *info; { char *ptr_name; char *ptr_size; char buf[PATH_LEN]; int i; /* * initialize active_size[] if no entries */ if (! num_active_size) { for (i = 0 ; i < max_active_size ; i++) { active_size[i].server = (char *) 0; active_size[i].attribute = (char *) 0; } } my_strncpy (buf, info, sizeof (buf)); ptr_name = buf; ptr_name = (char *) strchr (buf, ']'); if (ptr_name != (char *) 0) { *ptr_name = '\0'; } ptr_name = buf; ptr_name = (char *) strchr (buf, '['); if (ptr_name != (char *) 0) { ptr_size = ptr_name; *ptr_name = '\0'; if (num_active_size > max_active_size) { expand_active_size (); } active_size[num_active_size].server = str_dup (buf); active_size[num_active_size].attribute = str_dup (++ptr_size); if (debug == 2) { sprintf (buf, "ACTIVE server=[%s] attribute=[%s]", active_size[num_active_size].server, active_size[num_active_size].attribute); error_message ("%s", buf); } num_active_size++; } } int find_active_size_index (cur_active_server) char *cur_active_server; { int i, found = FALSE; for (i = 0 ; i < num_active_size ; i++) { if (strcmp (cur_active_server, active_size[i].server) == 0) { found = TRUE; break; } } return (found ? i : -1); } /* * check for message of the day (motd) file * * If reading news locally stat() the active file to get its * mtime otherwise do a XMOTD command to the NNTP server */ void read_motd_file () { #ifndef INDEX_DAEMON char buf[LEN]; char motd_file_date[32]; FILE *fp = (FILE *) 0; int lineno = 0; long new_motd_date = 0L; long old_motd_date = 0L; struct stat sb; struct tm *tm; if (update && ! update_fork) { return; } old_motd_date = atol (motd_file_info); /* * reading news locally (local) or via NNTP (server name) */ if (read_news_via_nntp) { if (! old_motd_date) { strcpy (motd_file_date, "920101 000000"); } else { tm = localtime (&old_motd_date); sprintf (motd_file_date, "%02d%02d%02d %02d%02d%02d", tm->tm_year, tm->tm_mon+1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); } time (&new_motd_date); } else { if (stat (motd_file, &sb) >=0) { new_motd_date = sb.st_mtime; } } if (old_motd_date && new_motd_date <= old_motd_date) { goto read_motd_done; } /* * Only check if spooldir is active news feed */ if (strcmp (spooldir_alias, "news") != 0) { goto read_motd_done; } if ((fp = open_motd_fp (motd_file_date)) != (FILE *) 0) { while (fgets (buf, sizeof (buf), fp) != NULL) { if (buf[0] == '.') { break; } printf ("%s", buf); lineno++; } fclose (fp); if (lineno) { wait_message (txt_cmdline_hit_any_key); Raw (TRUE); ReadCh (); Raw (FALSE); wait_message ("\n"); } } read_motd_done: /* * update motd tinrc entry with new date */ sprintf (motd_file_info, "%ld", new_motd_date); #endif /* INDEX_DAEMON */ } /* * find first occurrence of any char from str2 in str1 */ char * my_strpbrk (str1, str2) char *str1; char *str2; { register char *ptr1; register char *ptr2; for (ptr1 = str1; *ptr1 != '\0'; ptr1++) { for (ptr2 = str2; *ptr2 != '\0';) { if (*ptr1 == *ptr2++) { return (ptr1); } } } return (char *) 0; } ð*[SRC.TIN-1_22]ACTIVED.C;1+,w.//€ 4-d0@î123KÿPWO56 Ð8t…—7„c1—89€]V‚—G/€HªJÿ/* * Project : tin - a Usenet reader * Module : actived.c * Author : M.Tomlinson & I.Lea * Created : 23-08-92 * Updated : 02-08-93 * Notes : Creates an active file by looking through all the * .next files in the news directories, and writing * this to UULIB:newactive. The UULIB:newsgroups file * must exist. * Copyright : (c) Copyright 1991-93 by Mark Tomlinson & Iain Lea * You may freely copy or redistribute this software, * so long as there is no profit made from its use, sale * trade or reproduction. You may not change this copy- * right notice, and it must be included in any copy made */ #include #define NEWSGROUPS_FILE "UULIB:newsgroups" #define NEWSACTIVE_FILE "UULIB:newsactive" main () { char buf[20]; char groupname[81]; char next_path[90]; char *p, last[21]; FILE *fp, *ng, *active; long numgroups = 0, x; if ((ng = fopen (NEWSGROUPS_FILE, "r")) == (FILE *) 0) { perror (NEWSGROUPS_FILE); exit (1); } if ((active = fopen (NEWSACTIVE_FILE, "w")) == (FILE *) 0) { perror (NEWSACTIVE_FILE); exit (1); } while (fgets (groupname, 80, ng)) { for (p = groupname; *p && *p != ' ' && *p != '\t' && *p != '\n'; p++) { ; } *p = 0; sprintf (next_path,"UUNEWS:%s",groupname); for (p = &next_path[7]; *p ; p++) { if (*p == '.') { *p = '/'; /* convert to tree structure */ } } strcat (next_path,"/.next"); if (fp = fopen (next_path,"r")) { fgets (last,20,fp); x = atol (last) - 1; fclose (fp); } else { x = 0; } fprintf (active, "%s %05ld 00001 y\n", groupname, x); numgroups++; } fclose (ng); sprintf (buf, "%d", numgroups+1); setenv (ENV_VAR_GROUPS, buf); } ð*[SRC.TIN-1_22]AMIGA.C;1+,‹. //€ 4 -d0@î123KÿPWO 56€2t…—78ßg1—89€]V‚—G/€HªJÿ/* * Project : tin - a Usenet reader * Module : amiga.c * Author : M.Tomlinson & I.Lea * Created : 01-04-91 * Updated : 02-08-93 * Notes : Extra functions for Amiga port * Copyright : (c) Copyright 1991-93 by Mark Tomlinson & Iain Lea * You may freely copy or redistribute this software, * so long as there is no profit made from its use, sale * trade or reproduction. You may not change this copy- * right notice, and it must be included in any copy made */ #include "tin.h" #if defined(M_AMIGA) #include #include #ifdef __SASC # include # include #else # include # include # include # include #endif #include #include extern struct DosLibrary *DOSBase; int optind = 1; char *optarg; /* * dummy */ int chmod (file, mode) const char *file; int mode; { return 0; } /* * use the task addres for pid which is unique. */ int getpid (void) { return ((long) FindTask(0L) >> 2); } /* * stub for tputs */ #ifndef INDEX_DAEMON int tputs (str, count, func) char *str; int count; int (*func)(int); { if (! str) { return 0; } while (*str) { if (*str == '\n') func('\r'); func(*str++); } return 0; } #endif /* * stub for tzset */ void tzset (void) { #ifdef __SASC __daylight = 0; __timezone = 0; __tzname[0] = __tzname[1] = "GMT"; #endif } /* * joinpath tacks a file (or sub dir) on to the end of a directory name. * Not just as simple as putting a '/' between the two, as the directory * name may be an assign! */ void joinpath (str, dir, file) char *str; char *dir; char *file; { char c; if (strlen (dir) == 0) { strcpy (str, file); return; } c = dir[strlen(dir)-1]; if (c=='/' || c==':') { sprintf (str, "%s%s", dir, file); } else { sprintf (str, "%s/%s", dir, file); } } void sleep (seconds) int seconds; { Delay (50*seconds); } /* * I'm not really sure how well popen and pclose work, but they seem OK */ FILE * popen (command, mode) char *command; char *mode; { char cmd[256]; if (mode[0] == 'w') { sprintf (cmd, "run >NIL: %s", command); Execute (cmd, 0L, 0L); return fopen ("PIPE:", mode); } else { FILE *rp; rp = fopen ("PIPE:", mode); sprintf (cmd,"run %s >PIPE:",command); Execute (cmd, 0L, 0L); return rp; } } void pclose (pipe) FILE *pipe; { fclose (pipe); } /* * Directory stuff */ DIR * opendir (name) char *name; { DIR *di; di = calloc (1, sizeof (DIR)); di->Lock = Lock (name,ACCESS_READ); if (di->Lock == 0) { free (di); return 0; } if (Examine(di->Lock,&di->fib)==0) { UnLock(di->Lock); free (di); return 0; } return di; } struct dirent * readdir (di) DIR *di; { static struct dirent de; if (ExNext (di->Lock, &di->fib) == 0) { return 0; } de.d_name = di->fib.fib_FileName; de.d_reclen = strlen (de.d_name); return &de; } void closedir (di) DIR *di; { UnLock (di->Lock); free (di); } char getopt (argc, argv, options) int argc; char *argv[]; char *options; { char c,*z; static int subind = 0; for (;optind < argc ; optind++) { if (subind == 0) { c = argv[optind][0]; if (c != '-') { return EOF; } subind = 1; } c = argv[optind][subind]; if (c != 0) { break; } } if (optind == argc) { return EOF; } /* get rid of funnies */ if (c == ':' || c == '?') { return '?'; } if ((z = strchr (options,c)) == 0) { return '?'; } if (z[1] == ':') { if (argv[optind][subind+1]) { optarg = &argv[optind][subind+1]; } else { optarg = argv[++optind]; } optind++; subind = 0; return c; } subind++; return c; } int system (str) const char *str; { if (DOSBase->dl_lib.lib_Version >= 36) { return (System ((char *)str, 0L)); } else { return (!Execute((char *)str, 0L, 0L)); } } /* * The stat call in Aztec C doesn't tell us if the entry is a directory * or not. This one does. You will have to change to define * ST_DIRECT though */ int stat (name, buf) char *name; struct stat *buf; { BPTR dirlock; register struct FileInfoBlock *inf; if (! (dirlock = Lock (name, ACCESS_READ))) { return -1; } if (! (inf = malloc(sizeof(*inf)))) { UnLock (dirlock); return -1; } Examine (dirlock,inf); UnLock (dirlock); buf->st_attr = ((inf->fib_EntryType>0) ? ST_DIRECT : 0) | (inf->fib_Protection & 0xf); buf->st_size = inf->fib_Size; buf->st_mtime = ((inf->fib_Date.ds_Days + 2922) * (24 * 60) + inf->fib_Date.ds_Minute) * 60 + inf->fib_Date.ds_Tick / TICKS_PER_SECOND; free (inf); return 0; } /* * This getenv and setenv will use the WB2.0 calls if you have the new * rom. If not, it resorts to looking in the ENV: directory. */ char * getenv (name) register const char *name; { register FILE *fp; register char *ptr; static char buf[256]; static char value[256]; /* 2.0 style? */ if (DOSBase->dl_lib.lib_Version >= 36) { if (GetVar ((char *)name,value,256,0L) == -1) { return 0; } } else { if (strlen (name) > 252) { return 0; } strcpy (buf,"ENV:"); strcpy (&buf[4],name); if (! (fp = fopen(buf,"r"))) { return 0; } for (ptr = value; (*ptr=getc(fp))!=EOF && ++ptr < &value[256];); fclose(fp); *ptr = 0; } return value; } int setenv (name, value) char *name; char *value; { if (DOSBase->dl_lib.lib_Version >= 36) { SetVar ((char *)name,(char *)value,strlen(value)+1,GVF_LOCAL_ONLY); } return 0; } void make_post_cmd (cmd, name) char *cmd; char *name; { char *p; if ((p = getenv (ENV_VAR_POSTER)) != (char *) 0) { sprintf (cmd, p, name); } else { sprintf (cmd, DEFAULT_POSTER, name); } } #else /* * The ';' is to satisfy a really picky Ansi compiler */ ; #endif /* M_AMIGA */ ð*[SRC.TIN-1_22]AMIGA.H;1+,†.//€ 4I-d0@î123KÿPWO56`™Ût…—7€¡Fg1—89€]V‚—G/€HªJÿ/* * Project : tin - a Usenet reader * Module : amiga.h * Author : M.Tomlinson & I.Lea * Created : 17-09-92 * Updated : 20-06-93 * Notes : Directory support for AmigaDOS * Copyright : (c) Copyright 1991-93 by Mark Tomlinson & Iain Lea * You may freely copy or redistribute this software, * so long as there is no profit made from its use, sale * trade or reproduction. You may not change this copy- * right notice, and it must be included in any copy made */ #if defined(M_AMIGA) #ifndef AMIGA_H #define AMIGA_H #include /* SAS-C and Aztec don't take the mode for mkdir() */ extern int mkdir(char *path); #define mkdir(p,m) mkdir(p) /* Replace Aztec's stat function with one that gives ST_DIRECT info */ struct stat { char st_attr; long st_mtime; long st_size; }; #define ST_DELETE 0x01 #define ST_EXECUTE 0x02 #define ST_WRITE 0x04 #define ST_READ 0x08 #define ST_DIRECT 0x10 /* Aztec's stat() doesn't give this information */ /* For opendir(), and readdir() */ struct dirent { char *d_name; long d_reclen; }; typedef struct { BPTR Lock; struct FileInfoBlock fib; int first; } DIR; extern DIR *opendir (char *name); extern struct dirent *readdir (DIR *di); extern void closedir (DIR *di); extern int stat(char *name, struct stat *buf); extern FILE *popen (char *command, char *mode); extern void pclose (FILE *pipe); extern void sleep(int secs); extern int tputs (char *cp, int count, int (*outc)(int)); extern int getpid(void); extern int setenv(char *, char *); extern int optind; extern char *optarg; extern char getopt (int argc, char *argv[], char *options); extern void make_post_cmd (char *cmd, char *name); extern void make_post_process_cmd(char *cmd, char *dir, char *file); #endif /* AMIGA_H */ #endif /* M_AMIGA */ ð*[SRC.TIN-1_22]ART.C;5+,ã.H//€ 4HF…-d0@î123KÿPWOI56à+™±Æ‹—7 ‰³Æ‹—89€]V‚—G/€HªJÿ /* * Project : tin - a Usenet reader * Module : art.c * Author : I.Lea & R.Skrenta * Created : 01-04-91 * Updated : 22-09-93 * Notes : * Copyright : (c) Copyright 1991-93 by Iain Lea & Rich Skrenta * You may freely copy or redistribute this software, * so long as there is no profit made from its use, sale * trade or reproduction. You may not change this copy- * right notice, and it must be included in any copy made */ #include "tin.h" #include "stpwatch.h" char index_file[PATH_LEN]; char *glob_art_group; static long last_read_article; /* * Construct the pointers to the basenotes of each thread * arts[] contains every article in the group. inthread is * set on each article that is after the first article in the * thread. Articles which have been expired have their thread * set to -2 (ART_EXPIRED). */ void find_base (index) int index; /* active[index] */ { register int i; register int j; top_base = 0; debug_print_arts (); if (active[index].attribute.show_only_unread) { for (i = 0; i < top; i++) { if (IGNORE_ART(i) || arts[i].inthread != FALSE) { continue; } if (top_base >= max_art) { expand_art (); } if (arts[i].unread == ART_UNREAD) { base[top_base++] = i; } else { for (j = i ; j >= 0 ; j = arts[j].thread) { if (arts[j].unread) { base[top_base++] = i; break; } } } } } else { for (i = 0; i < top; i++) { if (IGNORE_ART(i) || arts[i].inthread != FALSE) { continue; } if (top_base >= max_art) { expand_art (); } base[top_base++] = i; } } } /* * Count the number of non-expired articles in arts[] */ int num_of_arts () { int sum = 0; register int i; for (i = 0; i < top; i++) { if (arts[i].thread != ART_EXPIRED) { sum++; } } return sum; } /* * Return TRUE if arts[] contains any expired articles * (articles we have an entry for which don't have a * corresponding article file in the spool directory) */ int purge_needed (group_path) char *group_path; { register int i; for (i = 0; i < top; i++) { if (arts[i].thread == ART_EXPIRED) { return TRUE; } } return FALSE; } /* * Main group indexing routine. Group should be the name of the * newsgroup, i.e. "comp.unix.amiga". group_path should be the * same but with the .'s turned into /'s: "comp/unix/amiga" * * Will read any existing index, create or incrementally update * the index by looking at the articles in the spool directory, * and attempt to write a new index if necessary. */ int index_group (group, group_path) char *group; char *group_path; { int index; int killed = FALSE; int expired = FALSE; int modified = FALSE; long min; long max; register int i; glob_art_group = group; if (! update) { sprintf (msg, txt_group, group); wait_message (msg); } BegStopWatch("index_group"); index = find_group_index (group); if (index != -1) { set_alarm_clock_off (); set_signals_art (); hash_reclaim (); free_art_array (); /* * load article numbers into base[] */ setup_base (group, group_path); /* * load articles from xover/xindex file if it exists */ min = base[0]; max = (top_base ? base[top_base-1] : base[0]); if (! read_xover_file (group, min, max)) { read_xindex_file (group); } /* * add any articles to arts[] that are new or were killed */ modified = read_group (group, group_path); /* * check that user did not abort indexing */ if (modified == -1) { set_alarm_clock_on (); return FALSE; } /* * Stat all articles to see if any have expired */ if (purge_index_files) { if (! cmd_line) { sprintf (msg, txt_purge, group); wait_message (msg); } for (i = 0 ; i < top ; i++) { if (! stat_article (arts[i].artnum, group_path)) { expired = TRUE; if (cmd_line && verbose) { fputc ('P', stdout); fflush (stdout); } } } if (expired && cmd_line && verbose) { fputc ('\n', stdout); fflush (stdout); } } /* * If reading index file via XINDEX this is useless */ if (expired || modified || purge_needed (group_path)) { if (! cmd_line && index_file[0]) { wait_message (txt_writing_index_file); } write_xindex_file (group); } read_newsrc_line (group); killed = kill_any_articles (index); make_threads (FALSE); find_base (index); if ((modified || killed) && ! update) { clear_message (); } set_alarm_clock_on (); } EndStopWatch(); PrintStopWatch(); return TRUE; } /* * Index a group. Assumes any existing index has already been * loaded. Return values are: * TRUE loaded index and modified it * FALSE loaded index but not modified * -1 user aborted indexing operation */ int read_group (group, group_path) char *group; char *group_path; { char *ptr, buf[PATH_LEN]; char progress[PATH_LEN]; extern long head_next; int count = 0; int modified = FALSE; int respnum, total = 0; long art; register int i; static char dir[PATH_LEN] = ""; /* * change to groups spooldir to optimize fopen()'s on local articles */ #ifdef INDEX_DAEMON if (dir[0] == 0) #endif get_cwd (dir); joinpath (buf, active[my_group[cur_groupnum]].spooldir, group_path); my_chdir (buf); buf[0] = '\0'; sprintf (progress, txt_group, active[my_group[cur_groupnum]].name); /* * Count num of arts to index so the user has an idea of index time */ BegStopWatch("valid_artnum1"); for (i = 0; i < top_base; i++) { if (base[i] <= last_read_article || valid_artnum (base[i]) >= 0) { continue; } total++; } EndStopWatch(); PrintStopWatch(); /* * Reset the next article number index (for when HEAD fails) */ head_next = -1; for (i = 0; i < top_base; i++) { /* for each article # */ art = base[i]; /* * Do we already have this article in our index? Change * thread from (ART_EXPIRED) to (ART_NORMAL) if so and * skip the header eating. */ BegStopWatch("valid_artnum2"); if ((respnum = valid_artnum (art)) >= 0 || art <= last_read_article) { if (respnum >= 0) { arts[respnum].thread = ART_NORMAL; arts[respnum].unread = ART_UNREAD; } continue; } EndStopWatch(); PrintStopWatch(); /* * we've modified the index so it will need to be re-written */ if (! modified) { modified = TRUE; } if ((ptr = open_art_header (art)) == (char *) 0) { continue; } /* * Add article to arts[] */ if (top >= max_art) { expand_art(); } arts[top].artnum = art; arts[top].thread = ART_NORMAL; set_article (&arts[top]); if (! parse_headers (ptr, &arts[top])) { sprintf (buf, "FAILED parse_header(%ld)", art); debug_nntp ("read_group", buf); continue; } last_read_article = arts[top].artnum; /* used if arts are killed */ top++; if (++count % MODULO_COUNT_NUM == 0 && ! update) { if (input_pending ()) { if (read (STDIN_FILENO, buf, sizeof (buf)-1)) { if (buf[0] == ESC || buf[0] == 'q' || buf[0] == 'Q') { if (prompt_yn (cLINES, txt_abort_indexing, 'y')) { chdir (dir); return -1; } else { printf (progress); } } } } if (count == 0) { printf (progress); } else { printf ("\b\b\b\b\b\b\b\b\b%4d/%-4d", count, total); } fflush (stdout); } if (update && verbose) { fputc ('.', stdout); fflush (stdout); } } if (count && update && verbose) { fputc ('\n', stdout); fflush (stdout); } /* * change to previous dir before indexing started */ my_chdir (dir); return modified; } /* * Go through the articles in arts[] and use .thread to snake threads * through them. Use the subject line to construct threads. The * first article in a thread should have .inthread set to FALSE, the * rest TRUE. Only do unexprired articles we haven't visited yet * (arts[].thread == -1 ART_NORMAL). */ void make_threads (rethread) int rethread; { register int i; register int j; if (! cmd_line) { if (active[my_group[cur_groupnum]].attribute.thread_arts) { wait_message (tx ñ±Þa~ TIN-1_22.BCKãd[SRC.TIN-1_22]ART.C;5H‹Ólt_threading_arts); } else { wait_message (txt_unthreading_arts); } } /* if (debug == 2) { sprintf (msg, "rethread=[%d] thread_arts=[%d] attr_thread_arts=[%d]", rethread, default_thread_arts, active[my_group[cur_groupnum]].attribute.thread_arts); error_message (msg, ""); } */ /* * arts[].thread & arts[].inthread need to be reset if re-threading */ if (rethread || active[my_group[cur_groupnum]].attribute.thread_arts) { /* if (debug == 2) { error_message("Resetting .thread & .inthread", ""); } */ for (i=0 ; i < top ; i++) { arts[i].thread = ART_NORMAL; arts[i].inthread = FALSE; } } switch (active[my_group[cur_groupnum]].attribute.sort_art_type) { case SORT_BY_NOTHING: /* don't sort at all */ qsort ((char *) arts, top, sizeof (struct t_article), artnum_comp); break; case SORT_BY_SUBJ_DESCEND: case SORT_BY_SUBJ_ASCEND: qsort ((char *) arts, top, sizeof (struct t_article), subj_comp); break; case SORT_BY_FROM_DESCEND: case SORT_BY_FROM_ASCEND: qsort ((char *) arts, top, sizeof (struct t_article), from_comp); break; case SORT_BY_DATE_DESCEND: case SORT_BY_DATE_ASCEND: qsort ((char *) arts, top, sizeof (struct t_article), date_comp); break; default: break; } /* * FIXME - Once full group attributes are implemented what should the case be here? */ if (active[my_group[cur_groupnum]].attribute.thread_arts == 0 || default_thread_arts == 0) { /* if (debug == 2) { error_message("Returning before threading", ""); } */ return; } /* if (debug == 2) { error_message("Threading", ""); } */ for (i = 0; i < top; i++) { if (arts[i].thread != ART_NORMAL || IGNORE_ART(i)) { continue; } for (j = i+1; j < top; j++) { if (! IGNORE_ART(j) && arts[j].inthread == FALSE && ((arts[i].subject == arts[j].subject) || ((arts[i].part || arts[i].patch) && arts[i].archive == arts[j].archive))) { arts[i].thread = j; arts[j].inthread = TRUE; break; } } } } int parse_headers (buf, h) char *buf; struct t_article *h; { char buf2[HEADER_LEN]; char art_from_addr[LEN]; char art_full_name[LEN]; char *ptr, *ptrline, *s; int flag, n = 0, len = 0; int lineno = 0; int max_lineno = 25; int got_archive = FALSE; int got_date = FALSE; int got_from = FALSE; int got_lines = FALSE; int got_received = FALSE; int got_subject = FALSE; int got_xref = FALSE; n = strlen (buf); if (n == 0) { return FALSE; } buf[n-1] = '\0'; ptr = buf; while (1) { for (ptrline = ptr; *ptr && *ptr != '\n'; ptr++) { if (((*ptr) & 0xFF) < ' ') { *ptr = ' '; } } flag = *ptr; *ptr++ = '\0'; lineno++; switch (*ptrline) { case 'F': /* From: mandatory */ case 'T': /* To: mandatory (mailbox) */ if (! got_from) { if (match_header (ptrline, "From", buf2, HEADER_LEN) || match_header (ptrline, "To", buf2, HEADER_LEN)) { parse_from (buf2, art_from_addr, art_full_name); h->from = hash_str (art_from_addr); if (art_full_name[0]) { h->name = hash_str (art_full_name); } got_from = TRUE; } } break; case 'R': /* Received: If found its probably a mail article */ if (! got_received) { if (match_header (ptrline, "Received", buf2, HEADER_LEN)) { max_lineno = 50; got_received = TRUE; } } break; case 'S': /* Subject: mandatory */ if (! got_subject) { if (match_header (ptrline, "Subject", buf2, HEADER_LEN)) { s = eat_re (buf2); h->subject = hash_str (eat_re (s)); got_subject = TRUE; } } break; case 'D': /* Date: mandatory */ if (! got_date) { if (match_header (ptrline, "Date", buf2, HEADER_LEN)) { h->date = parsedate (buf2, (struct _TIMEINFO *) 0); got_date = TRUE; } } break; case 'X': /* Xref: optional */ if (! got_xref) { if (match_header (ptrline, "Xref", buf2, HEADER_LEN) || match_header (ptrline, "xref", buf2, HEADER_LEN)) { s = buf2; while (*s && *s == ' ') { s++; } h->xref = str_dup (s); got_xref = TRUE; } } break; case 'L': /* Lines: optional */ if (! got_lines) { if (match_header (ptrline, "Lines", buf2, HEADER_LEN)) { h->lines = atoi (buf2); got_lines = TRUE; } } break; case 'A': /* Archive-name: optional */ if (match_header (ptrline, "Archive-name", buf2, HEADER_LEN) || match_header (ptrline, "Archive-Name", buf2, HEADER_LEN)) { if ((s = (char *) strchr (buf2, '/')) != (char *) 0) { if (strncmp (s+1, "part", 4) == 0 || strncmp (s+1, "Part", 4) == 0) { h->part = str_dup (s+5); len = (int) strlen (h->part); if (h->part[len-1] == '\n') { h->part[len-1] = '\0'; } } else if (strncmp (s+1,"patch",5) == 0 || strncmp (s+1,"Patch",5) == 0) { h->patch = str_dup (s+6); len = (int) strlen (h->patch); if (h->patch[len-1] == '\n') { h->patch[len-1] = '\0'; } } if (h->part || h->patch) { s = buf2; while (*s && *s != '/') s++; *s = '\0'; s = buf2; h->archive = hash_str (s); got_archive = TRUE; } } } break; } if (! flag || lineno > max_lineno || got_archive) { if (got_from && got_date) { if (! got_subject) { h->subject = hash_str (""); } debug_print_header (h); return TRUE; } else { return FALSE; } } } /* NOTREACHED */ } /* * Write out an index file. Write the group name first so if * local indexing is done so we can disambiguate between group * name hash collisions by looking at the index file. */ void write_xindex_file (group) char *group; { char nam[LEN]; FILE *fp; int *iptr; int index; int realnum; long min_artnum = 0L; long max_artnum = 0L; register int i; if (! index_file[0]) { if (debug) { error_message (txt_no_index_file, ""); } return; } set_tin_uid_gid(); sprintf (nam, "%s.%d", index_file, process_id); #ifdef VMS if ((fp = fopen (nam, "w", "fop=cif")) == NULL) { #else if ((fp = fopen (nam, "w")) == NULL) { #endif perror_message (txt_cannot_open, nam); set_real_uid_gid (); return; } /* * dump group header info. */ index = my_group[cur_groupnum]; if (active[index].attribute.sort_art_type != SORT_BY_NOTHING) { qsort ((char *) arts, top, sizeof (struct t_article), artnum_comp); } fprintf (fp, "%s\n", group); fprintf (fp, "%d\n", num_of_arts ()); if (top <= 0) { fprintf (fp, "0\n"); } else { min_artnum = arts[0].artnum; max_artnum = arts[top-1].artnum; if (last_read_article > max_artnum) { max_artnum = last_read_article; fprintf (fp, "%ld\n", last_read_article); } else { fprintf (fp, "%ld\n", max_artnum); } if (active[index].type == GROUP_TYPE_MAIL) { i = FALSE; if (min_artnum > active[index].min) { active[index].min = min_artnum; i = TRUE; } if (max_artnum > active[index].max) { active[index].max = max_artnum; i = TRUE; } if (i) { write_mail_active_file (); } } } /* * dump articles */ realnum = 0; for (i = 0; i < top; i++) { if (arts[i].thread == ART_EXPIRED) { continue; } #ifdef DEBUG debug_print_header (&arts[i]); #endif fprintf(fp, "%ld\n", arts[i].artnum); iptr = (int *) arts[i].subject; iptr--; if (! arts[i].subject) { fprintf(fp, " \n"); } else if (*iptr < 0 || *iptr > top) { fprintf(fp, " %s\n", arts[i].subject); *iptr = realnum; } else if (*iptr == i) { fprintf(fp, " %s\n", arts[i].subject); } else { fprintf(fp, "%%%d\n", *iptr); } iptr = (int *) arts[i].from; iptr--; if (! arts[i].from) { fprintf (fp, " \n"); } else if (*iptr < 0 || *iptr > top) { fprintf (fp, " %s\n", arts[i].from); *iptr = realnum; } else if (*iptr == i) { fprintf(fp, " %s\n", arts[i].from); } else { fprintf(fp, "%%%d\n", *iptr); } iptr = (int *) arts[i].name; iptr--; if (! arts[i].name) { fprintf (fp, " \n"); } else if (*iptr < 0 || *iptr > top) { fprintf (fp, " %s\n", arts[i].name); *iptr = realnum; } else if (*iptr == i) { fprintf(fp, " %s\n", arts[i].name); } else { fprintf(fp, "%%%d\n", *iptr); } fprintf (fp, "%ld\n", arts[i].date); if (! arts[i].xref) { fprintf (fp, "\n"); } else { fprintf (fp, " %s\n", arts[i].xref); } if (arts[i].lines < 0) { fprintf (fp, "\n"); } else { fprintf (fp, " %d\n", arts[i].lines); } iptr = (int *) arts[i].archive; iptr--; if (! arts[i].archive) { fprintf (fp, "\n"); } else if (*iptr < 0 || *iptr > top) { fprintf (fp, " %s\n", arts[i].archive); *iptr = realnum; } else if (arts[i].part || arts[i].patch) { if (*iptr == i) { fprintf(fp, " %s\n", arts[i].archive); } else { fprintf (fp, "%%%d\n", *iptr); } } else { fprintf (fp, "\n"); } if (! arts[i].part) { fprintf (fp, " \n"); } else { fprintf (fp, "%s\n", arts[i].part); } if (! arts[i].patch) { fprintf (fp, " \n"); } else { fprintf (fp, "%s\n", arts[i].patch); } realnum++; } fclose (fp); rename_file (nam, index_file); chmod (index_file, 0644); set_real_uid_gid(); if (debug == 2) { #ifdef VMS sprintf (msg, "copy %s INDEX", index_file); #else sprintf (msg, "cp %s INDEX", index_file); #endif system (msg); } } /* * Read in an XINDEX index file. * * index file header * 1. newsgroup name (ie. alt.sources) * 2. number of articles (ie. 26) * 3. number of last read article (ie. 210) * 4. Is this a complete/killed index file (ie. COMPLETE/KILLED) * * index file record * 1. Article number (ie. 183) [mandatory] * 2. Subject: line (ie. Which newsreader?) [mandatory] * 3. From: line (addr) (ie. iain@norisc) [mandatory] * 4. From: line (name) (ie. Iain Lea) [mandatory] * 5. Date: of posting (ie. 71459801) [mandatory] * 6. Xref: grp:num ... (ie. alt.test:389) [optional] * 7. Lines: number (ie. 23) [optional] * 8. Archive: name (ie. compiler) [optional] * 9. Part number of Archive: name (ie. 01) [optional] * 10. Patch number of Archive: name (ie. 01) [optional] */ void read_xindex_file (group_name) char *group_name; { char buf[LEN], *p; int error = 0; int i, n; FILE *fp = NULL; top = 0; last_read_article = 0L; if ((fp = open_xindex_fp (group_name)) == (FILE *) 0) { return; } /* * load header - discard group name, num. of arts in index file after any arts were killed */ if (fgets (buf, sizeof buf, fp) == NULL || fgets (buf, sizeof buf, fp) == NULL) { error = 0; goto corrupt_index; } i = atoi (buf); /* * num. of last_read_article including any that were killed */ if (fgets(buf, sizeof buf, fp) == NULL) { error = 1; goto corrupt_index; } last_read_article = (long) atol (buf); /* * load articles */ while (top < i) { if (top >= max_art) { expand_art (); } arts[top].thread = ART_EXPIRED; set_article (&arts[top]); /* * 1. Article no. */ if (fgets (buf, sizeof buf, fp) == NULL) { error = 2; goto corrupt_index; } arts[top].artnum = (long) atol (buf); /* * 2. Subject: */ if (fgets (buf, sizeof buf, fp) == NULL) { error = 3; goto corrupt_index; } if (buf[0] == '%') { n = atoi (&buf[1]); if (n >= top || n < 0) { error = 4; goto corrupt_index; } arts[top].subject = arts[n].subject; } else if (buf[0] == ' ') { for (p = &buf[1]; *p && *p != '\n'; p++) continue; *p = '\0'; arts[top].subject = hash_str (&buf[1]); } else { error = 5; goto corrupt_index; } /* * 3. From: (addr part) */ if (fgets (buf, sizeof buf, fp) == NULL) { error = 6; goto corrupt_index; } if (buf[0] == '%') { n = atoi (&buf[1]); if (n >= top || n < 0) { error = 7; goto corrupt_index; } arts[top].from = arts[n].from; } else if (buf[0] == ' ') { for (p = &buf[1]; *p && *p != '\n'; p++) continue; *p = '\0'; arts[top].from = hash_str (&buf[1]); } else { error = 8; goto corrupt_index; } /* * 4. From: (name part) */ if (fgets (buf, sizeof buf, fp) == NULL) { error = 9; goto corrupt_index; } if (buf[0] == '%') { n = atoi (&buf[1]); if (n > top || n < 0) { error = 10; goto corrupt_index; } if (n == top) { /* no full name so .name = .from */ arts[top].name = arts[top].from; } else { arts[top].name = arts[n].name; } } else if (buf[0] == ' ') { for (p = &buf[1]; *p && *p != '\n'; p++) continue; *p = '\0'; if (buf[1]) { arts[top].name = hash_str (&buf[1]); } } else { error = 11; goto corrupt_index; } /* * 5. Date: */ if (fgets (buf, sizeof buf, fp) == NULL) { error = 12; goto corrupt_index; } arts[top].date = (long) atol (buf); /* * 6. Xref: */ if (fgets (buf, sizeof buf, fp) == NULL) { error = 13; goto corrupt_index; } if (buf[0] == '\n') { arts[top].xref = (char *) 0; } else { p = strrchr (buf, '\n'); if (p != (char *) 0) { *p = '\0'; } arts[top].xref = str_dup (&buf[1]); } /* * 7. Lines: */ if (fgets (buf, sizeof buf, fp) == NULL) { error = 14; goto corrupt_index; } if (buf[0] == '\n') { arts[top].lines = -1; } else { arts[top].lines = atoi (buf); } /* * 8. Archive-name: */ if (fgets (buf, sizeof buf, fp) == NULL) { error = 15; goto corrupt_index; } if (buf[0] == '\n') { arts[top].archive = (char *) 0; } else if (buf[0] == '%') { n = atoi (&buf[1]); if (n > top || n < 0) { error = 16; goto corrupt_index; } arts[top].archive = arts[n].archive; } else if (buf[0] == ' ') { for (p = &buf[1]; *p && *p != '\n' ; p++) continue; *p = '\0'; arts[top].archive = hash_str (&buf[1]); } else { error = 17; goto corrupt_index; } /* * 9. Part no. */ if (fgets(buf, sizeof buf, fp) == NULL) { error = 18; goto corrupt_index; } if (buf[0] != ' ') { p = strrchr (buf, '\n'); if (p != (char *) 0) { *p = '\0'; } arts[top].part = str_dup (buf); } /* * 10. Patch no. */ if (fgets (buf, sizeof buf, fp) == NULL) { error = 19; goto corrupt_index; } if (buf[0] != ' ') { p = strrchr (buf, '\n'); if (p != (char *) 0) { *p = '\0'; } arts[top].patch = str_dup (buf); } debug_print_header (&arts[top]); top++; } fclose(fp); /* * If reading in a mail group index check if min & max numbers are * consistant with what has been read from index file. */ i = my_group[cur_groupnum]; if (active[i].type == GROUP_TYPE_MAIL) { n = FALSE; if (top && top > active[i].max) { active[i].max = top; n = TRUE; } if (top && arts[0].artnum > active[i].min) { active[i].min = arts[0].artnum; n = TRUE; } if (n) { write_mail_active_file (); } } return; corrupt_index: if (! update) { sprintf (msg, txt_corrupt_index, index_file, error, top); error_message (msg, ""); } if (debug == 2) { #ifdef VMS sprintf (msg, "copy %s INDEX.BAD", index_file); #else sprintf (msg, "cp %s INDEX.BAD", index_file); #endif system (msg); } last_read_article = 0L; if (fp) { fclose(fp); } set_tin_uid_gid (); unlink (index_file); set_real_uid_gid (); top = 0; } /* * Read in an XOVER index file. Fields are separated by TAB. * * index file record * 1. article number (ie. 183) [mandatory] * 2. Subject: line (ie. Which newsreader?) [mandatory] * 3. From: line (ie. iain@norisc) [mandatory] * 4. Date: line (ie. rfc822 format) [mandatory] * 5. Lines: line (ie. 23) [optional] * 6. Xref: line (ie. alt.test:389) [optional] */ int read_xover_file (group_name, min, max) char *group_name; long min; long max; { char *p, *q; char buf[1024]; char art_full_name[LEN]; char art_from_addr[LEN]; FILE *fp; top = 0; last_read_article = 0L; /* * setup the overview file (whether it be local or via nntp) */ if ((fp = open_xover_fp (group_name, min, max)) == (FILE *) 0) { return FALSE; } while (fgets (buf, sizeof (buf), fp) != (char *) 0) { if (strcmp (buf, ".") == 0) { break; } if (top >= max_art) { expand_art (); } arts[top].thread = ART_EXPIRED; set_article (&arts[top]); p = buf; /* * read the article number */ last_read_article = arts[top].artnum = atol (p); q = strchr (p, '\t'); if (q == (char *) 0) { error_message ("Bad overview record '%s'", buf); continue; } else { p = q + 1; } /* * READ subject */ q = strchr (p, '\t'); if (q == (char *) 0) { error_message ("Bad overview record (Subject) '%s'", p); debug_nntp ("read_xover_file", "Bad overview record (Subject)"); continue; } else { *q = '\0'; } arts[top].subject = hash_str (eat_re (eat_re (p))); p = q + 1; /* * READ author */ q = strchr (p, '\t'); if (q == (char *) 0) { error_message ("Bad overview record (From) '%s'", p); debug_nntp ("read_xover_file", "Bad overview record (From)"); continue; } else { *q = '\0'; } parse_from (p, art_from_addr, art_full_name); arts[top].from = hash_str (art_from_addr); if (art_full_name[0]) { arts[top].name = hash_str (art_full_name); } p = q + 1; /* * READ article date */ q = strchr (p, '\t'); if (q == (char *) 0) { error_message ("Bad overview record (Date) '%s'", p); debug_nntp ("read_xover_file", "Bad overview record (Date)"); continue; } else { *q = '\0'; } arts[top].date = parsedate (p, NULL); p = q + 1; /* * SKIP article messageid */ q = strchr (p, '\t'); if (q == (char *) 0) { error_message ("Bad overview record (Msg-id) '%s'", p); debug_nntp ("read_xover_file", "Bad overview record (Msg-id)"); continue; } p = q + 1; /* * SKIP article references */ q = strchr (p, '\t'); if (q == (char *) 0) { error_message ("Bad overview record (References) '%s'", p); debug_nntp ("read_xover_file", "Bad overview record (References)"); continue; } p = q + 1; /* * SKIP article bytes */ q = strchr (p, '\t'); if (q == (char *) 0) { error_message ("Bad overview record (Bytes) '%s'", p); debug_nntp ("read_xover_file", "Bad overview record (Bytes)"); continue; } else { *q = '\0'; } p = q + 1; /* * READ article lines (special case - last standard nov header) */ q = strchr (p, '\t'); if (q == (char *) 0) { if (!*p || (*p < '0' && *p > '9')) { error_message ("Bad overview record (Lines) '%s'", p); debug_nntp ("read_xover_file", "Bad overview record (Lines)"); continue; } } else { *q = '\0'; } arts[top].lines = atoi (p); p = (q == (char *) 0 ? (char *) 0 : q + 1); /* * READ article xrefs */ if (p != (char *) 0 && xref_supported) { q = str_str (p, "Xref: ", 6); if (q != (char *) 0) { p = q + 6; q = p; while (*q && *q != '\t') { q++; } *q = '\0'; q = strrchr (p, '\n'); if (q != (char *) 0) { *q = '\0'; } q = p; while (*q && *q == ' ') { q++; } arts[top].xref = str_dup (q); } } /* * end of overview line processing */ debug_print_header (&arts[top]); top++; } fclose (fp); return TRUE; } /* * Look in the local $HOME/RCDIR/[ INDEX_NEWSDIR | INDEX_MAILDIR ] etc. * directory for the index file for the given group. Hashing the group * name gets a number. See if that #.1 file exists; if so, read first * line. Group we want? If no, try #.2. Repeat until no such file or * we find an existing file that matches our group. * Return group type of the index file (mail / news / -1 on error). */ int find_index_file (group) char *group; { char *p, dir[PATH_LEN]; FILE *fp; int i = 1, j, type; static char buf[PATH_LEN]; unsigned long h; j = find_group_index (group); if (j == -1) { return j; } type = active[j].type; h = hash_groupname (group); if (read_news_via_nntp && xindex_supported && type == GROUP_TYPE_NEWS) { sprintf (index_file, "%sxindex.%d", TMPDIR, process_id); return (type); } if (local_index) { if (type == GROUP_TYPE_NEWS) { my_strncpy (dir, index_newsdir, sizeof (dir)); } else { my_strncpy (dir, index_maildir, sizeof (dir)); } } else { #ifdef VMS joindir (dir, get_val ("TIN_INDEXDIR", active[j].spooldir), INDEX_NEWSDIR); #else joinpath (dir, get_val ("TIN_INDEXDIR", active[j].spooldir), INDEX_NEWSDIR); #endif } i = 1; while (TRUE) { sprintf (buf, "%lu.%d", h, i); joinpath (index_file, dir, buf); if ((fp = fopen (index_file, "r")) == (FILE *) 0) { return (type); } if (fgets (buf, sizeof (buf), fp) == (char *) 0) { fclose (fp); return (type); } fclose (fp); for (p = buf; *p && *p != '\n'; p++) { continue; } *p = '\0'; if (strcmp (buf, group) == 0) { return (type); } i++; } } /* * Run the index file updater only for the groups we've loaded. */ void do_update () { char group_path[PATH_LEN]; register int i, j; long beg_epoch, end_epoch; #ifdef INDEX_DAEMON char buf[PATH_LEN]; long group_time, index_time; struct stat stinfo; #endif if (verbose) { time (&beg_epoch); } /* * load last updated times for each group (tind daemon only) */ read_active_times_file (); /* * loop through groups and update any required index files */ for (i = 0; i < group_top; i++) { make_group_path (active[my_group[i]].name, group_path); #ifdef INDEX_DAEMON joinpath (buf, active[my_group[i]].spooldir, group_path); if (stat (buf, &stinfo) == -1) { if (verbose) { error_message ("Can't stat group %s\n", buf); } continue; } group_time = stinfo.st_mtime; index_time = 0L; if (find_index_file (active[my_group[i]].name) == -1) { continue; } if (stat (index_file, &stinfo) == -1) { if (verbose) { printf ("Can't stat %s index %s\n", active[my_group[i]].name, index_file); } } else { index_time = stinfo.st_mtime; } if (debug == 2) { printf ("[%s] [%s] idxtime=[%ld] old=[%ld] new=[%ld]\n", active[my_group[i]].name, index_file, index_time, active[my_group[i]].last_updated_time, group_time); } if (index_time == 0L || active[my_group[i]].last_updated_time == 0L || group_time > active[my_group[i]].last_updated_time || purge_index_files) { active[my_group[i]].last_updated_time = group_time; } else { continue; } #endif if (verbose) { printf ("%s %s\n", (catchup ? "Catchup" : "Updating"), active[my_group[i]].name); fflush (stdout); } if (! index_group (active[my_group[i]].name, group_path)) { continue; } if (catchup) { for (j = 0; j < top; j++) { arts[j].unread = ART_READ; } update_newsrc (active[my_group[i]].name, my_group[i], FALSE); } } /* * save last updated times for each group (tind daemon only) */ write_active_times_file (); if (verbose) { time (&end_epoch); sprintf (msg, txt_catchup_update_info, (catchup ? "Caughtup" : "Updated"), group_top, end_epoch - beg_epoch); wait_message (msg); } } int artnum_comp (p1, p2) t_comptype *p1; t_comptype *p2; { struct t_article *s1 = (struct t_article *) p1; struct t_article *s2 = (struct t_article *) p2; /* * s1->artnum less than s2->artnum */ if (s1->artnum < s2->artnum) { return -1; } /* * s1->artnum greater than s2->artnum */ if (s1->artnum > s2->artnum) { return 1; } return 0; } int subj_comp (p1, p2) t_comptype *p1; t_comptype *p2; { int retval; struct t_article *s1 = (struct t_article *) p1; struct t_article *s2 = (struct t_article *) p2; /* * return result of strcmp (reversed for descending) */ return (active[my_group[cur_groupnum]].attribute.sort_art_type == SORT_BY_SUBJ_ASCEND ? (retval = my_stricmp (s1->subject, s2->subject)) ? retval : ((s1->date - s2->date) > 0) ? 1 : -1 : (retval = my_stricmp (s2->subject, s1->subject)) ? retval : ((s1->date - s2->date) > 0) ? 1 : -1); } int from_comp (p1, p2) t_comptype *p1; t_comptype *p2; { int retval; struct t_article *s1 = (struct t_article *) p1; struct t_article *s2 = (struct t_article *) p2; /* * return result of strcmp (reversed for descending) */ return (active[my_group[cur_groupnum]].attribute.sort_art_type == SORT_BY_FROM_ASCEND ? (retval = my_stricmp (s1->from, s2->from)) ? retval : ((s1->date - s2->date) > 0) ? 1 : -1 : (retval = my_stricmp (s2->from, s1->from)) ? retval : ((s1->date - s2->date) > 0) ? 1 : -1); } int date_comp (p1, p2) t_comptype *p1; t_comptype *p2; { struct t_article *s1 = (struct t_article *) p1; struct t_article *s2 = (struct t_article *) p2; if (active[my_group[cur_groupnum]].attribute.sort_art_type == SORT_BY_DATE_ASCEND) { /* * s1->date less than s2->date */ if (s1->date < s2->date) { return -1; } /* * s1->date greater than s2->date */ if (s1->date > s2->date) { return 1; } } else { /* * s2->date less than s1->date */ if (s2->date < s1->date) { return -1; } /* * s2->date greater than s1->date */ if (s2->date > s1->date) { return 1; } } return 0; } void set_article (art) struct t_article *art; { art->subject = (char *) 0; art->from = (char *) 0; art->name = (char *) 0; art->date = 0L; art->xref = (char *) 0; art->lines = -1; art->archive = (char *) 0; art->part = (char *) 0; art->patch = (char *) 0; art->unread = ART_UNREAD; art->inthread = FALSE; art->killed = FALSE; art->tagged = FALSE; art->hot = FALSE; art->zombie = FALSE; } int input_pending () { #ifdef HAVE_SELECT int fd = STDIN_FILENO; fd_set fdread; struct timeval tvptr; FD_ZERO(&fdread); tvptr.tv_sec = 0; tvptr.tv_usec = 0; FD_SET(fd, &fdread); if (select (1, &fdread, NULL, NULL, &tvptr)) { if (FD_ISSET(fd, &fdread)) { return TRUE; } } #endif /* HAVE_SELECT */ #if defined(HAVE_POLL) && !defined(HAVE_SELECT) static int timeout = 0; static long nfds = 1; static struct pollfd fds[]= { STDIN_FILENO, POLLIN, 0 }; if (poll (fds, nfds, timeout) < 0) { /* * Error on poll */ return FALSE; } switch (fds[0].revents) { case POLLIN: return TRUE; break; /* * Other conditions on the stream */ case POLLHUP: case POLLERR: default: return FALSE; break; } #endif /* HAVE_POLL */ return FALSE; } int valid_artnum (art) long art; { register int prev, range; register int dtop = top; register int cur = 1; while (dtop /= 2) { cur = cur << 1; } range = cur / 2; cur--; while (1) { if (arts[cur].artnum == art) { return cur; } prev = cur; if (arts[cur].artnum < art) { cur = cur + range; } else { cur = cur - range; } if (prev == cur) { return -1; } if (cur >= top) { cur = top - 1; } range = range / 2; } } rð*[SRC.TIN-1_22]BISON.SIMPLE;2+,¯.!//€ 4! I-d0ú123KÿPWO!56ଡ଼ۼ‹—7 ì†u¿‹—89€]V‚—G/€HªJÿ/* -*-C-*- Note some compilers choke on comments on `#line' lines. */ #line 3 "bison.simple" /* Skeleton output parser for bison, Copyright (C) 1984, 1989, 1990 Bob Corbett and Richard Stallman This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 1, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef alloca #ifdef __GNUC__ #define alloca __builtin_alloca #else /* not GNU C. */ #if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) || defined (__sparc) || defined (__sgi) #include #else /* not sparc */ #if defined (MSDOS) && !defined (__TURBOC__) #include #else /* not MSDOS, or __TURBOC__ */ #if defined(_AIX) #include #pragma alloca #else /* not MSDOS, __TURBOC__, or _AIX */ #ifdef __hpux #ifdef __cplusplus extern "C" { void *alloca (unsigned int); }; #else /* not __cplusplus */ void *alloca (); #endif /* not __cplusplus */ #endif /* __hpux */ #endif /* not _AIX */ #endif /* not MSDOS, or __TURBOC__ */ #endif /* not sparc. */ #endif /* not GNU C. */ #endif /* alloca not defined. */ /* This is the parser code that is written into each bison parser when the %semantic_parser declaration is not specified in the grammar. It was written by Richard Stallman by simplifying the hairy parser used when %semantic_parser is specified. */ /* Note: there must be only one dollar sign in this file. It is replaced by the list of actions, each action as one case of the switch. */ #define yyerrok (yyerrstatus = 0) #define yyclearin (yychar = YYEMPTY) #define YYEMPTY -2 #define YYEOF 0 #define YYACCEPT return(0) #define YYABORT return(1) #define YYERROR goto yyerrlab1 /* Like YYERROR except do call yyerror. This remains here temporarily to ease the transition to the new meaning of YYERROR, for GCC. Once GCC version 2 has supplanted version 1, this can go. */ #define YYFAIL goto yyerrlab #define YYRECOVERING() (!!yyerrstatus) #define YYBACKUP(token, value) \ do \ if (yychar == YYEMPTY && yylen == 1) \ { yychar = (token), yylval = (value); \ yychar1 = YYTRANSLATE (yychar); \ YYPOPSTACK; \ goto yybackup; \ } \ else \ { yyerror ("syntax error: cannot back up"); YYERROR; } \ while (0) #define YYTERROR 1 #define YYERRCODE 256 #ifndef YYPURE #define YYLEX yylex() #endif #ifdef YYPURE #ifdef YYLSP_NEEDED #define YYLEX yylex(&yylval, &yylloc) #else #define YYLEX yylex(&yylval) #endif #endif /* If nonreentrant, generate the variables here */ #ifndef YYPURE int yychar; /* the lookahead symbol */ YYSTYPE yylval; /* the semantic value of the */ /* lookahead symbol */ #ifdef YYLSP_NEEDED YYLTYPE yylloc; /* location data for the lookahead */ /* symbol */ #endif int yynerrs; /* number of parse errors so far */ #endif /* not YYPURE */ #if YYDEBUG != 0 int yydebug; /* nonzero means print parse trace */ /* Since this is uninitialized, it does not stop multiple parsers fromÐ |ñV~ TIN-1_22.BCK¯d[SRC.TIN-1_22]BISON.SIMPLE;2!Ûü coexisting. */ #endif /* YYINITDEPTH indicates the initial size of the parser's stacks */ #ifndef YYINITDEPTH #define YYINITDEPTH 200 #endif /* YYMAXDEPTH is the maximum size the stacks can grow to (effective only if the built-in stack extension method is used). */ #if YYMAXDEPTH == 0 #undef YYMAXDEPTH #endif #ifndef YYMAXDEPTH #define YYMAXDEPTH 10000 #endif /* Prevent warning if -Wstrict-prototypes. */ #ifdef __GNUC__ int yyparse (void); #endif #if __GNUC__ > 1 /* GNU C and GNU C++ define this. */ #define __yy_bcopy(FROM,TO,COUNT) __builtin_memcpy(TO,FROM,COUNT) #else /* not GNU C or C++ */ #ifndef __cplusplus /* This is the most reliable way to avoid incompatibilities in available built-in functions on various systems. */ static void __yy_bcopy (from, to, count) char *from; char *to; int count; { register char *f = from; register char *t = to; register int i = count; while (i-- > 0) *t++ = *f++; } #else /* __cplusplus */ /* This is the most reliable. way to avoid incompatibilities in available built-in functions on various systems. */ static void __yy_bcopy (char *from, char *to, int count) { register char *f = from; register char *t = to; register int i = count; while (i-- > 0) *t++ = *f++; } #endif #endif #line 184 "bison.simple" int yyparse() { register int yystate; register int yyn;