1 /* common.h
2  */
3 /* This software is copyrighted as detailed in the LICENSE file. */
4 
5 
6 #include <stdio.h>
7 #include <sys/types.h>
8 #include <sys/stat.h>
9 
10 #include <ctype.h>
11 #include "config.h"	/* generated by installation script */
12 #include "config2.h"
13 
14 #include <errno.h>
15 #include <signal.h>
16 #ifdef I_SYS_FILIO
17 # include <sys/filio.h>
18 #else
19 # ifdef I_SYS_IOCTL
20 #   include <sys/ioctl.h>
21 # endif
22 #endif
23 #ifdef I_VFORK
24 # include <vfork.h>
25 #endif
26 #include <fcntl.h>
27 
28 #ifdef I_TERMIO
29 # include <termio.h>
30 #else
31 # ifdef I_TERMIOS
32 #   include <termios.h>
33 #   if !defined (O_NDELAY)
34 #     define O_NDELAY O_NONBLOCK	/* Posix-style non-blocking i/o */
35 #   endif
36 # else
37 #   ifdef I_SGTTY
38 #     include <sgtty.h>
39 #   endif
40 # endif
41 #endif
42 
43 #ifdef I_PTEM
44 #include <sys/stream.h>
45 #include <sys/ptem.h>
46 #endif
47 
48 #ifdef I_TIME
49 #include <time.h>
50 #endif
51 #ifdef I_SYS_TIME
52 #include <sys/time.h>
53 #endif
54 
55 #include "typedef.h"
56 
57 #define BITSPERBYTE 8
58 #define LBUFLEN 1024	/* line buffer length */
59 			/* (don't worry, .newsrc lines can exceed this) */
60 #define CBUFLEN 512	/* command buffer length */
61 #define PUSHSIZE 256
62 #define MAXFILENAME 512
63 #define FINISHCMD 0177
64 #define OV_MAX_FIELDS 9
65 
66 /* Things we can figure out ourselves */
67 
68 #ifdef SIGTSTP
69 #   define BERKELEY 	/* include job control signals? */
70 #endif
71 
72 #if defined(FIONREAD) || defined(HAS_RDCHK) || defined(O_NDELAY) || defined(MSDOS)
73 #   define PENDING
74 #endif
75 
76 #ifdef EUNICE
77 #   define LINKART		/* add 1 level of possible indirection */
78 #   define UNLINK(victim) while (!unlink(victim))
79 #else
80 #   define UNLINK(victim) unlink(victim)
81 #endif
82 
83 #ifdef HAS_RENAME
84 #   define RENAME(from,to) rename(from,to)
85 #else
86 #   define RENAME(from,to) safelink(from,to), UNLINK(from)
87 #endif
88 
89 #ifdef HAS_STRSTR
90 #   define STRSTR(s1,s2) strstr((s1),(s2))
91 #else
92 #   define STRSTR(s1,s2) trn_strstr((s1),(s2))
93 #endif
94 
95 /* Valid substitutions for strings marked with % comment are:
96  *	%a	Current article number
97  *	%A	Full name of current article (%P/%c/%a)
98  *		(if LINKART defined, is the name of the real article)
99  *	%b	Destination of a save command, a mailbox or command
100  *	%B	The byte offset to the beginning of the article for saves
101  *		with or without the header
102  *	%c	Current newsgroup, directory form
103  *	%C	Current newsgroup, dot form
104  *	%d	%P/%c
105  *	%D	Old Distribution: line
106  *	%e	Extract program
107  *	%E	Extract destination directory
108  *	%f	Old From: line or Reply-To: line
109  *	%F	Newsgroups to followup to from Newsgroups: and Followup-To:
110  *	%h	Name of header file to pass to mail or news poster
111  *	%H	Host name (yours)
112  *	%i	Old Message-I.D.: line, with <>
113  *	%j	The terminal speed (e.g. 9600)
114  *	%I	Inclusion indicator
115  *	%l	News administrator login name
116  *	%L	Login name (yours)
117  *	%m	The current mode of trn.
118  *	%M	Number of articles marked with M
119  *	%n	Newsgroups from source article
120  *	%N	Full name (yours)
121  *	%o	Organization (yours)
122  *	%O	Original working directory (where you ran trn from)
123  *	%p	Your private news directory (-d switch)
124  *	%P	Public news spool directory (NEWSSPOOL)
125  *	%r	Last reference (parent article id)
126  *	%q	The last quoted input (via %").
127  *	%R	New references list
128  *	%s	Subject, with all Re's and (nf)'s stripped off
129  *	%S	Subject, with one Re stripped off
130  *	%t	New To: line derived from From: and Reply-To (Internet always)
131  *	%T	New To: line derived from Path:
132  *	%u	Number of unread articles
133  *	%U	Number of unread articles disregarding current article
134  *	%v	Number of unselected articles disregarding current article
135  *	%W	The thread directory root
136  *	%x	News library directory, usually /usr/lib/news
137  *	%X	Trn's private library directory, usually %x/trn
138  *	%y	From line with domain shortening (name@*.domain.nam)
139  *	%Y	The tmp directory to use
140  *	%z	Size of current article in bytes.
141  *	%Z	Number of selected threads.
142  *	%~	Home directory
143  *	%.	Directory containing . files, usually %~
144  *	%+	Directory containing a user's init files, usually %./.trn
145  *	%#	count of articles saved in current command (from 1 to n)
146  *	%^#	ever-increasing number (from 1 to n)
147  *	%$	current process number
148  *	%{name} Environment variable "name".  %{name-default} form allowed.
149  *	%[name]	Header line beginning with "Name: ", without "Name: "
150  *	%"prompt"
151  *		Print prompt and insert what is typed.
152  *	%`command`
153  *		Insert output of command.
154  *	%(test_text=pattern?if_text:else_text)
155  *		Substitute if_text if test_text matches pattern, otherwise
156  *		substitute else_text.  Use != for negated match.
157  *		% substitutions are done on test_text, if_text, and else_text.
158  *	%digit	Substitute the text matched by the nth bracket in the last
159  *		pattern that had brackets.  %0 matches the last bracket
160  *		matched, in case you had alternatives.
161  *	%?	Insert a space unless the entire result is > 79 chars, in
162  *		which case the space becomes a newline.
163  *
164  *	Put ^ in the middle to capitalize the first letter: %^C = Rec.humor
165  *	Put _ in the middle to capitalize last component: %_c = net/Jokes
166  *	Put \ in the middle to quote regexp and % characters in the result
167  *	Put > in the middle to return the address portion of a name.
168  *	Put ) in the middle to return the comment portion of a name.
169  *	Put ' in the middle to protect "'"s in arguments you've put in "'"s.
170  *	Put :FMT in the middle to format the result: %:-30.30t
171  *
172  *	~ interpretation in filename expansion happens after % expansion, so
173  *	you could put ~%{NEWSLOGNAME-news} and it will expand correctly.
174  */
175 
176 /* *** System Dependent Stuff *** */
177 
178 /* NOTE: many of these are defined in the config.h file */
179 
180 /* name of organization */
181 #ifndef ORGNAME
182 #   define ORGNAME "ACME Widget Company, Widget Falls, Southern North Dakota"
183 #endif
184 
185 #ifndef MBOXCHAR
186 #   define MBOXCHAR 'F'	/* how to recognize a mailbox by 1st char */
187 #endif
188 
189 #ifndef ROOTID
190 #   define ROOTID 0        /* uid of superuser */
191 #endif
192 
193 #ifdef NORMSIG
194 #   define sigset signal
195 #   define sigignore(sig) signal(sig,SIG_IGN)
196 #endif
197 
198 #ifndef PASSFILE
199 #   ifdef LIMITED_FILENAMES
200 #	define PASSFILE "%X/passwd"
201 #   else
202 #	define PASSFILE "/etc/passwd"
203 #   endif
204 #endif
205 
206 #ifndef LOGDIRFIELD
207 #   define LOGDIRFIELD 6		/* Which field (origin 1) is the */
208 					/* login directory in /etc/passwd? */
209 					/* (If it is not kept in passwd, */
210 					/* but getpwnam() returns it, */
211 					/* define the symbol HAS_GETPWENT) */
212 #endif
213 #ifndef GCOSFIELD
214 #   define GCOSFIELD 5
215 #endif
216 
217 #ifndef NEGCHAR
218 #   define NEGCHAR '!'
219 #endif
220 
221 /* Space conservation section */
222 
223 /* To save D space, cut down size of MAXNGTODO and VARYSIZE. */
224 #define MAXNGTODO 512	/* number of newsgroups allowed on command line */
225 #define VARYSIZE 256	/* this makes a block 1024 bytes long in DECville */
226 			/* (used by virtual array routines) */
227 
228 /* Undefine any of the following features to save both I and D space */
229 /* In general, earlier ones are easier to get along without */
230 #define USE_FILTER	/* external kill/score filter */
231 #define CUSTOMLINES	/* include code for HIDELINE and PAGESTOP */
232 #define WORDERASE	/* enable ^W to erase a word */
233 #define MAILCALL	/* check periodically for mail */
234 #define NOFIREWORKS	/* keep whole screen from flashing on certain */
235 			/* terminals such as older Televideos */
236 #define VERIFY		/* echo the command they just typed */
237 #define BACKTICK	/* allow %`command` */
238 #define PROMPTTTY	/* allow %"prompt" */
239 #define ULSMARTS	/* catch _^H in text and do underlining */
240 #define TERMMOD		/* allow terminal type modifier on switches */
241 #define BAUDMOD		/* allow baudrate modifier on switches */
242 #define ORGFILE		/* if organization begins with /, look up in file */
243 #define TILDENAME	/* allow ~logname expansion */
244 #define SETENV		/* allow command line environment variable setting */
245 #define MAKEDIR		/* use our makedir() instead of shell script */
246 #define MEMHELP		/* keep help messages in memory */
247 #define VERBOSE		/* compile in more informative messages */
248 #define TERSE		/* compile in shorter messages */
249 			/* (Note: both VERBOSE and TERSE can be defined; -t
250 			 * sets terse mode.  One or the other MUST be defined.
251 			 */
252 #define CHARSUBST	/* enable the _C command */
253 #define DELBOGUS	/* ask if bogus newsgroups should be deleted */
254 #define RELOCATE	/* allow newsgroup rearranging */
255 #define ESCSUBS		/* escape substitutions in multi-character commands */
256 #undef MCHASE		/* unmark xrefed articles on m or M */
257 #define MUNGHEADER	/* allow alternate header formatting via */
258 			/* environment variable ALTHEADER (not impl) */
259 #define ASYNC_PARSE	/* allow parsing headers asyncronously to reading */
260 			/* used by MCHASE and MUNGHEADER */
261 #define FINDNEWNG	/* check for new newsgroups on startup */
262 #define FASTNEW		/* do optimizations on FINDNEWNG for faster startup */
263 #define INNERSEARCH	/* search command 'g' with article */
264 #define CATCHUP		/* catchup command at newsgroup level */
265 #define NGSEARCH	/* newsgroup pattern matching */
266 #define KILLFILES	/* automatic article killer files */
267 #define ARTSEARCH	/* pattern searches among articles */
268 			/* /, ?, ^N, ^P, k, K */
269 #define EDIT_DISTANCE	/* Allow -G to specify a fuzzy 'go' command */
270 #undef	VALIDATE_XREF_SITE /* are xrefs possibly invalid? */
271 
272 /*#define LONG_THREAD_NAMES	*//**/
273 
274 /* USEURL may soon become a Configure script option */
275 /*#define USEURL  *//* allow trn to fetch/use WWW URLs */
276 
277 /* if USEFTP is defined, trn will use the ftpgrab script for ftp: URLs
278  * USEFTP is not very well tested, and the ftpgrab script is not
279  * installed with make install.  May go away later
280  */
281 /*#define USEFTP  *//**/
282 
283 /* The NICEBG functions are probably only useful now for *slow* systems */
284 /*#define NICEBG  *//* use some kind of nice-background call */
285 /* the specific type of NICEBG is used only if NICBG is defined */
286 /* select() call for nice background. */
287 #define NBG_SELECT   /**/
288 /* TERMIO(S) style of nice background available.  Second choice */
289 /*#define NBG_TERMIO *//**/
290 /* SIGIO style of nice background (last resort) */
291 /*#define NBG_SIGIO  *//**/
292 
293 /* SHORTSCORENAMES has not been tested recently */
294 /*#define SHORTSCORENAMES  *//* foo/bar/baz/SCORE instead of foo.bar.baz */
295 
296 /* if SCOREFILE_CACHE is defined, scorefiles will be kept in memory. */
297 #define SCOREFILE_CACHE
298 
299 /* some dependencies among options */
300 
301 #ifdef SCAN
302 # define SCAN_ART
303 #else
304 # ifdef SCAN_ART
305 #  undef SCAN_ART
306 # endif
307 #endif /* SCAN */
308 
309 #ifndef SCORE
310 # ifdef USE_FILTER
311 #  undef USE_FILTER
312 # endif
313 #endif /* SCORE */
314 
315 #ifndef ARTSEARCH
316 #   undef KILLFILES
317 #   undef INNERSEARCH
318 #endif
319 
320 #ifndef SETUIDGID
321 #   define eaccess access
322 #endif
323 
324 #ifdef VERBOSE
325 #   ifdef TERSE
326 #	define IF(c) if (c)
327 #	define ELSE else
328 #   else
329 #	define IF(c)
330 #	define ELSE
331 #   endif
332 #else /* !VERBOSE */
333 #   ifndef TERSE
334 #	define TERSE
335 #   endif
336 #   define IF(c) ..."IF" outside of VERBOSE
337 #   define ELSE ..."ELSE" outside of VERBOSE
338 #endif
339 
340 #ifdef SUPPORT_NNTP
341 #define ElseIf else if
342 #else
343 #define ElseIf if
344 #endif
345 
346 #ifdef DEBUG
347 #   define assert(ex) {if (!(ex)){fprintf(stderr,"Assertion failed: file %s, line %d\n", __FILE__, __LINE__);sig_catcher(0);}}
348 #else
349 #   define assert(ex) ;
350 #endif
351 
352 /* If you're strapped for space use the help messages in shell scripts */
353 /* if {NG,ART,PAGER,SUBS}HELP is undefined, help messages are in memory */
354 #ifdef MEMHELP  /* undef MEMHELP above to get them all as sh scripts */
355 #   undef NGHELP
356 #   undef ARTHELP
357 #   undef PAGERHELP
358 #   undef SUBSHELP
359 #else
360 #   ifndef NGHELP			/* % and ~ */
361 #	define NGHELP "%X/ng.help"
362 #   endif
363 #   ifndef ARTHELP			/* % and ~ */
364 #	define ARTHELP "%X/art.help"
365 #   endif
366 #   ifndef PAGERHELP		/* % and ~ */
367 #	define PAGERHELP "%X/pager.help"
368 #   endif
369 #   ifndef SUBSHELP		/* % and ~ */
370 #	define SUBSHELP "%X/subs.help"
371 #   endif
372 #endif
373 
374 #define TCSIZE 512	/* capacity for termcap strings */
375 
376 #ifdef EDIT_DISTANCE
377 #   define MIN_DIST 7	/* Maximum error count for acceptable match */
378 #endif
379 
380 /* Additional ideas:
381  *	Make the do_newsgroup() routine a separate process.
382  *	Keep .newsrc on disk instead of in memory.
383  *	Overlays, if you have them.
384  *	Get a bigger machine.
385  */
386 
387 /* End of Space Conservation Section */
388 
389 /* More System Dependencies */
390 
391 /* news library */
392 #ifndef NEWSLIB		/* ~ and %l only ("~%l" is permissable) */
393 #   define NEWSLIB "/usr/lib/news"
394 #endif
395 
396 /* path to private executables */
397 #ifndef PRIVLIB		/* ~, %x and %l only */
398 #   define PRIVLIB "%x/trn"
399 #endif
400 
401 /* system-wide RNINIT switches */
402 #ifndef GLOBINIT
403 #   define GLOBINIT "%X/INIT"
404 #endif
405 
406 /* where to find news files */
407 #ifndef NEWSSPOOL		/* % and ~ */
408 #   define NEWSSPOOL "/usr/spool/news"
409 #endif
410 
411 #ifndef THREAD_DIR
412 #   undef LONG_THREAD_NAMES
413 #endif
414 
415 /* default characters to use in the selection menu */
416 #ifndef SELECTCHARS
417 #   define SELECTCHARS "abdefgijlorstuvwxyz1234567890BCFGIKVW"
418 #endif
419 
420 /* file containing list of active newsgroups and max article numbers */
421 #ifndef ACTIVE			/* % and ~ */
422 #   define ACTIVE "%x/active"
423 #endif
424 #ifndef ACTIVE_TIMES
425 #   define ACTIVE_TIMES "none"
426 #endif
427 #ifndef GROUPDESC
428 #   define GROUPDESC "%x/newsgroups"
429 #endif
430 #ifndef DBINIT
431 #   define DBINIT "%W/db.init"
432 #endif
433 
434 /* location of history file */
435 #ifndef ARTFILE			/* % and ~ */
436 #    define ARTFILE "%x/history"
437 #endif
438 
439 /* preferred shell for use in doshell routine */
440 /*  ksh or sh would be okay here */
441 #ifndef PREFSHELL
442 #   define PREFSHELL "/bin/csh"
443 #endif
444 
445 /* path to fastest starting shell */
446 #ifndef SH
447 #   define SH "/bin/sh"
448 #endif
449 
450 /* path to default editor */
451 #ifndef DEFEDITOR
452 #   define DEFEDITOR "/usr/ucb/vi"
453 #endif
454 
455 /* the user's init files */
456 #ifndef TRNDIR
457 # ifdef LIMITED_FILENAMES
458 #   define TRNDIR "%./trn"
459 # else
460 #   define TRNDIR "%./.trn"
461 # endif
462 #endif
463 
464 /* location of macro file for trn and rn modes */
465 #ifndef TRNMACRO
466 #   define TRNMACRO "%+/macros"
467 #endif
468 #ifndef RNMACRO
469 # ifdef LIMITED_FILENAMES
470 #   define RNMACRO "%./rnmac"
471 # else
472 #   define RNMACRO "%./.rnmac"
473 # endif
474 #endif
475 
476 /* location of full name */
477 #ifndef FULLNAMEFILE
478 #   ifndef PASSNAMES
479 #     ifdef LIMITED_FILENAMES
480 #	define FULLNAMEFILE "%./fullname"
481 #     else
482 #	define FULLNAMEFILE "%./.fullname"
483 #     endif
484 #   endif
485 #endif
486 
487 /* The name to append to the directory name to read an overview file. */
488 #ifndef OV_FILE_NAME
489 # ifdef LIMITED_FILENAMES
490 #   define OV_FILE_NAME "/overview"
491 # else
492 #   define OV_FILE_NAME	"/.overview"
493 # endif
494 #endif
495 
496 /* The name to append to the directory name to read a thread file. */
497 #ifndef MT_FILE_NAME
498 # ifdef LIMITED_FILENAMES
499 #   define MT_FILE_NAME "/thread"
500 # else
501 #   define MT_FILE_NAME	"/.thread"
502 # endif
503 #endif
504 
505 /* virtual array file name template */
506 #ifndef VARYNAME		/* % and ~ */
507 #   define VARYNAME "%Y/rnvary.%$"
508 #endif
509 
510 /* file to pass header to followup article poster */
511 #ifndef HEADNAME		/* % and ~ */
512 #   ifdef LIMITED_FILENAMES
513 #	define HEADNAME "%Y/tmpart.%$"
514 #   else
515 #	define HEADNAME "%./.rnhead.%$"
516 #   endif
517 #endif
518 
519 #ifndef MAKEDIR
520 /* shell script to make n-deep subdirectories */
521 #   ifndef DIRMAKER		/* % and ~ */
522 #	define DIRMAKER "%X/makedir"
523 #   endif
524 #endif
525 
526 /* trn's default access list */
527 #ifndef DEFACCESS
528 #   define DEFACCESS "%X/access.def"
529 #endif
530 
531 /* trn's access list */
532 #ifndef TRNACCESS
533 #   define TRNACCESS "%+/access"
534 #endif
535 
536 /* location of newsrc file */
537 #ifndef RCNAME		/* % and ~ */
538 # ifdef LIMITED_FILENAMES
539 #   define RCNAME "%./newsrc"
540 # else
541 #   define RCNAME "%./.newsrc"
542 # endif
543 #endif
544 
545 /* temporary newsrc file in case we crash while writing out */
546 #ifndef RCNAME_NEW
547 #   define RCNAME_NEW "%s.new"
548 #endif
549 
550 /* newsrc file at the beginning of this session */
551 #ifndef RCNAME_OLD
552 #   define RCNAME_OLD "%s.old"
553 #endif
554 
555 /* lockfile for each newsrc that is not ~/.newsrc (which uses .rnlock) */
556 #ifndef RCNAME_LOCK
557 #   define RCNAME_LOCK "%s.LOCK"
558 #endif
559 
560 /* news source info for each newsrc that is not ~/.newsrc (.rnlast) */
561 #ifndef RCNAME_INFO
562 #   define RCNAME_INFO "%s.info"
563 #endif
564 
565 /* if existent, contains process number of current or crashed trn */
566 #ifndef LOCKNAME		/* % and ~ */
567 # ifdef LIMITED_FILENAMES
568 #   define LOCKNAME "%+/lock"
569 # else
570 #   define LOCKNAME "%./.rnlock"
571 # endif
572 #endif
573 
574 /* information from last invocation of trn */
575 #ifndef LASTNAME		/* % and ~ */
576 # ifdef LIMITED_FILENAMES
577 #   define LASTNAME "%+/rnlast"
578 # else
579 #   define LASTNAME "%./.rnlast"
580 # endif
581 #endif
582 
583 #ifndef SIGNATURE_FILE
584 # ifdef LIMITED_FILENAMES
585 #   define SIGNATURE_FILE "%./signatur"
586 # else
587 #   define SIGNATURE_FILE "%./.signature"
588 # endif
589 #endif
590 
591 #ifndef NNTP_AUTH_FILE
592 # define NNTP_AUTH_FILE "%./.nntpauth"
593 #endif
594 
595 /* a motd-like file for trn */
596 #ifndef NEWSNEWSNAME		/* % and ~ */
597 #   define NEWSNEWSNAME "%X/newsnews"
598 #endif
599 
600 /* command to send a reply */
601 #ifndef MAILPOSTER		/* % and ~ */
602 #   define MAILPOSTER "Rnmail -h %h"
603 #endif
604 
605 #ifdef INTERNET
606 #   ifndef MAILHEADER		/* % */
607 #	define MAILHEADER "To: %t\nSubject: %(%i=^$?:Re: %S\nX-Newsgroups: %n\nIn-Reply-To: %i)\n%(%{FROM}=^$?:From: %{FROM}\n)%(%{REPLYTO}=^$?:Reply-To: %{REPLYTO}\n)%(%[references]=^$?:References: %[references]\n)Organization: %o\nCc: \nBcc: \n\n"
608 #   endif
609 #else
610 #   ifndef MAILHEADER		/* % */
611 #	define MAILHEADER "To: %T\nSubject: %(%i=^$?:Re: %S\n%(%{FROM}=^$?:From: %{FROM}\n)%(%{REPLYTO}=^$?:Reply-To: %{REPLYTO}\n)X-Newsgroups: %n\nIn-Reply-To: %i)\n%(%[references]=^$?:References: %[references]\n)Organization: %o\nCc: \nBcc: \n\n"
612 #   endif
613 #endif
614 
615 #ifndef YOUSAID			/* % */
616 #   define YOUSAID "In article %i you write:"
617 #endif
618 
619 /* command to forward an article */
620 #define FORWARDPOSTER MAILPOSTER
621 
622 #ifdef INTERNET
623 #   ifndef FORWARDHEADER	/* % */
624 #	define FORWARDHEADER "To: %\"\n\nTo: \"\nSubject: %(%i=^$?:%[subject] (fwd\\)\n%(%{FROM}=^$?:From: %{FROM}\n)%(%{REPLYTO}=^$?:Reply-To: %{REPLYTO}\n)X-Newsgroups: %n\nIn-Reply-To: %i)\n%(%[references]=^$?:References: %[references]\n)Organization: %o\nMime-Version: 1.0\nContent-Type: multipart/mixed; boundary=\"=%$%^#=--\"\nCc: \nBcc: \n\n"
625 #   endif
626 #else
627 #   ifndef FORWARDHEADER	/* % */
628 #	define FORWARDHEADER "To: %\"\n\nTo: \"\nSubject: %(%i=^$?:%[subject] (fwd\\)\n%(%{FROM}=^$?:From: %{FROM}\n)%(%{REPLYTO}=^$?:Reply-To: %{REPLYTO}\n)X-Newsgroups: %n\nIn-Reply-To: %i)\n%(%[references]=^$?:References: %[references]\n)Organization: %o\nMime-Version: 1.0\nContent-Type: multipart/mixed; boundary=\"=%$%^#=--\"\nCc: \nBcc: \n\n"
629 #   endif
630 #endif
631 
632 #ifndef FORWARDMSG		/* % */
633 #   define FORWARDMSG "------- start of forwarded message -------"
634 #endif
635 
636 #ifndef FORWARDMSGEND		/* % */
637 #   define FORWARDMSGEND "------- end of forwarded message -------"
638 #endif
639 
640 /* command to submit a followup article */
641 #ifndef NEWSPOSTER		/* % and ~ */
642 #   define NEWSPOSTER "Pnews -h %h"
643 #endif
644 
645 #ifndef NEWSHEADER		/* % */
646 #   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%(%{FROM}=^$?:From: %{FROM}\n)%(%{REPLYTO}=^$?:Reply-To: %{REPLYTO}\n)Distribution: %(%i=^$?%\"Distribution: \":%D)\nOrganization: %o\nKeywords: %[keywords]\nCc: %(%F=poster?%t:%(%F!=@?:%F))\n\n"
647 #endif
648 
649 #ifndef ATTRIBUTION		/* % */
650 #   define ATTRIBUTION "In article %i,%?%)f <%>f> wrote:"
651 #endif
652 
653 #ifndef PIPESAVER		/* % */
654 #   define PIPESAVER "%(%B=^0$?<%A:tail +%Bc %A |) %b"
655 #endif
656 
657 #ifndef SHARSAVER
658 #   define SHARSAVER "tail +%Bc %A | /bin/sh"
659 #endif
660 
661 #ifndef CUSTOMSAVER
662 #   define CUSTOMSAVER "tail +%Bc %A | %e"
663 #endif
664 
665 #ifndef VERIFY_RIPEM
666 #   define VERIFY_RIPEM "ripem -d -Y fgs -i %A"
667 #endif
668 
669 #ifndef VERIFY_PGP
670 #   define VERIFY_PGP "pgp +batchmode -m %A"
671 #endif
672 
673 #ifdef MKDIRS
674 
675 #   ifndef SAVEDIR			/* % and ~ */
676 #	define SAVEDIR "%p/%c"
677 #   endif
678 #   ifndef SAVENAME		/* % */
679 #	define SAVENAME "%a"
680 #   endif
681 
682 #else
683 
684 #   ifndef SAVEDIR			/* % and ~ */
685 #	define SAVEDIR "%p"
686 #   endif
687 #   ifndef SAVENAME		/* % */
688 #	define SAVENAME "%^C"
689 #   endif
690 
691 #endif
692 
693 #ifndef KILLGLOBAL		/* % and ~ */
694 #   define KILLGLOBAL "%p/KILL"
695 #endif
696 
697 #ifndef KILLLOCAL		/* % and ~ */
698 #   define KILLLOCAL "%p/%c/KILL"
699 #endif
700 
701 #ifndef KILLTHREADS		/* % and ~ */
702 #   define KILLTHREADS "%+/Kill/Threads"
703 #endif
704 
705 #ifdef USE_FILTER
706 #  ifndef FILTERPROG
707 #    define FILTERPROG "%+/filter"
708 #  endif
709 #endif /* USE_FILTER */
710 
711 /* how to cancel an article */
712 #ifndef CALL_INEWS
713 #   ifdef BNEWS
714 #	define CALL_INEWS "%x/inews -h <%h"
715 #   else
716 #	define CALL_INEWS "inews -h <%h"
717 #   endif
718 #endif
719 
720 /* how to cancel an article, continued */
721 #ifndef CANCELHEADER
722 #   define CANCELHEADER "Newsgroups: %n\nSubject: cancel\n%(%{FROM}=^$?:From: %{FROM}\n)Control: cancel %i\nDistribution: %D\n\n%i was cancelled from within trn.\n"
723 #endif
724 
725 /* how to supersede an article */
726 #ifndef SUPERSEDEHEADER
727 #   define SUPERSEDEHEADER "Newsgroups: %n\nSubject: %[subject]\n%(%{FROM}=^$?:From: %{FROM}\n)Summary: %[summary]\nExpires: %[expires]\nReferences: %[references]\nFrom: %[from]\nReply-To: %[reply-to]\nSupersedes: %i\nSender: %[sender]\nFollowup-To: %[followup-to]\nDistribution: %D\nOrganization: %o\nKeywords: %[keywords]\n\n"
728 #endif
729 
730 #ifndef LOCALTIMEFMT
731 #   define LOCALTIMEFMT "%a %b %d %X %Z %Y"
732 #endif
733 
734 /* where to find the mail file */
735 #ifndef MAILFILE
736 #   define MAILFILE "/usr/spool/mail/%L"
737 #endif
738 
739 /* dependencies of nice background scoring */
740 #ifdef PENDING
741 # ifdef NICEBG
742 #  ifndef I_TERMIO
743 #   ifndef I_TERMIOS
744 #    undef NBG_TERMIO
745 #   endif
746 #  endif
747 /* later insert defines to turn off NBG_SIGIO when needed */
748 # endif
749 #else /* !PENDING */
750 #   undef NICEBG
751 #endif
752 
753 #ifndef HAS_VFORK
754 #   define vfork fork
755 #endif
756 
757 /* Winsock is only initialized if NNTP_SUPPORT is defined */
758 #ifdef WINSOCK
759 # ifndef NNTP_SUPPORT
760 #  ifdef USEURL
761 #   undef USEURL
762 #  endif
763 # endif
764 #endif
765 
766 /* TK requires TCL */
767 #ifdef USE_TK
768 # ifndef USE_TCL
769 #  define USE_TCL
770 # endif
771 #endif
772 
773 /* *** end of the machine dependent stuff *** */
774 
775 /* GLOBAL THINGS */
776 
777 /* file statistics area */
778 
779 EXT struct stat filestat;
780 
781 /* various things of type char */
782 
783 EXT char msg[CBUFLEN];		/* general purpose message buffer */
784 EXT char buf[LBUFLEN+1];	/* general purpose line buffer */
785 EXT char cmd_buf[CBUFLEN];	/* buffer for formatting system commands */
786 EXT char* indstr INIT(">");	/* indent for old article embedded in followup */
787 
788 EXT char* cwd INIT(NULL);	/* current working directory */
789 EXT char* dfltcmd INIT(NULL);	/* 1st char is default command */
790 
791 /* switches */
792 
793 #ifdef DEBUG
794     EXT int debug INIT(0);				/* -D */
795 #   define DEB_COREDUMPSOK 2
796 #   define DEB_HEADER 4
797 #   define DEB_INTRP 8
798 #   define DEB_NNTP 16
799 #   define DEB_INNERSRCH 32
800 #   define DEB_FILEXP 64
801 #   define DEB_HASH 128
802 #   define DEB_XREF_MARKER 256
803 #   define DEB_CTLAREA_BITMAP 512
804 #   define DEB_RCFILES 1024
805 #   define DEB_NEWSRC_LINE 2048
806 #   define DEB_SEARCH_AHEAD 4096
807 #   define DEB_CHECKPOINTING 8192
808 #   define DEB_FEED_XREF 16384
809 #endif
810 
811 #ifdef ARTSEARCH
812 EXT int scanon INIT(0);					/* -S */
813 #endif
814 
815 EXT bool use_threads INIT(THREAD_INIT);			/* -x */
816 EXT int max_tree_lines INIT(6);
817 
818 EXT char UnivSelCmds[3] INIT("Z>");
819 EXT char NewsrcSelCmds[3] INIT("Z>");
820 EXT char AddSelCmds[3] INIT("Z>");
821 EXT char NewsgroupSelCmds[3] INIT("Z>");
822 EXT char NewsSelCmds[3] INIT("Z>");
823 EXT char OptionSelCmds[3] INIT("Z>");
824 
825 EXT int UnivSelBtnCnt;
826 EXT int NewsrcSelBtnCnt;
827 EXT int AddSelBtnCnt;
828 EXT int NewsgroupSelBtnCnt;
829 EXT int NewsSelBtnCnt;
830 EXT int OptionSelBtnCnt;
831 EXT int ArtPagerBtnCnt;
832 
833 EXT char* UnivSelBtns INIT(NULL);
834 EXT char* NewsrcSelBtns INIT(NULL);
835 EXT char* AddSelBtns INIT(NULL);
836 EXT char* NewsgroupSelBtns INIT(NULL);
837 EXT char* NewsSelBtns INIT(NULL);
838 EXT char* OptionSelBtns INIT(NULL);
839 EXT char* ArtPagerBtns INIT(NULL);
840 
841 EXT bool dont_filter_control INIT(FALSE);		/* -j */
842 EXT int  join_subject_len INIT(0);			/* -J */
843 EXT bool kill_thru_kludge INIT(TRUE);			/* -k */
844 EXT bool keep_the_group_static INIT(FALSE);		/* -K */
845 EXT bool mbox_always INIT(FALSE);			/* -M */
846 EXT bool norm_always INIT(FALSE);			/* -N */
847 EXT bool thread_always INIT(FALSE);			/* -a */
848 EXT int auto_arrow_macros INIT(2);			/* -A */
849 EXT bool breadth_first INIT(FALSE);			/* -b */
850 EXT bool bkgnd_spinner INIT(FALSE);			/* -B */
851 EXT bool novice_delays INIT(TRUE);			/* +f */
852 EXT int olden_days INIT(FALSE);				/* -o */
853 EXT char auto_select_postings INIT(0);			/* -p */
854 EXT bool checkflag INIT(FALSE);				/* -c */
855 EXT char* savedir INIT(NULL);				/* -d */
856 EXT bool suppress_cn INIT(FALSE);			/* -s */
857 EXT int countdown INIT(5);	/* how many lines to list before invoking -s */
858 EXT bool muck_up_clear INIT(FALSE);			/* -loco */
859 EXT bool erase_screen INIT(FALSE);			/* -e */
860 EXT bool can_home INIT(FALSE);
861 EXT bool erase_each_line INIT(FALSE);			/* fancy -e */
862 EXT int findlast INIT(0);				/* -r */
863 EXT bool allow_typeahead INIT(FALSE);			/* -T */
864 #ifdef EDIT_DISTANCE
865 EXT bool fuzzyGet INIT(FALSE);				/* -G */
866 #endif
867 #ifdef VERBOSE
868 #   ifdef TERSE
869 EXT bool verbose INIT(TRUE);				/* +t */
870 #   endif
871 #endif
872 EXT bool unbroken_subjects INIT(FALSE);			/* -u */
873 EXT bool unsafe_rc_saves INIT(FALSE);			/* -U */
874 #ifdef VERIFY
875 EXT bool verify INIT(FALSE);				/* -v */
876 #endif
877 EXT bool quickstart INIT(FALSE);			/* -q */
878 
879 #define DEFAULT_REFETCH_SECS  4L*60*60	/* 4 hours */
880 EXT time_t defRefetchSecs INIT(DEFAULT_REFETCH_SECS);	/* -z */
881 
882 EXT int word_wrap_offset INIT(8);  /* right-hand column size (0 is off) */
883 
884 #define NOMARKING 0
885 #define STANDOUT 1
886 #define UNDERLINE 2
887 #define LASTMARKING 3
888 EXT int marking INIT(NOMARKING);			/* -m */
889 #define HALFPAGE_MARKING 1
890 #define BACKPAGE_MARKING 2
891 EXT int marking_areas INIT(HALFPAGE_MARKING);
892 
893 EXT ART_LINE initlines INIT(0);				/* -i */
894 EXT bool append_unsub					/* -I */
895 #ifdef APPEND_UNSUB
896      INIT(1);
897 #else
898      INIT(0);
899 #endif
900 
901 EXT bool UseUnivSelector INIT(FALSE);
902 EXT bool UseNewsrcSelector INIT(FALSE);
903 EXT bool UseAddSelector INIT(TRUE);
904 EXT bool UseNewsgroupSelector INIT(TRUE);
905 EXT int UseNewsSelector INIT(SELECT_INIT-1);
906 EXT bool UseMouse INIT(FALSE);
907 EXT char MouseModes[32] INIT("acjlptwvK");
908 EXT bool use_colors INIT(FALSE);
909 EXT bool UseTk INIT(FALSE);
910 EXT bool UseTcl INIT(FALSE);
911 EXT bool UseSelNum INIT(FALSE);
912 EXT bool SelNumGoto INIT(FALSE);
913 /* miscellania */
914 
915 EXT bool in_ng INIT(FALSE);		/* TRUE if in a newsgroup */
916 EXT char mode INIT('i');		/* current state of trn */
917 EXT char gmode INIT('I');		/* general mode of trn */
918 
919 EXT FILE* tmpfp INIT(NULL);	/* scratch fp used for .rnlock, .rnlast, etc. */
920 
921 #define PLURAL(num) ((num)==1? nullstr : ess)
922 #define ALLBITS(val,bits) (((val) & (bits)) == (bits))
923 
924 /* Factored strings */
925 
926 EXT char nullstr[1] INIT("");
927 EXT char ess[2] INIT("s");
928 EXT char sh[] INIT(SH);
929 EXT char defeditor[] INIT(DEFEDITOR);
930 EXT char hforhelp[] INIT("Type h for help.\n");
931 #ifdef STRICTCR
932 EXT char badcr[] INIT("\nUnnecessary CR ignored.\n");
933 #endif
934 EXT char readerr[] INIT("rn read error");
935 EXT char unsubto[] INIT("Unsubscribed to newsgroup %s\n");
936 EXT char cantopen[] INIT("Can't open %s\n");
937 EXT char cantcreate[] INIT("Can't create %s\n");
938 EXT char cantrecreate[] INIT("Can't recreate %s -- restoring older version.\n\
939 Perhaps you are near or over quota?\n");
940 
941 #ifdef VERBOSE
942     EXT char nocd[] INIT("Can't chdir to directory %s\n");
943 #else
944     EXT char nocd[] INIT("Can't find %s\n");
945 #endif
946 
947 #ifdef NOLINEBUF
948 #define FLUSH ,fflush(stdout)
949 #else
950 #define FLUSH
951 #endif
952 
953 #ifdef lint
954 #undef FLUSH
955 #define FLUSH
956 #undef putchar
957 #define putchar(c)
958 #endif
959 
960 #define nntp_advise(str) fputs(str,stdout)
961 #define nntp_init_error(str) fputs(str,stdout)
962 #define nntp_error(str) fputs(str,stderr)
963 #define NNTP_ERROR_IS_FATAL
964 #define NNTP_HANDLE_TIMEOUT
965 #define NNTP_HANDLE_AUTH_ERR
966