1 /* $Id: common.h,v 3.0 1992/02/23 21:25:39 davison Trn $
2  */
3 /* This software is Copyright 1991 by Stan Barber.
4  *
5  * Permission is hereby granted to copy, reproduce, redistribute or otherwise
6  * use this software as long as: there is no monetary profit gained
7  * specifically from the use or reproduction of this software, it is not
8  * sold, rented, traded or otherwise marketed, and this copyright notice is
9  * included prominently in any copy made.
10  *
11  * The authors make no claims as to the fitness or correctness of this software
12  * for any use whatsoever, and it is provided as is. Any use of this software
13  * is at the user's own risk.
14  */
15 
16 #include <stdio.h>
17 #include <sys/types.h>
18 #include <sys/stat.h>
19 
20 #ifndef S_ISDIR
21 #define S_ISDIR(m)  ( ((m) & S_IFMT) == S_IFDIR )
22 #endif
23 #ifndef S_ISCHR
24 #define S_ISCHR(m)  ( ((m) & S_IFMT) == S_IFCHR )
25 #endif
26 #ifndef S_ISREG
27 #define S_ISREG(m)  ( ((m) & S_IFMT) == S_IFREG )
28 #endif
29 
30 #include <ctype.h>
31 #include "config.h"	/* generated by installation script */
32 #ifndef isalnum
33 #   define isalnum(c) (isalpha(c) || isdigit(c))
34 #endif
35 
36 #include <errno.h>
37 #include <signal.h>
38 #ifdef I_SYS_FILIO
39 # include <sys/filio.h>
40 #else
41 # ifdef I_SYS_IOCTL
42 #   include <sys/ioctl.h>
43 # endif
44 #endif
45 #ifdef I_VFORK
46 # include <vfork.h>
47 #endif
48 #include <fcntl.h>
49 
50 #ifdef I_TERMIO
51 # include <termio.h>
52 #else
53 # ifdef I_TERMIOS
54 #   include <termios.h>
55 #   if !defined (O_NDELAY)
56 #     define O_NDELAY O_NONBLOCK	/* Posix-style non-blocking i/o */
57 #   endif
58 # else
59 #   include <sgtty.h>
60 # endif
61 #endif
62 
63 #ifdef HAS_GETPWENT
64 #   include <pwd.h>
65 #endif
66 
67 #ifdef I_PTEM
68 #include <sys/stream.h>
69 #include <sys/ptem.h>
70 #endif
71 
72 #ifdef I_UNISTD
73 #include <unistd.h>
74 #endif
75 #ifdef I_STDLIB
76 #include <stdlib.h>
77 #else
78 char	*malloc();
79 char	*realloc();
80 char	*getenv();
81 #endif
82 
83 #ifdef I_STRING
84 #include <string.h>
85 #else
86 #include <strings.h>
87 #endif
88 
89 #ifdef I_TIME
90 #include <time.h>
91 #endif
92 #ifdef I_SYS_TIME
93 #include <sys/time.h>
94 #endif
95 
96 #define BITSPERBYTE 8
97 #define LBUFLEN 1024	/* line buffer length */
98 			/* (don't worry, .newsrc lines can exceed this) */
99 #define CBUFLEN 512	/* command buffer length */
100 #define PUSHSIZE 256
101 #define MAXFILENAME 512
102 #define LONGKEY 25	/* longest keyword */
103 			/* (currently "Content-Transfer-Encoding") */
104 #define FINISHCMD 0177
105 
106 /* some handy defs */
107 
108 #define bool char
109 #define bool_int int
110 #define char_int int
111 #ifndef TRUE
112 #define TRUE (1)
113 #endif
114 #ifndef FALSE
115 #define FALSE (0)
116 #endif
117 #define Null(t) ((t)0)
118 #define Nullch Null(char*)
119 #define Nullfp Null(FILE*)
120 
121 #define Ctl(ch) (ch & 037)
122 
123 #define strNE(s1,s2) (strcmp(s1,s2))
124 #define strEQ(s1,s2) (!strcmp(s1,s2))
125 #define strnNE(s1,s2,l) (strncmp(s1,s2,l))
126 #define strnEQ(s1,s2,l) (!strncmp(s1,s2,l))
127 
128 /* Things we can figure out ourselves */
129 
130 #ifdef SIGTSTP
131 #   define BERKELEY 	/* include job control signals? */
132 #endif
133 
134 #if defined(FIONREAD) || defined(HAS_RDCHK) || defined(O_NDELAY)
135 #   define PENDING
136 #endif
137 
138 #ifdef EUNICE
139 #   define LINKART		/* add 1 level of possible indirection */
140 #   define UNLINK(victim) while (!unlink(victim))
141 #else
142 #   define UNLINK(victim) unlink(victim)
143 #endif
144 
145 /* Valid substitutions for strings marked with % comment are:
146  *	%a	Current article number
147  *	%A	Full name of current article (%P/%c/%a)
148  *		(if LINKART defined, is the name of the real article)
149  *	%b	Destination of a save command, a mailbox or command
150  *	%B	The byte offset to the beginning of the article for saves
151  *		with or without the header
152  *	%c	Current newsgroup, directory form
153  *	%C	Current newsgroup, dot form
154  *	%d	%P/%c
155  *	%D	Old Distribution: line
156  *	%e	Extract program
157  *	%E	Extract destination directory
158  *	%f	Old From: line or Reply-To: line
159  *	%F	Newsgroups to followup to from Newsgroups: and Followup-To:
160  *	%h	Name of header file to pass to mail or news poster
161  *	%H	Host name (yours)
162  *	%i	Old Message-I.D.: line, with <>
163  *	%I	Inclusion indicator
164  *	%l	News administrator login name
165  *	%L	Login name (yours)
166  *	%m	The current mode of trn.
167  *	%M	Number of articles marked with M
168  *	%n	Newsgroups from source article
169  *	%N	Full name (yours)
170  *	%o	Organization (yours)
171  *	%O	Original working directory (where you ran trn from)
172  *	%p	Your private news directory (-d switch)
173  *	%P	Public news spool directory (NEWSSPOOL)
174  *	%r	Last reference (parent article id)
175  *	%q	The last quoted input (via %").
176  *	%R	New references list
177  *	%s	Subject, with all Re's and (nf)'s stripped off
178  *	%S	Subject, with one Re stripped off
179  *	%t	New To: line derived from From: and Reply-To (Internet always)
180  *	%T	New To: line derived from Path:
181  *	%u	Number of unread articles
182  *	%U	Number of unread articles disregarding current article
183  *	%v	Number of unselected articles disregarding current article
184  *	%W	The thread directory root
185  *	%x	News library directory, usually /usr/lib/news
186  *	%X	Rn library directory, usually %x/rn
187  *	%y	The tmp directory to use
188  *	%z	Size of current article in bytes.
189  *	%Z	Number of selected threads.
190  *	%~	Home directory
191  *	%.	Directory containing . files
192  *	%#	count of articles saved in current command (from 1 to n)
193  *	%$	current process number
194  *	%{name} Environment variable "name".  %{name-default} form allowed.
195  *	%[name]	Header line beginning with "Name: ", without "Name: "
196  *	%"prompt"
197  *		Print prompt and insert what is typed.
198  *	%`command`
199  *		Insert output of command.
200  *	%(test_text=pattern?if_text:else_text)
201  *		Substitute if_text if test_text matches pattern, otherwise
202  *		substitute else_text.  Use != for negated match.
203  *		% substitutions are done on test_text, if_text, and else_text.
204  *		(Note: %() only works if CONDSUB defined.)
205  *	%digit	Substitute the text matched by the nth bracket in the last
206  *		pattern that had brackets.  %0 matches the last bracket
207  *		matched, in case you had alternatives.
208  *	%?	Insert a space unless the entire result is > 79 chars, in
209  *		which case the space becomes a newline.
210  *
211  *	Put ^ in the middle to capitalize the first letter: %^C = Rec.humor
212  *	Put _ in the middle to capitalize last component: %_c = net/Jokes
213  *	Put \ in the middle to quote regexp and % characters in the result
214  *	Put > in the middle to return the address portion of a name.
215  *	Put ) in the middle to return the comment portion of a name.
216  *	Put ' in the middle to protect "'"s in arguments you've put in "'"s.
217  *	Put :FMT in the middle to format the result: %:-30.30t
218  *
219  *	~ interpretation in filename expansion happens after % expansion, so
220  *	you could put ~%{NEWSLOGNAME-news} and it will expand correctly.
221  */
222 
223 /* *** System Dependent Stuff *** */
224 
225 /* NOTE: many of these are defined in the config.h file */
226 
227 /* name of organization */
228 #ifndef ORGNAME
229 #   define ORGNAME "ACME Widget Company, Widget Falls, Southern North Dakota"
230 #endif
231 
232 #ifndef MBOXCHAR
233 #   define MBOXCHAR 'F'	/* how to recognize a mailbox by 1st char */
234 #endif
235 
236 #ifndef ROOTID
237 #   define ROOTID 0        /* uid of superuser */
238 #endif
239 
240 #ifdef NORMSIG
241 #   define sigset signal
242 #   define sigignore(sig) signal(sig,SIG_IGN)
243 #endif
244 
245 #ifndef LOGDIRFIELD
246 #   define LOGDIRFIELD 6		/* Which field (origin 1) is the */
247 					/* login directory in /etc/passwd? */
248 					/* (If it is not kept in passwd, */
249 					/* but getpwnam() returns it, */
250 					/* define the symbol HAS_GETPWENT) */
251 #endif
252 #ifndef GCOSFIELD
253 #   define GCOSFIELD 5
254 #endif
255 
256 #ifndef NEGCHAR
257 #   define NEGCHAR '!'
258 #endif
259 
260 /* Space conservation section */
261 
262 /* To save D space, cut down size of NGMAX and  VARYSIZE. */
263 #define NGMAX 100	/* number of newsgroups allowed on command line */
264 			/* undefine ONLY symbol to disable "only" feature */
265 #define VARYSIZE 256	/* this makes a block 1024 bytes long in DECville */
266 			/* (used by virtual array routines) */
267 
268 /* Undefine any of the following features to save both I and D space */
269 /* In general, earlier ones are easier to get along without */
270 #define CUSTOMLINES	/* include code for HIDELINE and PAGESTOP */
271 #define WORDERASE	/* enable ^W to erase a word */
272 #define MAILCALL	/* check periodically for mail */
273 #define CLEAREOL	/* use clear to end-of-line instead of clear screen */
274 #define NOFIREWORKS	/* keep whole screen from flashing on certain */
275 			/* terminals such as older Televideos */
276 #define VERIFY		/* echo the command they just typed */
277 #define HASHNG		/* hash newsgroup lines for fast lookup-- */
278 			/* linear search used if not defined */
279 #define CONDSUB		/* allow %(cond?text:text) */
280 #define BACKTICK	/* allow %`command` */
281 #define PROMPTTTY	/* allow %"prompt" */
282 #define ULSMARTS	/* catch _^H in text and do underlining */
283 #define TERMMOD		/* allow terminal type modifier on switches */
284 #define BAUDMOD		/* allow baudrate modifier on switches */
285 #define GETLOGIN	/* use getlogin() routine as backup to environment */
286 			/* variables USER or LOGNAME */
287 #define ORGFILE		/* if organization begins with /, look up in file */
288 #define TILDENAME	/* allow ~logname expansion */
289 #define SETENV		/* allow command line environment variable setting */
290 #define MAKEDIR		/* use our makedir() instead of shell script */
291 #define MEMHELP		/* keep help messages in memory */
292 #define VERBOSE		/* compile in more informative messages */
293 #define TERSE		/* compile in shorter messages */
294 			/* (Note: both VERBOSE and TERSE can be defined; -t
295 			 * sets terse mode.  One or the other MUST be defined.
296 			 */
297 #define ROTATION	/* enable x, X and ^X commands to work */
298 #define CHARSUBST	/* enable the _C command */
299 #define DELBOGUS	/* ask if bogus newsgroups should be deleted */
300 #define RELOCATE	/* allow newsgroup rearranging */
301 #define ESCSUBS		/* escape substitutions in multi-character commands */
302 #undef MCHASE		/* unmark xrefed articles on m or M */
303 #define MUNGHEADER	/* allow alternate header formatting via */
304 			/* environment variable ALTHEADER (not impl) */
305 #define ASYNC_PARSE	/* allow parsing headers asyncronously to reading */
306 			/* used by MCHASE and MUNGHEADER */
307 #define FINDNEWNG	/* check for new newsgroups on startup */
308 #define FASTNEW		/* do optimizations on FINDNEWNG for faster startup */
309 			/* (this optimization can make occasional mistakes */
310 			/* if a group is removed and another group of the */
311 			/* same length is added, and if no softpointers are */
312 			/* affected by said change.) */
313 #define INNERSEARCH	/* search command 'g' with article */
314 #define CATCHUP		/* catchup command at newsgroup level */
315 #define NGSEARCH	/* newsgroup pattern matching */
316 #define ONLY		/* newsgroup restrictions by pattern */
317 #define KILLFILES	/* automatic article killer files */
318 #define ARTSEARCH	/* pattern searches among articles */
319 			/* /, ?, ^N, ^P, k, K */
320 #define EDIT_DISTANCE	/* Allow -G to specify a fuzzy 'go' command */
321 #undef	VALIDATE_XREF_SITE /* are xrefs possibly invalid? */
322 
323 /* some dependencies among options */
324 
325 #ifndef ARTSEARCH
326 #   undef KILLFILES
327 #   undef INNERSEARCH
328 #endif
329 
330 #ifndef SETUIDGID
331 #   define eaccess access
332 #endif
333 
334 #ifdef ONLY				/* idiot lint doesn't grok #if */
335 #   define NGSORONLY
336 #else
337 #   ifdef NGSEARCH
338 #	define NGSORONLY
339 #   endif
340 #endif
341 
342 #ifdef VERBOSE
343 #   ifdef TERSE
344 #	define IF(c) if (c)
345 #	define ELSE else
346 #   else
347 #	define IF(c)
348 #	define ELSE
349 #   endif
350 #else /* !VERBOSE */
351 #   ifndef TERSE
352 #	define TERSE
353 #   endif
354 #   define IF(c) "IF" outside of VERBOSE???
355 #   define ELSE "ELSE" outside of VERBOSE???
356 #endif
357 
358 #ifdef DEBUG
359 #   define assert(ex) {if (!(ex)){fprintf(stderr,"Assertion failed: file %s, line %d\n", __FILE__, __LINE__);sig_catcher(0);}}
360 #else
361 #   define assert(ex) ;
362 #endif
363 
364 /* If you're strapped for space use the help messages in shell scripts */
365 /* if {NG,ART,PAGER,SUBS}HELP is undefined, help messages are in memory */
366 #ifdef MEMHELP  /* undef MEMHELP above to get them all as sh scripts */
367 #   undef NGHELP
368 #   undef ARTHELP
369 #   undef PAGERHELP
370 #   undef SUBSHELP
371 #else
372 #   ifndef NGHELP			/* % and ~ */
373 #	define NGHELP "%X/ng.help"
374 #   endif
375 #   ifndef ARTHELP			/* % and ~ */
376 #	define ARTHELP "%X/art.help"
377 #   endif
378 #   ifndef PAGERHELP		/* % and ~ */
379 #	define PAGERHELP "%X/pager.help"
380 #   endif
381 #   ifndef SUBSHELP		/* % and ~ */
382 #	define SUBSHELP "%X/subs.help"
383 #   endif
384 #endif
385 
386 #define TCSIZE 512	/* capacity for termcap strings */
387 
388 #ifdef EDIT_DISTANCE
389 #   define MIN_DIST 7	/* Maximum error count for acceptable match */
390 #endif
391 
392 /* Additional ideas:
393  *	Make the do_newsgroup() routine a separate process.
394  *	Keep .newsrc on disk instead of in memory.
395  *	Overlays, if you have them.
396  *	Get a bigger machine.
397  */
398 
399 /* End of Space Conservation Section */
400 
401 /* More System Dependencies */
402 
403 /* news library */
404 #ifndef NEWSLIB		/* ~ and %l only ("~%l" is permissable) */
405 #   define NEWSLIB "/usr/lib/news"
406 #endif
407 
408 /* path to private executables */
409 #ifndef PRIVLIB		/* ~, %x and %l only */
410 #   define PRIVLIB "%x/trn"
411 #endif
412 
413 /* system-wide RNINIT switches */
414 #ifndef GLOBINIT
415 #   define GLOBINIT "%X/INIT"
416 #endif
417 
418 /* where to find news files */
419 #ifndef NEWSSPOOL		/* % and ~ */
420 #   define NEWSSPOOL "/usr/spool/news"
421 #endif
422 
423 #ifndef THREAD_DIR
424 #   undef LONG_THREAD_NAMES
425 #endif
426 
427 /* default characters to use in the selection menu */
428 #ifndef SELECTCHARS
429 #   define SELECTCHARS "abdefgijlorstuvwxyz1234567890BCFGHIKVW"
430 #endif
431 
432 /* file containing list of active newsgroups and max article numbers */
433 #ifdef USE_NNTP
434 #   undef ACTIVE
435 #   define ACTIVE "%P/rrnact.%$"
436 #else
437 # ifndef ACTIVE			/* % and ~ */
438 #   define ACTIVE "%x/active"
439 # endif
440 #endif
441 #ifndef DBINIT
442 #   define DBINIT "%W/db.init"
443 #endif
444 
445 #ifdef USE_NNTP
446 # ifndef ACTIVE_TIMES
447 #   define APPEND_UNSUB
448 # endif
449 #else
450 # ifdef USE_XTHREAD
451 #   undef USE_XTHREAD
452 # endif
453 # ifdef USE_XOVER
454 #   undef USE_XOVER
455 # endif
456 #endif
457 
458 /* location of history file */
459 #ifndef ARTFILE			/* % and ~ */
460 #    define ARTFILE "%x/history"
461 #endif
462 
463 /* command to setup a new .newsrc */
464 #ifndef NEWSETUP		/* % and ~ */
465 #   define NEWSETUP "newsetup"
466 #endif
467 
468 /* command to display a list of un-subscribed-to newsgroups */
469 #ifndef NEWSGROUPS		/* % and ~ */
470 #   define NEWSGROUPS "newsgroups"
471 #endif
472 
473 /* preferred shell for use in doshell routine */
474 /*  ksh or sh would be okay here */
475 #ifndef PREFSHELL
476 #   define PREFSHELL "/bin/csh"
477 #endif
478 
479 /* path to fastest starting shell */
480 #ifndef SH
481 #   define SH "/bin/sh"
482 #endif
483 
484 /* default unshar'ing program */
485 #ifndef UNSHAR
486 #   define UNSHAR "/bin/sh"
487 #endif
488 
489 /* path to default editor */
490 #ifndef DEFEDITOR
491 #   define DEFEDITOR "/usr/ucb/vi"
492 #endif
493 
494 /* location of macro file for trn and rn modes */
495 #ifndef TRNMACRO
496 #   define TRNMACRO "%./.trnmac"
497 #endif
498 #ifndef RNMACRO
499 #   define RNMACRO "%./.rnmac"
500 #endif
501 
502 /* location of full name */
503 #ifndef FULLNAMEFILE
504 #   ifndef PASSNAMES
505 #	define FULLNAMEFILE "%./.fullname"
506 #   endif
507 #endif
508 
509 /* virtual array file name template */
510 #ifndef VARYNAME		/* % and ~ */
511 #   define VARYNAME "%y/rnvary.%$"
512 #endif
513 
514 /* where to compile a new newsgroup list */
515 #ifndef RNEWNAME
516 #   define RNEWNAME "%y/rnew.%$"
517 #endif
518 
519 /* file to pass header to followup article poster */
520 #ifndef HEADNAME		/* % and ~ */
521 #   define HEADNAME "%./.rnhead"
522 /* or alternately #define HEADNAME "%y/rnhead.%$" */
523 #endif
524 
525 #ifndef MAKEDIR
526 /* shell script to make n-deep subdirectories */
527 #   ifndef DIRMAKER		/* % and ~ */
528 #	define DIRMAKER "%X/makedir"
529 #   endif
530 #endif
531 
532 /* location of newsrc file */
533 #ifndef RCNAME		/* % and ~ */
534 #   define RCNAME "%./.newsrc"
535 #endif
536 
537 /* temporary newsrc file in case we crash while writing out */
538 #ifndef RCTNAME		/* % and ~ */
539 #   define RCTNAME "%./.newnewsrc"
540 #endif
541 
542 /* newsrc file at the beginning of this session */
543 #ifndef RCBNAME		/* % and ~ */
544 #   define RCBNAME "%./.oldnewsrc"
545 #endif
546 
547 /* if existent, contains process number of current or crashed trn */
548 #ifndef LOCKNAME		/* % and ~ */
549 #   define LOCKNAME "%./.rnlock"
550 #endif
551 
552 /* information from last invocation of trn */
553 #ifndef LASTNAME		/* % and ~ */
554 #   define LASTNAME "%./.rnlast"
555 #endif
556 
557 /* file with soft pointers into the active file */
558 #ifndef SOFTNAME		/* % and ~ */
559 #   define SOFTNAME "%./.rnsoft"
560 #endif
561 
562 /* list of article numbers to mark as unread later (see M and Y cmmands) */
563 #ifndef RNDELNAME		/* % and ~ */
564 #   define RNDELNAME "%./.rndelay"
565 #endif
566 
567 /* a motd-like file for trn */
568 #ifndef NEWSNEWSNAME		/* % and ~ */
569 #   define NEWSNEWSNAME "%X/newsnews"
570 #endif
571 
572 /* command to send a reply */
573 #ifndef MAILPOSTER		/* % and ~ */
574 #   define MAILPOSTER "QUOTECHARS=%I Rnmail -h %h"
575 #endif
576 
577 #ifdef INTERNET
578 #   ifndef MAILHEADER		/* % */
579 #	ifdef CONDSUB
580 #	    define MAILHEADER "To: %t\nSubject: %(%i=^$?:Re: %S\n%(%{REPLYTO}=^$?:Reply-To: %{REPLYTO}\n)Newsgroups: %n\nIn-Reply-To: %i)\n%(%[references]=^$?:References: %[references]\n)Organization: %o\nCc: \nBcc: \n\n"
581 #	else
582 #	    define MAILHEADER "To: %t\nSubject: Re: %S\nNewsgroups: %n\nIn-Reply-To: %i\nReferences: %[references]\nCc: \nBcc: \n\n"
583 #	endif
584 #   endif
585 #else
586 #   ifndef MAILHEADER		/* % */
587 #	ifdef CONDSUB
588 #	    define MAILHEADER "To: %T\nSubject: %(%i=^$?:Re: %S\n%(%{REPLYTO}=^$?:Reply-To: %{REPLYTO}\n)Newsgroups: %n\nIn-Reply-To: %i)\n%(%[references]=^$?:References: %[references]\n)Organization: %o\nCc: \nBcc: \n\n"
589 #	else
590 #	    define MAILHEADER "To: %T\nSubject: Re: %S\nNewsgroups: %n\nIn-Reply-To: %i\nReferences: %[references]\nCc: \nBcc: \n\n"
591 #	endif
592 #   endif
593 #endif
594 
595 #ifndef YOUSAID			/* % */
596 #   define YOUSAID "In article %i you write:"
597 #endif
598 
599 /* command to forward an article */
600 #define FORWARDPOSTER MAILPOSTER
601 
602 #ifdef INTERNET
603 #   ifndef FORWARDHEADER	/* % */
604 #	ifdef CONDSUB
605 #	    define FORWARDHEADER "To: %\"\n\nTo: \"\nSubject: %(%i=^$?:%[subject] (fwd\\)\n%(%{REPLYTO}=^$?:Reply-To: %{REPLYTO}\n)Newsgroups: %n\nIn-Reply-To: %i)\n%(%[references]=^$?:References: %[references]\n)Organization: %o\nCc: \nBcc: \n\n"
606 #	else
607 #	    define FORWARDHEADER "To: \nSubject: %[subject] (fwd)\nNewsgroups: %n\nIn-Reply-To: %i\nReferences: %[references]\nCc: \nBcc: \n\n"
608 #	endif
609 #   endif
610 #else
611 #   ifndef FORWARDHEADER	/* % */
612 #	ifdef CONDSUB
613 #	    define FORWARDHEADER "To: %\"\n\nTo: \"\nSubject: %(%i=^$?:%[subject] (fwd\\)\n%(%{REPLYTO}=^$?:Reply-To: %{REPLYTO}\n)Newsgroups: %n\nIn-Reply-To: %i)\n%(%[references]=^$?:References: %[references]\n)Organization: %o\nCc: \nBcc: \n\n"
614 #	else
615 #	    define FORWARDHEADER "To: \nSubject: %[subject] (fwd)\nNewsgroups: %n\nIn-Reply-To: %i\nReferences: %[references]\nCc: \nBcc: \n\n"
616 #	endif
617 #   endif
618 #endif
619 
620 #ifndef FORWARDMSG		/* % */
621 #   define FORWARDMSG "------- start of forwarded message -------"
622 #endif
623 
624 #ifndef FORWARDMSGEND		/* % */
625 #   define FORWARDMSGEND "------- end of forwarded message -------"
626 #endif
627 
628 /* command to submit a followup article */
629 #ifndef NEWSPOSTER		/* % and ~ */
630 #   define NEWSPOSTER "QUOTECHARS=%I Pnews -h %h"
631 #endif
632 
633 #ifndef NEWSHEADER		/* % */
634 #   ifdef CONDSUB
635 #	define NEWSHEADER "%(%[followup-to]=^$?:%(%[followup-to]=^%n$?:X-ORIGINAL-NEWSGROUPS: %n\n))Newsgroups: %(%F=^$?%C:%F)\nSubject: %(%S=^$?%\"\n\nSubject: \":Re: %S)\nSummary: \nExpires: \n%(%R=^$?:References: %R\n)Sender: \nFollowup-To: \n%(%{REPLYTO}=^$?:Reply-To: %{REPLYTO}\n)Distribution: %(%i=^$?%\"Distribution: \":%D)\nOrganization: %o\nKeywords: %[keywords]\nCc: %(%F=poster?%t:%(%F!=@?:%F))\n\n"
636 #   else
637 #	define NEWSHEADER "Newsgroups: %F\nSubject: Re: %S\nSummary: \nExpires: \nReferences: %R\nSender: \nFollowup-To: \nDistribution: %D\nOrganization: %o\nKeywords: %[keywords]\nCc: \n\n"
638 #   endif
639 #endif
640 
641 #ifndef ATTRIBUTION		/* % */
642 #   define ATTRIBUTION "In article %i,%?%)f <%>f> wrote:"
643 #endif
644 
645 #ifndef PIPESAVER		/* % */
646 #   ifdef CONDSUB
647 #	define PIPESAVER "%(%B=^0$?<%A:tail +%Bc %A |) %b"
648 #   else
649 #	define PIPESAVER "tail +%Bc %A | %b"
650 #   endif
651 #endif
652 
653 #ifndef EXSAVER
654 #   define EXSAVER "tail +%Bc %A | %e"
655 #endif
656 
657 #ifdef MIMESTORE
658 #  ifndef EXMIMESAVER
659 #    define EXMIMESAVER "%e %A"
660 #  endif
661 #endif
662 
663 #ifndef NORMSAVER		/* % and ~ */
664 #   define NORMSAVER "%X/norm.saver %A %P %c %a %B %C \"%b\""
665 #endif
666 
667 #ifndef MBOXSAVER		/* % and ~ */
668 #   ifndef ANCIENT_NEWS
669 #	define MBOXSAVER "%X/mbox.saver %A %P %c %a %B %C \"%b\" \"From %t %`LANG= date`\""
670 #   else
671 #	ifdef CONDSUB
672 #	    define MBOXSAVER "%X/mbox.saver %A %P %c %a %B %C \"%b\" \"From %t %(%[date]=^\\(\\w*\\), \\(\\w*\\)-\\(\\w*\\)-\\(\\w*\\) \\([^ ]*\\)?%1 %3 %(%2=..?%2: %2) %5 19%4)\""
673 					/* header munging with a vengeance */
674 #	else
675 #	    define MBOXSAVER "%X/mbox.saver %A %P %c %a %B %C \"%b\" \"From %t %[posted]\""
676 #	endif
677 #   endif
678 #endif
679 
680 #ifdef MKDIRS
681 
682 #   ifndef SAVEDIR			/* % and ~ */
683 #	define SAVEDIR "%p/%c"
684 #   endif
685 #   ifndef SAVENAME		/* % */
686 #	define SAVENAME "%a"
687 #   endif
688 
689 #else
690 
691 #   ifndef SAVEDIR			/* % and ~ */
692 #	define SAVEDIR "%p"
693 #   endif
694 #   ifndef SAVENAME		/* % */
695 #	define SAVENAME "%^C"
696 #   endif
697 
698 #endif
699 
700 #ifndef KILLGLOBAL		/* % and ~ */
701 #   define KILLGLOBAL "%p/KILL"
702 #endif
703 
704 #ifndef KILLLOCAL		/* % and ~ */
705 #   define KILLLOCAL "%p/%c/KILL"
706 #endif
707 
708 /* how to cancel an article */
709 #ifndef CANCEL
710 #   ifdef BNEWS
711 #	define CANCEL "%x/inews -h < %h"
712 #   else
713 #	define CANCEL "inews -h < %h"
714 #   endif
715 #endif
716 
717 /* how to cancel an article, continued */
718 #ifndef CANCELHEADER
719 #   define CANCELHEADER "Newsgroups: %n\nSubject: cancel\nControl: cancel %i\nDistribution: %D\n\n%i was cancelled from within trn.\n"
720 #endif
721 
722 /* how to supersede an article */
723 #ifndef SUPERSEDEHEADER
724 #   define SUPERSEDEHEADER "Newsgroups: %n\nSubject: %S\nSummary: %[summary]\nExpires: %[expires]\nReferences: %[references]\nSupersedes: %i\nSender: %[sender]\nFollowup-To: %[followup-to]\nDistribution: %D\nOrganization: %o\nKeywords: %[keywords]\n\n"
725 #endif
726 
727 #ifndef LOCALTIMEFMT
728 #   define LOCALTIMEFMT "%a %b %d %X %Z %Y"
729 #endif
730 
731 /* where to find the mail file */
732 #ifndef MAILFILE
733 #   define MAILFILE "/usr/spool/mail/%L"
734 #endif
735 
736 /* how to open binary format files */
737 #ifndef FOPEN_RB
738 #   define FOPEN_RB "r"
739 #endif
740 #ifndef FOPEN_WB
741 #   define FOPEN_WB "w"
742 #endif
743 
744 /* what to do with ansi prototypes -- '()' == ignore, 'x' == use */
745 #ifndef _
746 #   ifdef __STDC__
747 #	define _(x) x
748 #	ifndef CONST
749 #	    define CONST const
750 #	endif
751 #   else
752 #	define _(x) ()
753 #	ifndef CONST
754 #	    define CONST
755 #	endif
756 #   endif
757 #endif
758 
759 /* how many characters is a newline in a text file? */
760 #ifndef NL_SIZE
761 #   define NL_SIZE 1
762 #endif
763 
764 /* some important types */
765 
766 typedef int		NG_NUM;		/* newsgroup number */
767 typedef long		ART_NUM;	/* article number */
768 typedef long		ART_UNREAD;	/* could be short to save space */
769 typedef long		ART_POS;	/* char position in article file */
770 typedef int		ART_LINE;	/* line position in article file */
771 typedef long		ACT_POS;	/* char position in active file */
772 typedef unsigned int	MEM_SIZE;	/* for passing to malloc */
773 
774 /* some slight-of-hand for compatibility issues */
775 
776 #ifdef HAS_STRCHR
777 # ifndef index
778 #   define index strchr
779 # endif
780 # ifndef rindex
781 #   define rindex strrchr
782 # endif
783 #endif
784 #ifdef HAS_MEMCMP
785 # ifndef bcmp
786 #   define bcmp(s,d,l) memcmp((s),(d),(l))
787 # endif
788 #endif
789 #ifdef HAS_MEMCPY
790 # ifndef bcopy
791 #   define bcopy(s,d,l) memcpy((d),(s),(l))
792 # endif
793 #endif
794 #ifdef HAS_MEMSET
795 # ifndef bzero
796 #   define bzero(s,l) memset((s),0,(l))
797 # endif
798 #endif
799 
800 #ifndef HAS_VFORK
801 #   define vfork fork
802 #endif
803 
804 /* *** end of the machine dependent stuff *** */
805 
806 /* GLOBAL THINGS */
807 
808 /* file statistics area */
809 
810 EXT struct stat filestat;
811 
812 /* various things of type char */
813 
814 #ifdef SUPPLEMENT_STRING_H
815 char	*index();
816 char	*rindex();
817 char	*strcat();
818 char	*strcpy();
819 #endif
820 
821 EXT char buf[LBUFLEN+1];	/* general purpose line buffer */
822 EXT char cmd_buf[CBUFLEN];	/* buffer for formatting system commands */
823 EXT char *indstr INIT(">");	/* indent for old article embedded in followup */
824 
825 EXT char *cwd INIT(Nullch);		/* current working directory */
826 EXT char *dfltcmd INIT(Nullch);	/* 1st char is default command */
827 
828 /* switches */
829 
830 #ifdef DEBUG
831     EXT int debug INIT(0);				/* -D */
832 #   define DEB_COREDUMPSOK 2
833 #   define DEB_HEADER 4
834 #   define DEB_INTRP 8
835 #   define DEB_NNTP 16
836 #   define DEB_INNERSRCH 32
837 #   define DEB_FILEXP 64
838 #   define DEB_HASH 128
839 #   define DEB_XREF_MARKER 256
840 #   define DEB_CTLAREA_BITMAP 512
841 #   define DEB_SOFT_POINTERS 1024
842 #   define DEB_NEWSRC_LINE 2048
843 #   define DEB_SEARCH_AHEAD 4096
844 #   define DEB_CHECKPOINTING 8192
845 #   define DEB_FEED_XREF 16384
846 #endif
847 
848 #ifdef ARTSEARCH
849     EXT int scanon INIT(0);				/* -S */
850 #endif
851 
852 EXT bool use_threads INIT(THREAD_INIT);			/* -x */
853 EXT int max_tree_lines INIT(6);
854 EXT char select_order[4] INIT("lms");
855 EXT int select_on INIT(SELECT_INIT);			/* -X */
856 EXT char end_select INIT('Z');
857 EXT char page_select INIT('>');
858 
859 EXT bool dont_filter_control INIT(FALSE);		/* -j */
860 EXT int  join_subject_len INIT(0);			/* -J */
861 EXT bool kill_thru_kludge INIT(TRUE);			/* -k */
862 EXT bool keep_the_group_static INIT(FALSE);		/* -K */
863 EXT bool mbox_always INIT(FALSE);			/* -M */
864 EXT bool norm_always INIT(FALSE);			/* -N */
865 EXT bool thread_always INIT(FALSE);			/* -a */
866 EXT bool auto_arrow_macros INIT(TRUE);			/* -B */
867 EXT bool breadth_first INIT(FALSE);			/* -b */
868 EXT bool bkgnd_spinner INIT(FALSE);			/* -B */
869 EXT bool novice_delays INIT(TRUE);			/* +f */
870 EXT int olden_days INIT(FALSE);				/* -o */
871 EXT char auto_select_postings INIT(0);			/* -p */
872 EXT bool checkflag INIT(FALSE);				/* -c */
873 EXT bool suppress_cn INIT(FALSE);			/* -s */
874 EXT int countdown INIT(5);	/* how many lines to list before invoking -s */
875 EXT bool muck_up_clear INIT(FALSE);			/* -loco */
876 EXT bool erase_screen INIT(FALSE);			/* -e */
877 EXT bool can_home INIT(FALSE);
878 #ifdef CLEAREOL
879 EXT bool can_home_clear INIT(FALSE);		/* fancy -e */
880 #endif
881 EXT bool findlast INIT(FALSE);			/* -r */
882 EXT bool typeahead INIT(FALSE);			/* -T */
883 #ifdef EDIT_DISTANCE
884 EXT bool fuzzyGet INIT(FALSE);			/* -G */
885 #endif
886 #ifdef VERBOSE
887 #   ifdef TERSE
888 EXT bool verbose INIT(TRUE);				/* +t */
889 #   endif
890 #endif
891 EXT bool unbroken_subjects INIT(FALSE);			/* -u */
892 EXT bool unsafe_rc_saves INIT(FALSE);			/* -U */
893 #ifdef VERIFY
894 EXT bool verify INIT(FALSE);				/* -v */
895 #endif
896 EXT bool quickstart INIT(FALSE);			/* -q */
897 EXT time_t actFetchTime					/* -z */
898 #ifdef USE_NNTP
899 	INIT(5*60);
900 #else
901 	INIT(0);
902 #endif
903 EXT int try_ov						/* -Z */
904 #ifdef USE_OV
905 	INIT(1);
906 #else
907 	INIT(0);
908 #endif
909 EXT int try_mt
910 #ifdef USE_MT
911 	INIT(1);
912 #else
913 	INIT(0);
914 #endif
915 
916 #define NOMARKING 0
917 #define STANDOUT 1
918 #define UNDERLINE 2
919 EXT int marking INIT(NOMARKING);			/* -m */
920 #define HALFPAGE_MARKING 1
921 #define BACKPAGE_MARKING 2
922 EXT int marking_areas INIT(HALFPAGE_MARKING);
923 
924 EXT ART_LINE initlines INIT(0);				/* -i */
925 EXT bool initlines_specified INIT(FALSE);
926 #ifdef APPEND_UNSUB
927 EXT bool append_unsub INIT(1);				/* -I */
928 #else
929 EXT bool append_unsub INIT(0);
930 #endif
931 
932 /* miscellania */
933 
934 #ifndef __STDC__
935 int fseek();
936 long atol(), ftell();
937 extern int errno;
938 #endif
939 
940 EXT bool in_ng INIT(FALSE);		/* current state of trn */
941 EXT char mode INIT('i');		/* current state of trn */
942 
943 EXT FILE *tmpfp INIT(Nullfp);	/* scratch fp used for .rnlock, .rnlast, etc. */
944 
945 EXT NG_NUM nextrcline INIT(0);	/* 1st unused slot in rcline array */
946 				/* startup to avoid checking twice in a row */
947 
948 /* Factored strings */
949 
950 EXT char nullstr[1] INIT("");
951 EXT char sh[] INIT(SH);
952 EXT char defeditor[] INIT(DEFEDITOR);
953 EXT char hforhelp[] INIT("Type h for help.\n");
954 #ifdef STRICTCR
955 EXT char badcr[] INIT("\nUnnecessary CR ignored.\n");
956 #endif
957 EXT char readerr[] INIT("rn read error");
958 EXT char unsubto[] INIT("\n\nUnsubscribed to newsgroup %s\n");
959 EXT char cantopen[] INIT("Can't open %s\n");
960 EXT char cantcreate[] INIT("Can't create %s\n");
961 EXT char cantrecreate[] INIT("Can't recreate %s -- restoring older version.\n");
962 
963 #ifdef VERBOSE
964     EXT char nocd[] INIT("Can't chdir to directory %s\n");
965 #else
966     EXT char nocd[] INIT("Can't find %s\n");
967 #endif
968 
969 #if defined(MIMESHOW) || defined(MIMESTORE)
970 EXT bool mime_article INIT(FALSE);
971 #endif
972 
973 #ifdef NOLINEBUF
974 #define FLUSH ,fflush(stdout)
975 #else
976 #define FLUSH
977 #endif
978 
979 #ifdef lint
980 #undef FLUSH
981 #define FLUSH
982 #undef putchar
983 #define putchar(c)
984 #endif
985 
986 #define nntp_advise(str) fputs(str,stdout)
987 #define nntp_init_error(str) fputs(str,stderr)
988 #define nntp_error(str) fputs(str,stderr)
989 #define NNTP_ERROR_IS_FATAL
990 #define NNTP_HANDLE_TIMEOUT
991 #define NNTP_HANDLE_AUTH_ERR
992