Newsgroups: comp.sources.unix From: davison@borland.com (Wayne Davison) Subject: v29i042: trn-3.6 - threaded newsreader based on RN, V3.6, Part05/14 References: <1.814959141.29825@gw.home.vix.com> Sender: unix-sources-moderator@gw.home.vix.com Approved: vixie@gw.home.vix.com Submitted-By: davison@borland.com (Wayne Davison) Posting-Number: Volume 29, Issue 42 Archive-Name: trn-3.6/part05 #!/bin/sh # This is `part05' (part 5 of a multipart archive). # Do not concatenate these parts, unpack them in order with `/bin/sh'. # File `trn-3.6/intrp.c' is being continued... # touch -am 1231235999 $$.touch >/dev/null 2>&1 if test ! -f 1231235999 && test -f $$.touch; then shar_touch=touch else shar_touch=: echo echo 'WARNING: not restoring timestamps. Consider getting and' echo "installing GNU \`touch', distributed in GNU File Utilities..." echo fi rm -f 1231235999 $$.touch # if test ! -r _sharseq.tmp; then echo 'Please unpack part 1 first!' exit 1 fi shar_sequence=`cat _sharseq.tmp` if test "$shar_sequence" != 5; then echo "Please unpack part $shar_sequence next!" exit 1 fi if test ! -f _sharnew.tmp; then echo 'x - still skipping trn-3.6/intrp.c' else echo 'x - continuing file trn-3.6/intrp.c' sed 's/^X//' << 'SHAR_EOF' >> 'trn-3.6/intrp.c' && X case '`': { X pattern = skipinterp(pattern+1,"`"); X break; X } X#endif X#ifdef PROMPTTTY X case '"': X pattern = skipinterp(pattern+1,"\""); X break; X#endif X default: X break; X } X pattern++; X } X else { X if (*pattern == '^' && pattern[1]) X pattern += 2; X else if (*pattern == '\\' && pattern[1]) X pattern += 2; X else X pattern++; X } X } Xgetout: X return pattern; /* where we left off */ X} X#endif X X/* interpret interpolations */ X Xchar * Xdointerp(dest,destsize,pattern,stoppers) Xregister char *dest; Xregister int destsize; Xregister char *pattern; Xchar *stoppers; X{ X char *subj_buf = Nullch; X char *ngs_buf = Nullch; X char *refs_buf = Nullch; X char *artid_buf = Nullch; X char *reply_buf = Nullch; X char *from_buf = Nullch; X char *path_buf = Nullch; X char *follow_buf = Nullch; X char *dist_buf = Nullch; X char *line_buf = Nullch; X char *line_split = Nullch; X char *orig_dest = dest; X register char *s, *h; X register int i; X char scrbuf[512]; X char spfbuf[512]; X static char *input_str = Nullch; X static int input_siz = 0; X bool upper = FALSE; X bool lastcomp = FALSE; X bool re_quote = FALSE; X int tick_quote = 0; X bool address_parse = FALSE; X bool comment_parse = FALSE; X bool proc_sprintf = FALSE; X int metabit = 0; X X while (*pattern && (!stoppers || !index(stoppers,*pattern))) { X#ifdef DEBUG X if (debug & DEB_INTRP) X printf("dointerp till %s at %s\n",stoppers?stoppers:"",pattern); X#endif X if (*pattern == '%' && pattern[1]) { X upper = FALSE; X lastcomp = FALSE; X re_quote = FALSE; X tick_quote = 0; X address_parse = FALSE; X comment_parse = FALSE; X proc_sprintf = FALSE; X for (s=Nullch; !s; ) { X switch (*++pattern) { X case '^': X upper = TRUE; X break; X case '_': X lastcomp = TRUE; X break; X case '\\': X re_quote = TRUE; X break; X case '\'': X tick_quote++; X break; X case '>': X address_parse = TRUE; X break; X case ')': X comment_parse = TRUE; X break; X case ':': X proc_sprintf = TRUE; X h = spfbuf; X *h++ = '%'; X pattern++; /* Skip over ':' */ X while (*pattern X && (*pattern=='.' || *pattern=='-' || isdigit(*pattern))) { X *h++ = *pattern++; X } X *h++ = 's'; X *h++ = '\0'; X pattern--; X break; X case '/': X#ifdef ARTSEARCH X s = scrbuf; X if (!index("/?g",pattern[-2])) X *s++ = '/'; X strcpy(s,lastpat); X s += strlen(s); X if (pattern[-2] != 'g') { X if (index("/?",pattern[-2])) X *s++ = pattern[-2]; X else X *s++ = '/'; X if (art_doread) X *s++ = 'r'; X if (art_howmuch != ARTSCOPE_SUBJECT) { X *s++ = scopestr[art_howmuch]; X if (art_howmuch == ARTSCOPE_ONEHDR) { X safecpy(s,art_srchhdr, X (sizeof scrbuf) - (s-scrbuf)); X s = index(s,':') + 1; X if (!s) X s = scrbuf+(sizeof scrbuf)-1; X } X } X } X *s = '\0'; X s = scrbuf; X#else X s = nullstr; X#endif X break; X case '{': X pattern = cpytill(scrbuf,pattern+1,'}'); X if (s = index(scrbuf,'-')) X *s++ = '\0'; X else X s = nullstr; X s = getval(scrbuf,s); X break; X case '[': X if (in_ng) { X pattern = cpytill(scrbuf,pattern+1,']'); X i = set_line_type(scrbuf,scrbuf+strlen(scrbuf)); X if (line_buf) X free(line_buf); X s = line_buf = fetchlines(art,i); X } X else X s = nullstr; X break; X#ifdef CONDSUB X case '(': { X COMPEX *oldbra_compex = bra_compex; X char rch; X bool matched; X X pattern = dointerp(dest,destsize,pattern+1,"!="); X rch = *pattern; X if (rch == '!') X pattern++; X if (*pattern != '=') X goto getout; X pattern = cpytill(scrbuf,pattern+1,'?'); X if (!*pattern) X goto getout; X s = scrbuf; X h = spfbuf; X proc_sprintf = FALSE; X do { X switch (*s) { X case '^': X *h++ = '\\'; X break; X case '\\': X *h++ = '\\'; X *h++ = '\\'; X break; X case '%': X proc_sprintf = TRUE; X break; X } X *h++ = *s; X } while (*s++); X if (proc_sprintf) { X dointerp(scrbuf,sizeof scrbuf,spfbuf,Nullch); X proc_sprintf = FALSE; X } X if (s = compile(&cond_compex,scrbuf,TRUE,TRUE)) { X printf("%s: %s\n",scrbuf,s) FLUSH; X pattern += strlen(pattern); X free_compex(&cond_compex); X goto getout; X } X matched = (execute(&cond_compex,dest) != Nullch); X if (getbracket(&cond_compex, 0)) /* were there brackets? */ X bra_compex = &cond_compex; X if (matched==(rch == '=')) { X pattern = dointerp(dest,destsize,pattern+1,":)"); X if (*pattern == ':') X pattern = skipinterp(pattern+1,")"); X } X else { X pattern = skipinterp(pattern+1,":)"); X if (*pattern == ':') X pattern++; X pattern = dointerp(dest,destsize,pattern,")"); X } X s = dest; X bra_compex = oldbra_compex; X free_compex(&cond_compex); X break; X } X#endif X#ifdef BACKTICK X case '`': { X FILE *pipefp, *popen(); X X pattern = dointerp(scrbuf,(sizeof scrbuf),pattern+1,"`"); X pipefp = popen(scrbuf,"r"); X if (pipefp != Nullfp) { X int len; X X len = fread(scrbuf,sizeof(char),(sizeof scrbuf)-1, X pipefp); X scrbuf[len] = '\0'; X pclose(pipefp); X } X else { X printf("\nCan't run %s\n",scrbuf); X *scrbuf = '\0'; X } X for (s=scrbuf; *s; s++) { X if (*s == '\n') { X if (s[1]) X *s = ' '; X else X *s = '\0'; X } X } X s = scrbuf; X break; X } X#endif X#ifdef PROMPTTTY X case '"': X pattern = dointerp(scrbuf,(sizeof scrbuf),pattern+1,"\""); X fputs(scrbuf,stdout) FLUSH; X resetty(); X fgets(scrbuf, sizeof scrbuf, stdin); X noecho(); X crmode(); X i = strlen(scrbuf); X if (scrbuf[i-1] == '\n') { X scrbuf[--i] = '\0'; X } X growstr(&input_str, &input_siz, i+1); X safecpy(input_str, scrbuf, i+1); X s = input_str; X break; X#endif X case '~': X s = homedir; X break; X case '.': X s = dotdir; X break; X case '$': X s = scrbuf; X sprintf(s,"%ld",our_pid); X break; X case '#': X s = scrbuf; X sprintf(s,"%d",perform_cnt); X break; X case '?': X s = " "; X line_split = dest; X break; X case '0': case '1': case '2': case '3': case '4': X case '5': case '6': case '7': case '8': case '9': X#ifdef CONDSUB X s = getbracket(bra_compex,*pattern - '0'); X#else X s = nullstr; X#endif X break; X case 'a': X if (in_ng) { X s = scrbuf; X sprintf(s,"%ld",(long)art); X } X else X s = nullstr; X break; X case 'A': X if (in_ng) { X#ifdef LINKART X s = linkartname; /* so Eunice people get right file */ X#else X s = scrbuf; X#ifdef USE_NNTP X if (artopen(art)) X nntp_finishbody(FB_SILENT); X sprintf(s,"%s/%s",spool,nntp_artname()); X#else X sprintf(s,"%s/%s/%ld",spool,ngdir,(long)art); X#endif X#endif X } X else X s = nullstr; X break; X case 'b': X s = savedest; X break; X case 'B': X s = scrbuf; X sprintf(s,"%ld",(long)savefrom); X break; X case 'c': X s = ngdir; X break; X case 'C': X s = ngname; X break; X case 'd': X s = scrbuf; X sprintf(s,"%s/%s",spool,ngdir); X break; X case 'D': X if (in_ng) X s = dist_buf = fetchlines(art,DIST_LINE); X else X s = nullstr; X break; X case 'e': X s = (extractprog ? extractprog : "-"); X break; X case 'E': X s = extractdest; X break; X case 'f': /* from line */ X if (in_ng) { X parseheader(art); X if (htype[REPLY_LINE].ht_minpos >= 0 && !comment_parse) { X /* was there a reply line? */ X if (!(s=reply_buf)) X s = reply_buf = fetchlines(art,REPLY_LINE); X } X else if (!(s = from_buf)) X s = from_buf = fetchlines(art,FROM_LINE); X } X else X s = nullstr; X break; X case 'F': X if (in_ng) { X parseheader(art); X if (htype[FOLLOW_LINE].ht_minpos >= 0) X /* is there a Followup-To line? */ X s = follow_buf = fetchlines(art,FOLLOW_LINE); X else X s = ngs_buf = fetchlines(art,NGS_LINE); X } X else X s = nullstr; X break; X case 'h': /* header file name */ X s = headname; X break; X case 'H': /* host name in postings */ X s = phostname; X break; X case 'i': X if (in_ng) { X if (!(s=artid_buf)) X s = artid_buf = fetchlines(art,MESSID_LINE); X if (*s && *s != '<') { X sprintf(scrbuf,"<%s>",artid_buf); X s = scrbuf; X } X } X else X s = nullstr; X break; X case 'I': /* ref article indicator */ X s = scrbuf; X sprintf(scrbuf,"'%s'",indstr); X break; X case 'l': /* rn library */ X#ifdef NEWS_ADMIN X s = newsadmin; X#else X s = "???"; X#endif X break; X case 'L': /* login id */ X s = loginName; X break; X case 'm': /* current mode */ X s = scrbuf; X *s = mode; X s[1] = '\0'; X break; X case 'M': X sprintf(scrbuf,"%ld",(long)dmcount); X s = scrbuf; X break; X case 'n': /* newsgroups */ X if (in_ng) X s = ngs_buf = fetchlines(art,NGS_LINE); X else X s = nullstr; X break; X case 'N': /* full name */ X s = getval("NAME",realname); X break; X case 'o': /* organization */ X#ifdef IGNOREORG X s = getval("NEWSORG",orgname); X#else X s = getenv("NEWSORG"); X if (s == Nullch) X s = getval("ORGANIZATION",orgname); X#endif X s = filexp(s); X#ifdef ORGFILE X if (*s == '/') { X FILE *ofp = fopen(s,"r"); X X if (ofp) { X if (fgets(scrbuf,sizeof scrbuf,ofp) == NULL) X *scrbuf = '\0'; X fclose(ofp); X s = scrbuf+strlen(scrbuf)-1; X if (*scrbuf && *s == '\n') X *s = '\0'; X s = scrbuf; X } X else X s = nullstr; X } X#endif X break; X case 'O': X s = origdir; X break; X case 'p': X s = cwd; X break; X case 'P': X s = spool; X break; X case 'q': X s = input_str; X break; X case 'r': X if (in_ng) { X parseheader(art); X if (htype[REFS_LINE].ht_minpos >= 0) { X refs_buf = fetchlines(art,REFS_LINE); X refscpy(scrbuf,(sizeof scrbuf),refs_buf); X } X else X *scrbuf = '\0'; X s = rindex(scrbuf,'<'); X } X else X s = nullstr; X break; X case 'R': X if (!in_ng) { X s = nullstr; X break; X } X parseheader(art); X if (htype[REFS_LINE].ht_minpos >= 0) { X refs_buf = fetchlines(art,REFS_LINE); X refscpy(scrbuf,(sizeof scrbuf),refs_buf); X /* no more than 3 prior references PLUS the X ** root article allowed, including the one X ** concatenated below */ X if ((s = rindex(scrbuf,'<')) > scrbuf) { X *s = '\0'; X h = rindex(scrbuf,'<'); X *s = '<'; X if (h > scrbuf) { X s = index(scrbuf+1,'<'); X if (s < h) X strcpy(s,h); X } X } X } X else X *scrbuf = '\0'; X if (!artid_buf) X artid_buf = fetchlines(art,MESSID_LINE); X if (artid_buf[0] == '<') X safecat(scrbuf,artid_buf,sizeof(scrbuf)); X else if (artid_buf[0]) { X char tmpbuf[64]; X X sprintf(tmpbuf,"<%s>",artid_buf); X safecat(scrbuf,tmpbuf,sizeof(scrbuf)); X } X s = scrbuf; X break; X case 's': X if (!in_ng) { X s = nullstr; X break; X } X if (!(s=subj_buf)) X s = subj_buf = fetchsubj(art,TRUE); X /* get subject handy */ X while ((*s=='R'||*s=='r')&&(s[1]=='E'||s[1]=='e')&&s[2]==':') { X /* skip extra Re: */ X s += 3; X if (*s == ' ') X s++; X } X if (h = instr(s,"- (nf", TRUE)) X *h = '\0'; X break; X case 'S': X if (!in_ng) { X s = nullstr; X break; X } X if (!(s=subj_buf)) X s = subj_buf = fetchsubj(art,TRUE); X /* get subject handy */ X if ((*s=='R'||*s=='r')&&(s[1]=='E'||s[1]=='e')&&s[2]==':') { X /* skip extra Re: */ X s += 3; X if (*s == ' ') X s++; X } X break; X case 't': X case 'T': X if (!in_ng) { X s = nullstr; X break; X } X parseheader(art); X if (htype[REPLY_LINE].ht_minpos >= 0) { X /* was there a reply line? */ X if (!(s=reply_buf)) X s = reply_buf = fetchlines(art,REPLY_LINE); X } X else if (!(s = from_buf)) X s = from_buf = fetchlines(art,FROM_LINE); X else X s = "noname"; X if (*pattern == 'T') { X if (htype[PATH_LINE].ht_minpos >= 0) { X /* should we substitute path? */ X s = path_buf = fetchlines(art,PATH_LINE); X } X i = strlen(phostname); X if (strnEQ(phostname,s,i) && s[i] == '!') X s += i + 1; X } X address_parse = TRUE; /* just the good part */ X break; X case 'u': X sprintf(scrbuf,"%ld",(long)toread[ng]); X s = scrbuf; X break; X case 'U': { X int unseen; X X if (!in_ng) { X s = nullstr; X break; X } X unseen = (art <= lastart) && !was_read(art); X if (selected_only) { X int selected; X X selected = (curr_artp->flags & AF_SEL); X sprintf(scrbuf,"%ld", X (long)selected_count - (selected && unseen)); X } X else X sprintf(scrbuf,"%ld",(long)toread[ng] - unseen); X s = scrbuf; X break; X } X case 'v': { X int selected, unseen; X X if (in_ng) { X selected = (curr_artp->flags & AF_SEL); X unseen = (art <= lastart) && !was_read(art); X sprintf(scrbuf,"%ld",(long)toread[ng] - selected_count X - (!selected && unseen)); X s = scrbuf; X } X else X s = nullstr; X break; X } X case 'W': X s = threaddir; X break; X case 'x': /* news library */ X s = lib; X break; X case 'X': /* rn library */ X s = rnlib; X break; X case 'y': X s = tmpdir; X break; X case 'z': X if (!in_ng) { X s = nullstr; X break; X } X#ifdef LINKART X s = linkartname; /* so Eunice people get right file */ X#else X s = scrbuf; X sprintf(s,"%ld",(long)art); X#endif X if (stat(s,&filestat) < 0) X filestat.st_size = 0L; X sprintf(scrbuf,"%5ld",(long)filestat.st_size); X s = scrbuf; X break; X case 'Z': X sprintf(scrbuf,"%ld",(long)selected_count); X s = scrbuf; X break; X default: X if (--destsize <= 0) X abort_interp(); X *dest++ = *pattern | metabit; X s = nullstr; X break; X } X } X if (!s) X s = nullstr; X if (proc_sprintf) { X sprintf(scrbuf,spfbuf,s); X s = scrbuf; X } X pattern++; X if (upper || lastcomp) { X char *t; X X if (s != scrbuf) { X safecpy(scrbuf,s,(sizeof scrbuf)); X s = scrbuf; X } X if (upper || !(t=rindex(s,'/'))) X t = s; X while (*t && !isalpha(*t)) X t++; X if (islower(*t)) X *t = toupper(*t); X } X /* Do we have room left? */ X i = strlen(s); X if (destsize <= i) X abort_interp(); X destsize -= i; /* adjust the size now. */ X X /* A maze of twisty little conditions, all alike... */ X if (address_parse || comment_parse) { X if (s != scrbuf) { X safecpy(scrbuf,s,(sizeof scrbuf)); X s = scrbuf; X } X if (address_parse) { X if ((h=index(s,'<')) != Nullch) { /* grab the good part */ X s = h+1; X if ((h=index(s,'>')) != Nullch) X *h = '\0'; X } else if ((h=index(s,'(')) != Nullch) { X while (h-- != s && *h == ' ') X ; X h[1] = '\0'; /* or strip the comment */ X } X } else { X if (!(s = extract_name(s))) X s = nullstr; X } X } X if (metabit) { X /* set meta bit while copying. */ X i = metabit; /* maybe get into register */ X if (s == dest) { X while (*dest) X *dest++ |= i; X } else { X while (*s) X *dest++ = *s++ | i; X } X } else if (re_quote || tick_quote) { X /* put a backslash before regexp specials while copying. */ X if (s == dest) { X /* copy out so we can copy in. */ X safecpy(scrbuf, s, sizeof scrbuf); X s = scrbuf; X if (i > sizeof scrbuf) /* we truncated, ack! */ X abort_interp(); X } X while (*s) { X if ((re_quote && index(regexp_specials, *s)) X || (tick_quote == 2 && *s == '"')) { X if (--destsize <= 0) X abort_interp(); X *dest++ = '\\'; X } X else if (re_quote && *s == ' ' && s[1] == ' ') { X *dest++ = ' '; X *dest++ = '*'; X while (*++s == ' ') ; X continue; X } X else if (tick_quote && *s == '\'') { X if ((destsize -= 3) <= 0) X abort_interp(); X *dest++ = '\''; X *dest++ = '\\'; X *dest++ = '\''; X } X *dest++ = *s++; X } X } else { X /* straight copy. */ X if (s == dest) { X dest += i; X } else { X while (*s) X *dest++ = *s++; X } X } X } X else { X if (--destsize <= 0) X abort_interp(); X if (*pattern == '^' && pattern[1]) { X ++pattern; /* skip uparrow */ X i = *pattern; /* get char into a register */ X if (i == '?') X *dest++ = '\177' | metabit; X else if (i == '(') { X metabit = 0200; X destsize++; X } X else if (i == ')') { X metabit = 0; X destsize++; X } X else X *dest++ = (i & 037) | metabit; X pattern++; X } X else if (*pattern == '\\' && pattern[1]) { X ++pattern; /* skip backslash */ X i = *pattern; /* get char into a register */ X X /* this used to be a switch but the if may save space */ X X if (i >= '0' && i <= '7') { X i = 1; X while (i < 01000 && *pattern >= '0' && *pattern <= '7') { X i <<= 3; X i += *pattern++ - '0'; X } X *dest++ = (i & 0377) | metabit; X --pattern; X } X else if (i == 'b') X *dest++ = '\b' | metabit; X else if (i == 'f') X *dest++ = '\f' | metabit; X else if (i == 'n') X *dest++ = '\n' | metabit; X else if (i == 'r') X *dest++ = '\r' | metabit; X else if (i == 't') X *dest++ = '\t' | metabit; X else X *dest++ = i | metabit; X pattern++; X } X else X *dest++ = *pattern++ | metabit; X } X } X *dest = '\0'; X if (line_split != Nullch) X if ((int)strlen(orig_dest) > 79) X *line_split = '\n'; Xgetout: X if (subj_buf != Nullch) /* return any checked out storage */ X free(subj_buf); X if (ngs_buf != Nullch) X free(ngs_buf); X if (refs_buf != Nullch) X free(refs_buf); X if (artid_buf != Nullch) X free(artid_buf); X if (reply_buf != Nullch) X free(reply_buf); X if (from_buf != Nullch) X free(from_buf); X if (path_buf != Nullch) X free(path_buf); X if (follow_buf != Nullch) X free(follow_buf); X if (dist_buf != Nullch) X free(dist_buf); X if (line_buf != Nullch) X free(line_buf); X return pattern; /* where we left off */ X} X Xvoid Xinterp(dest,destsize,pattern) Xchar *dest; Xint destsize; Xchar *pattern; X{ X dointerp(dest,destsize,pattern,Nullch); X#ifdef DEBUG X if (debug & DEB_FILEXP) X fputs(dest,stdout); X#endif X} X X/* copy a references line, normalizing as we go */ X Xvoid Xrefscpy(dest,destsize,src) Xregister char *dest, *src; Xregister int destsize; X{ X register char *dot, *at, *beg; X char tmpbuf[64]; X X while (*src) { X if (*src != '<') { X if (--destsize <= 0) X break; X *dest++ = '<'; X at = dot = Nullch; X beg = src; X while (*src && *src != ' ' && *src != ',') { X if (*src == '.') X dot = src; X else if (*src == '@') X at = src; X if (--destsize <= 0) X break; X *dest++ = *src++; X } X if (destsize <= 0) X break; X if (dot && !at) { X int len; X X *dest = *dot++ = '\0'; X sprintf(tmpbuf,"%s@%s.UUCP",dot,beg); X len = strlen(tmpbuf); X if (destsize > len) { X strcpy(dest,tmpbuf); X dest = dest + len; X destsize -= len; X } X } X if (--destsize <= 0) X break; X *dest++ = '>'; X } X else { X while (*src && --destsize > 0 && (*dest++ = *src++) != '>') ; X if (destsize <= 0) X break; X } X while (*src == ' ' || *src == '\t' || *src == '\n' || *src == ',') X src++; X if (*src && --destsize > 0) X *dest++ = ' '; X } X *dest = '\0'; X} X X/* get the person's real name from /etc/passwd */ X/* (string is overwritten, so it must be copied) */ X Xchar * Xgetrealname(uid) Xlong uid; X{ X char *s, *c; X X#ifdef PASSNAMES X#ifdef HAS_GETPWENT X#ifdef notdef X struct passwd *getpwuid _((uid_t)); X#endif X struct passwd *pwd = getpwuid(uid); X X if (!pwd) X return nullstr; X X s = pwd->pw_gecos; X#else X char tmpbuf[512]; X int i; X X getpw(uid, tmpbuf); X for (s=tmpbuf, i=GCOSFIELD-1; i; i--) { X if (s) X s = index(s,':')+1; X } X if (!s) X return nullstr; X cpytill(tmpbuf,s,':'); X s = tmpbuf; X#endif X#ifdef BERKNAMES X#ifdef BERKJUNK X while (*s && !isalnum(*s) && *s != '&') s++; X#endif X if ((c = index(s, ',')) != Nullch) X *c = '\0'; X if ((c = index(s, ';')) != Nullch) X *c = '\0'; X s = cpytill(buf,s,'&'); X if (*s == '&') { /* whoever thought this one up was */ X c = buf + strlen(buf); /* in the middle of the night */ X strcat(c,loginName); /* before the morning after */ X strcat(c,s+1); X if (islower(*c)) X *c = toupper(*c); /* gack and double gack */ X } X#else X if ((c = index(s, '(')) != Nullch) X *c = '\0'; X if ((c = index(s, '-')) != Nullch) X s = c; X strcpy(buf,s); X#endif X#ifdef HAS_GETPWENT X endpwent(); X#endif X return buf; /* return something static */ X#else X if ((tmpfp=fopen(filexp(FULLNAMEFILE),"r")) != Nullfp) { X fgets(buf,sizeof buf,tmpfp); X fclose(tmpfp); X buf[strlen(buf)-1] = '\0'; X return buf; X } X return "PUT YOUR NAME HERE"; X#endif X} X Xstatic void Xabort_interp() X{ X fputs("\n% interp buffer overflow!\n",stdout) FLUSH; X sig_catcher(0); X} X X SHAR_EOF echo 'File trn-3.6/intrp.c is complete' && $shar_touch -am 1110023094 'trn-3.6/intrp.c' && chmod 0644 'trn-3.6/intrp.c' || echo 'restore of trn-3.6/intrp.c failed' shar_count="`wc -c < 'trn-3.6/intrp.c'`" test 30284 -eq "$shar_count" || echo "trn-3.6/intrp.c: original size 30284, current size $shar_count" rm -f _sharnew.tmp fi # ============= trn-3.6/intrp.h ============== if test -f 'trn-3.6/intrp.h' && test X"$1" != X"-c"; then echo 'x - skipping trn-3.6/intrp.h (file already exists)' rm -f _sharnew.tmp else > _sharnew.tmp echo 'x - extracting trn-3.6/intrp.h (text)' sed 's/^X//' << 'SHAR_EOF' > 'trn-3.6/intrp.h' && X/* $Id: intrp.h,v 3.0 1992/02/01 03:09:32 davison Trn $ X */ X/* This software is Copyright 1991 by Stan Barber. X * X * Permission is hereby granted to copy, reproduce, redistribute or otherwise X * use this software as long as: there is no monetary profit gained X * specifically from the use or reproduction of this software, it is not X * sold, rented, traded or otherwise marketed, and this copyright notice is X * included prominently in any copy made. X * X * The authors make no claims as to the fitness or correctness of this software X * for any use whatsoever, and it is provided as is. Any use of this software X * is at the user's own risk. X */ X XEXT char *lib INIT(Nullch); /* news library */ XEXT char *rnlib INIT(Nullch); /* private news program library */ XEXT char *origdir INIT(Nullch); /* cwd when rn invoked */ XEXT char *homedir INIT(Nullch); /* login directory */ XEXT char *dotdir INIT(Nullch); /* where . files go */ XEXT char *tmpdir INIT(Nullch); /* where tmp files go */ XEXT char *loginName INIT(Nullch); /* login id of user */ XEXT char *realname INIT(Nullch); /* real name of user */ XEXT char *phostname INIT(Nullch); /* host name in a posting */ XEXT int perform_cnt; X X#ifdef NEWS_ADMIN X EXT char newsadmin[] INIT(NEWS_ADMIN);/* news administrator */ X EXT int newsuid INIT(0); X#endif X Xvoid intrp_init _((char*)); Xchar *filexp _((char*)); Xchar *dointerp _((char*,int,char*,char*)); Xvoid interp _((char*,int,char*)); Xvoid refscpy _((char*,int,char*)); Xchar *getrealname _((long)); SHAR_EOF $shar_touch -am 1017161694 'trn-3.6/intrp.h' && chmod 0644 'trn-3.6/intrp.h' || echo 'restore of trn-3.6/intrp.h failed' shar_count="`wc -c < 'trn-3.6/intrp.h'`" test 1508 -eq "$shar_count" || echo "trn-3.6/intrp.h: original size 1508, current size $shar_count" rm -f _sharnew.tmp fi # ============= trn-3.6/kfile.c ============== if test -f 'trn-3.6/kfile.c' && test X"$1" != X"-c"; then echo 'x - skipping trn-3.6/kfile.c (file already exists)' rm -f _sharnew.tmp else > _sharnew.tmp echo 'x - extracting trn-3.6/kfile.c (text)' sed 's/^X//' << 'SHAR_EOF' > 'trn-3.6/kfile.c' && X/* $Id: kfile.c,v 3.0 1991/09/09 20:18:23 davison Trn $ X */ X/* This software is Copyright 1991 by Stan Barber. X * X * Permission is hereby granted to copy, reproduce, redistribute or otherwise X * use this software as long as: there is no monetary profit gained X * specifically from the use or reproduction of this software, it is not X * sold, rented, traded or otherwise marketed, and this copyright notice is X * included prominently in any copy made. X * X * The authors make no claims as to the fitness or correctness of this software X * for any use whatsoever, and it is provided as is. Any use of this software X * is at the user's own risk. X */ X X#include "EXTERN.h" X#include "common.h" X#include "term.h" X#include "util.h" X#include "cache.h" X#include "artsrch.h" X#include "ng.h" X#include "ngdata.h" X#include "intrp.h" X#include "ngstuff.h" X#include "rcstuff.h" X#include "trn.h" X#include "bits.h" X#include "hash.h" X#include "rthread.h" X#include "rt-process.h" X#include "rt-select.h" X#include "INTERN.h" X#include "kfile.h" X Xextern HASHTABLE *msgid_hash; X Xstatic bool exitcmds = FALSE; X Xvoid Xkfile_init() X{ X ; X} X X#ifndef KILLFILES Xint Xedit_kfile() X{ X notincl("^K"); X return -1; X} X X#else /* KILLFILES */ X Xchar killglobal[] = KILLGLOBAL; Xchar killlocal[] = KILLLOCAL; X Xvoid Xmention(str) Xchar *str; X{ X#ifdef VERBOSE X IF(verbose) { X#ifdef NOFIREWORKS X no_sofire(); X#endif X standout(); X fputs(str,stdout); X un_standout(); X putchar('\n'); X } X ELSE X#endif X#ifdef TERSE X putchar('.'); X#endif X fflush(stdout); X} X Xstatic bool kill_mentioned; X Xint Xdo_kfile(kfp,entering) XFILE *kfp; Xint entering; X{ X bool first_time = (entering && !killfirst); X ART_UNREAD selections = selected_count; X ART_UNREAD unread = toread[ng]; X int thread_kill_cnt = 0; X int thread_select_cnt = 0; X char *cp; X X art = lastart+1; X killfirst = firstart; X fseek(kfp,0L,0); /* rewind file */ X while (fgets(buf,LBUFLEN,kfp) != Nullch) { X if (*(cp = buf + strlen(buf) - 1) == '\n') X *cp = '\0'; X if (strnEQ(buf,"THRU",4)) { X killfirst = atol(buf+4)+1; X if (killfirst < absfirst) X killfirst = absfirst; X if (killfirst > lastart) X killfirst = lastart+1; X continue; X } X if (*buf == 'X') { /* exit command? */ X if (entering) { X exitcmds = TRUE; X continue; X } X strcpy(buf,buf+1); X } X else if (!entering) X continue; X X if (*buf == '&') { X mention(buf); X switcheroo(); X } X else if (*buf == '/') { X has_normal_kills = TRUE; X if (firstart > lastart) X continue; X mention(buf); X kill_mentioned = TRUE; X switch (art_search(buf, (sizeof buf), FALSE)) { X case SRCH_ABORT: X continue; X case SRCH_INTR: X#ifdef VERBOSE X IF(verbose) X printf("\n(Interrupted at article %ld)\n",(long)art) X FLUSH; X ELSE X#endif X#ifdef TERSE X printf("\n(Intr at %ld)\n",(long)art) FLUSH; X#endif X return -1; X case SRCH_DONE: X break; X case SRCH_SUBJDONE: X fputs("\tsubject not found (?)\n",stdout) FLUSH; X break; X case SRCH_NOTFOUND: X fputs("\tnot found\n",stdout) FLUSH; X break; X case SRCH_FOUND: X fputs("\tfound\n",stdout) FLUSH; X } X } X else if (first_time && *buf == '<') { X register ARTICLE *ap; X cp = index(buf,' '); X if (!cp) X cp = "T,"; X else X *cp++ = '\0'; X if ((ap = get_article(buf)) != Nullart) { X if ((ap->flags & AF_FAKE) == AF_FAKE) { X if (*cp == 'T') X cp++; X switch (*cp) { X case '+': X ap->autofl |= AUTO_SELECTALL; X thread_select_cnt++; X break; X case '.': X ap->autofl |= AUTO_SELECT; X thread_select_cnt++; X break; X case 'J': X case 'j': X ap->autofl |= AUTO_KILLALL; X thread_kill_cnt++; X break; X case ',': X ap->autofl |= AUTO_KILL; X thread_kill_cnt++; X break; X } X } else { X art = article_num(ap); X artp = ap; X perform(cp,FALSE); X if (ap->autofl & (AUTO_SELECT|AUTO_SELECTALL)) X thread_select_cnt++; X else if (ap->autofl & (AUTO_KILL|AUTO_KILLALL)) X thread_kill_cnt++; X } X } X art = lastart+1; X } else if (*buf == '*') { X register ARTICLE *ap; X register int killmask = AF_READ; X switch (buf[1]) { X case 'X': X killmask |= sel_mask; /* don't kill selected articles */ X /* FALL THROUGH */ X case 'j': X for (art = killfirst, ap = article_ptr(killfirst); X art <= lastart; X art++, ap++ X ) { X if (!(ap->flags & killmask)) X set_read(ap); X else if (ap->flags & sel_mask) { X ap->flags &= ~sel_mask; X if (!selected_count--) X selected_count = 0; X } X } X break; X } X has_normal_kills = TRUE; X } X } X if (thread_kill_cnt) { X sprintf(buf,"%ld auto-kill command%s.", (long)thread_kill_cnt, X thread_kill_cnt == 1? "" : "s"); X mention(buf); X kill_mentioned = TRUE; X } X if (thread_select_cnt) { X sprintf(buf,"%ld auto-select command%s.", (long)thread_select_cnt, X thread_select_cnt == 1? "" : "s"); X mention(buf); X kill_mentioned = TRUE; X } X unread -= toread[ng]; X selections -= selected_count; X#ifdef VERBOSE X IF(verbose && (unread > 0 || selections < 0)) { X putchar('\n'); X if (unread > 0) { X printf("Killed %ld article%s", (long)unread, X unread == 1? nullstr : "s"); X if (selections < 0) X fputs("; ",stdout); X } X if (selections < 0) X printf("Selected %ld article%s", (long)-selections, X selections == -1? nullstr : "s"); X fputs(".\n",stdout) FLUSH; X kill_mentioned = TRUE; X } X#endif X return 0; X} X Xvoid Xkill_unwanted(starting,message,entering) XART_NUM starting; Xchar *message; Xint entering; X{ X bool intr = FALSE; /* did we get an interrupt? */ X ART_NUM oldfirst; X char oldmode = mode; X bool anytokill = (toread[ng] > 0); X X mode = 'k'; X if ((entering || exitcmds) && (localkfp || globkfp)) { X exitcmds = FALSE; X oldfirst = firstart; X firstart = starting; X clear(); X#ifdef VERBOSE X# ifdef TERSE X if (message && (verbose || entering)) X# else X if (message) X# endif X#else X if (message && entering) X#endif X fputs(message,stdout) FLUSH; X X kill_mentioned = FALSE; X if (localkfp) { X if (entering) X localkf_changes |= 1; X intr = do_kfile(localkfp,entering); X } X if (globkfp && !intr) X intr = do_kfile(globkfp,entering); X putchar('\n') FLUSH; X if (entering && kill_mentioned && novice_delays) X#ifdef VERBOSE X IF(verbose) X get_anything(); X ELSE X#endif X#ifdef TERSE X pad(just_a_sec); X#endif X if (anytokill) /* if there was anything to kill */ X forcelast = FALSE; /* allow for having killed it all */ X firstart = oldfirst; X } X if (!entering && localkf_changes && !intr) X rewrite_kfile(lastart); X mode = oldmode; X} X Xstatic FILE *newkfp; X Xstatic void write_thread_commands(data, extra) XHASHDATUM *data; Xint extra; X{ X register ARTICLE *ap = (data->dat_ptr? (ARTICLE*)data->dat_ptr X : article_ptr(data->dat_len)); X register int autofl; X char ch; X X if ((autofl = ap->autofl) != 0) { X if (!(ap->flags & AF_MISSING) || ap->child1) { X if (autofl & AUTO_KILLALL) X ch = 'J'; X else if (autofl & AUTO_KILL) X ch = ','; X else if (autofl & AUTO_SELECTALL) X ch = '+'; X else if (autofl & AUTO_SELECT) X ch = '.'; X else X ch = '?'; X fprintf(newkfp,"%s T%c\n", ap->msgid, ch); X } X } X} X Xvoid Xrewrite_kfile(thru) XART_NUM thru; X{ X bool no_kills = 0, has_star_commands = FALSE; X X if (localkfp) { X fseek(localkfp,0L,0); /* rewind current file */ X /* If we're writing ids, we know the file is not null */ X if (localkf_changes > 1) X ; X else if (fgets(buf,LBUFLEN,localkfp) != Nullch X && (strnNE(buf,"THRU",4) || fgets(buf,LBUFLEN,localkfp) != Nullch)) X fseek(localkfp,0L,0); X else X no_kills = 1; X } X strcpy(buf,filexp(getval("KILLLOCAL",killlocal))); X if (!localkfp) X makedir(buf,MD_FILE); X UNLINK(buf); /* to prevent file reuse */ X if (no_kills) X open_kfile(KF_LOCAL); /* close file and reset open flag */ X else if (newkfp = fopen(buf,"w")) { X fprintf(newkfp,"THRU %ld\n",(long)thru); X while (localkfp && fgets(buf,LBUFLEN,localkfp) != Nullch) { X if (strnEQ(buf,"THRU",4)) X continue; X /* Write star commands after other kill commands */ X if (*buf == '*') { X has_star_commands = TRUE; X continue; X } X /* Leave out any outdated thread commands */ X if (*buf != 'T' && *buf != '<') X fputs(buf,newkfp); X } X if (has_star_commands) { X fseek(localkfp,0L,0); /* rewind file */ X while (fgets(buf,LBUFLEN,localkfp) != Nullch) { X if (*buf == '*') X fputs(buf,newkfp); X } X } X /* Append all the still-valid thread commands */ X hashwalk(msgid_hash, write_thread_commands, 0); X fclose(newkfp); X open_kfile(KF_LOCAL); /* and reopen local file */ X } X else X printf(cantcreate,buf) FLUSH; X localkf_changes = 0; X has_normal_kills = FALSE; X} X X/* edit KILL file for newsgroup */ X Xint Xedit_kfile() X{ X int r = -1; X X if (in_ng) { X register SUBJECT *sp; X X if (localkf_changes) X rewrite_kfile(lastart); X for (sp = first_subject; sp; sp = sp->next) X clear_subject(sp); X localkf_changes = 0; X strcpy(buf,filexp(getval("KILLLOCAL",killlocal))); X } else X strcpy(buf,filexp(getval("KILLGLOBAL",killglobal))); X if ((r = makedir(buf,MD_FILE)) >= 0) { X sprintf(cmd_buf,"%s %s", X filexp(getval("VISUAL",getval("EDITOR",defeditor))),buf); X printf("\nEditing %s KILL file:\n%s\n", X (in_ng?"local":"global"),cmd_buf) FLUSH; X resetty(); /* make sure tty is friendly */ X r = doshell(sh,cmd_buf);/* invoke the shell */ X noecho(); /* and make terminal */ X crmode(); /* unfriendly again */ X open_kfile(in_ng); X if (localkfp) { X fseek(localkfp,0L,0); /* rewind file */ X has_normal_kills = FALSE; X while (fgets(buf,LBUFLEN,localkfp) != Nullch) { X if (*buf == '/' || *buf == '*') X has_normal_kills = TRUE; X else if (*buf == '<') { X register ARTICLE *ap; X char *cp = index(buf,' '); X if (!cp) X cp = ","; X else X *cp++ = '\0'; X if ((ap = get_article(buf)) != Nullart) { X if (*cp == 'T') X cp++; X switch (*cp) { X case '+': X ap->autofl |= AUTO_SELECTALL; X break; X case '.': X ap->autofl |= AUTO_SELECT; X break; X case 'J': X case 'j': X ap->autofl |= AUTO_KILLALL; X break; X case ',': X ap->autofl |= AUTO_KILL; X break; X } X } X } X } X } X } X else X printf("Can't make %s\n",buf) FLUSH; X return r; X} X Xvoid Xopen_kfile(local) Xint local; X{ X char *kname = filexp(local ? X getval("KILLLOCAL",killlocal) : X getval("KILLGLOBAL",killglobal) X ); X X /* delete the file if it is empty */ X if (stat(kname,&filestat) >= 0 && !filestat.st_size) X UNLINK(kname); X if (local) { X if (localkfp) X fclose(localkfp); X localkfp = fopen(kname,"r"); X } X else { X if (globkfp) X fclose(globkfp); X globkfp = fopen(kname,"r"); X } X} X Xvoid Xkf_append(cmd) Xchar *cmd; X{ X strcpy(cmd_buf,filexp(getval("KILLLOCAL",killlocal))); X if (makedir(cmd_buf,MD_FILE) >= 0) { X#ifdef VERBOSE X IF(verbose) X printf("\nDepositing command in %s...",cmd_buf); X ELSE X#endif X#ifdef TERSE X printf("\n--> %s...",cmd_buf); X#endif X fflush(stdout); X if (novice_delays) X sleep(2); X if ((tmpfp = fopen(cmd_buf,"a+")) != Nullfp) { X char ch; X if (fseek(tmpfp,-1L,2) < 0) X ch = '\n'; X else X ch = getc(tmpfp); X fseek(tmpfp,0L,2); X if (ch != '\n') X putc('\n', tmpfp); X fprintf(tmpfp,"%s\n",cmd); X fclose(tmpfp); X if (!localkfp) X open_kfile(KF_LOCAL); X fputs("done\n",stdout) FLUSH; X } X else X printf(cantopen,cmd_buf) FLUSH; X } X has_normal_kills = TRUE; X} X#endif /* KILLFILES */ SHAR_EOF $shar_touch -am 1118220194 'trn-3.6/kfile.c' && chmod 0644 'trn-3.6/kfile.c' || echo 'restore of trn-3.6/kfile.c failed' shar_count="`wc -c < 'trn-3.6/kfile.c'`" test 11520 -eq "$shar_count" || echo "trn-3.6/kfile.c: original size 11520, current size $shar_count" rm -f _sharnew.tmp fi # ============= trn-3.6/kfile.h ============== if test -f 'trn-3.6/kfile.h' && test X"$1" != X"-c"; then echo 'x - skipping trn-3.6/kfile.h (file already exists)' rm -f _sharnew.tmp else > _sharnew.tmp echo 'x - extracting trn-3.6/kfile.h (text)' sed 's/^X//' << 'SHAR_EOF' > 'trn-3.6/kfile.h' && X/* $Id: kfile.h,v 3.0 1991/09/09 20:18:23 davison Trn $ X */ X/* This software is Copyright 1991 by Stan Barber. X * X * Permission is hereby granted to copy, reproduce, redistribute or otherwise X * use this software as long as: there is no monetary profit gained X * specifically from the use or reproduction of this software, it is not X * sold, rented, traded or otherwise marketed, and this copyright notice is X * included prominently in any copy made. X * X * The authors make no claims as to the fitness or correctness of this software X * for any use whatsoever, and it is provided as is. Any use of this software X * is at the user's own risk. X */ X X#define KF_GLOBAL 0 X#define KF_LOCAL 1 X X#ifdef KILLFILES XEXT FILE *globkfp INIT(Nullfp); /* global article killer file */ XEXT FILE *localkfp INIT(Nullfp); /* local (for this newsgroup) file */ XEXT int localkf_changes; /* do we need to write changes? */ XEXT bool has_normal_kills; /* flag when KILLs needs rereading */ XEXT ART_NUM killfirst; /* used as firstart when killing */ X#endif X Xvoid kfile_init _((void)); Xint do_kfile _((FILE*,int)); Xvoid kill_unwanted _((ART_NUM,char*,int)); Xint edit_kfile _((void)); Xvoid open_kfile _((int)); Xvoid kf_append _((char*)); Xvoid rewrite_kfile _((ART_NUM)); SHAR_EOF $shar_touch -am 0711223593 'trn-3.6/kfile.h' && chmod 0644 'trn-3.6/kfile.h' || echo 'restore of trn-3.6/kfile.h failed' shar_count="`wc -c < 'trn-3.6/kfile.h'`" test 1254 -eq "$shar_count" || echo "trn-3.6/kfile.h: original size 1254, current size $shar_count" rm -f _sharnew.tmp fi # ============= trn-3.6/last.c ============== if test -f 'trn-3.6/last.c' && test X"$1" != X"-c"; then echo 'x - skipping trn-3.6/last.c (file already exists)' rm -f _sharnew.tmp else > _sharnew.tmp echo 'x - extracting trn-3.6/last.c (text)' sed 's/^X//' << 'SHAR_EOF' > 'trn-3.6/last.c' && X/* $Id: last.c,v 3.0 1992/02/01 03:09:32 davison Trn $ X */ X/* This software is Copyright 1991 by Stan Barber. X * X * Permission is hereby granted to copy, reproduce, redistribute or otherwise X * use this software as long as: there is no monetary profit gained X * specifically from the use or reproduction of this software, it is not X * sold, rented, traded or otherwise marketed, and this copyright notice is X * included prominently in any copy made. X * X * The authors make no claims as to the fitness or correctness of this software X * for any use whatsoever, and it is provided as is. Any use of this software X * is at the user's own risk. X */ X X#include "EXTERN.h" X#include "common.h" X#include "trn.h" X#include "util.h" X#include "intrp.h" X#include "INTERN.h" X#include "last.h" X Xchar *lastname = Nullch; /* path name of .rnlast file */ X Xvoid Xlast_init(tcbuf) Xchar *tcbuf; X{ X lastname = savestr(filexp(LASTNAME)); X if ((tmpfp = fopen(lastname,"r")) != Nullfp && X fgets(tcbuf,1024,tmpfp) != Nullch) { X tcbuf[strlen(tcbuf)-1] = '\0'; X lastngname = savestr(tcbuf); X fgets(tcbuf,1024,tmpfp); X lasttime = atol(tcbuf); X fgets(tcbuf,1024,tmpfp); X lastactsiz = atol(tcbuf); X if (fgets(tcbuf,1024,tmpfp) != Nullch) X lastnewtime = atol(tcbuf); X else X lastnewtime = lasttime; X#if 1 X /* If the time is in the future, rewind by thirty days */ X if (lastnewtime > time(Null(time_t*))) X lastnewtime = time(Null(time_t*)) - 30L*24*60*60; X#endif X /* If the time wasn't set, just give them 2 days worth of groups */ X if (!lastnewtime) X lastnewtime = time(Null(time_t*)) - 2L*24*60*60; X X if (fgets(tcbuf,1024,tmpfp) != Nullch) X lastnewsize = atol(tcbuf); X else X lastnewsize = 0; X fclose(tmpfp); X } X else { X lastngname = nullstr; X lasttime = 0; X lastactsiz = 0; X lastnewsize = 0; X /* Use two days ago as an initial value for finding new groups. */ X lastnewtime = time(Null(time_t*)) - 2L*24*60*60; X } X} X X/* put out certain values for next run of rn */ X Xvoid Xwritelast() X{ X if ((tmpfp = fopen(lastname,"w")) != Nullfp) { X fprintf(tmpfp,"%s\n%ld\n%ld\n%ld\n%ld\n", X (ngname==Nullch?nullstr:ngname),(long)lasttime,(long)lastactsiz, X (long)lastnewtime,(long)lastnewsize); X fclose(tmpfp); X } X else X printf(cantcreate,lastname) FLUSH; X} SHAR_EOF $shar_touch -am 1130170793 'trn-3.6/last.c' && chmod 0644 'trn-3.6/last.c' || echo 'restore of trn-3.6/last.c failed' shar_count="`wc -c < 'trn-3.6/last.c'`" test 2268 -eq "$shar_count" || echo "trn-3.6/last.c: original size 2268, current size $shar_count" rm -f _sharnew.tmp fi # ============= trn-3.6/last.h ============== if test -f 'trn-3.6/last.h' && test X"$1" != X"-c"; then echo 'x - skipping trn-3.6/last.h (file already exists)' rm -f _sharnew.tmp else > _sharnew.tmp echo 'x - extracting trn-3.6/last.h (text)' sed 's/^X//' << 'SHAR_EOF' > 'trn-3.6/last.h' && X/* $Id: last.h,v 3.0 1992/02/01 03:09:32 davison Trn $ X */ X/* This software is Copyright 1991 by Stan Barber. X * X * Permission is hereby granted to copy, reproduce, redistribute or otherwise X * use this software as long as: there is no monetary profit gained X * specifically from the use or reproduction of this software, it is not X * sold, rented, traded or otherwise marketed, and this copyright notice is X * included prominently in any copy made. X * X * The authors make no claims as to the fitness or correctness of this software X * for any use whatsoever, and it is provided as is. Any use of this software X * is at the user's own risk. X */ X XEXT char *lastngname INIT(Nullch); /* last newsgroup read, from .rnlast file */ XEXT time_t lasttime INIT(0); /* time last rn was started up */ XEXT long lastactsiz INIT(0); /* size of active file when rn last started up */ XEXT time_t lastnewtime INIT(0); /* time last new group was found */ XEXT long lastnewsize INIT(0); /* size of active.times file when rn last started up */ X Xvoid last_init _((char*)); Xvoid writelast _((void)); SHAR_EOF $shar_touch -am 0711223593 'trn-3.6/last.h' && chmod 0644 'trn-3.6/last.h' || echo 'restore of trn-3.6/last.h failed' shar_count="`wc -c < 'trn-3.6/last.h'`" test 1082 -eq "$shar_count" || echo "trn-3.6/last.h: original size 1082, current size $shar_count" rm -f _sharnew.tmp fi # ============= trn-3.6/ndir.c ============== if test -f 'trn-3.6/ndir.c' && test X"$1" != X"-c"; then echo 'x - skipping trn-3.6/ndir.c (file already exists)' rm -f _sharnew.tmp else > _sharnew.tmp echo 'x - extracting trn-3.6/ndir.c (text)' sed 's/^X//' << 'SHAR_EOF' > 'trn-3.6/ndir.c' && X/* $Id: ndir.c,v 3.0 1991/09/09 20:23:31 davison Trn $ X */ X/* This software is Copyright 1991 by Stan Barber. X * X * Permission is hereby granted to copy, reproduce, redistribute or otherwise X * use this software as long as: there is no monetary profit gained X * specifically from the use or reproduction of this software, it is not X * sold, rented, traded or otherwise marketed, and this copyright notice is X * included prominently in any copy made. X * X * The authors make no claims as to the fitness or correctness of this software X * for any use whatsoever, and it is provided as is. Any use of this software X * is at the user's own risk. X */ X X#include "EXTERN.h" X#include "common.h" X#include "INTERN.h" X#include "ndir.h" X X#ifdef EMULATE_NDIR X/* X * support for Berkeley directory reading routine on a V7 file system X */ X X/* X * open a directory. X */ XDIR * Xopendir(name) Xchar *name; X{ X register DIR *dirp; X register int fd; X char *malloc(); X X if ((fd = open(name, 0)) == -1) X return NULL; X if ((dirp = (DIR *)malloc(sizeof(DIR))) == NULL) { X close (fd); X return NULL; X } X dirp->dd_fd = fd; X dirp->dd_loc = 0; X return dirp; X} X X/* X * read an old style directory entry and present it as a new one X */ X#ifndef pyr X#define ODIRSIZ 14 X Xstruct olddirect { X ino_t od_ino; X char od_name[ODIRSIZ]; X}; X#else /* an Pyramid in the ATT universe */ X#define ODIRSIZ 248 X Xstruct olddirect { X long od_ino; X short od_fill1, od_fill2; X char od_name[ODIRSIZ]; X}; X#endif X X/* X * get next entry in a directory. X */ XDirentry_t * Xreaddir(dirp) Xregister DIR *dirp; X{ X register struct olddirect *dp; X static Direntry_t dir; X X for (;;) { X if (dirp->dd_loc == 0) { X dirp->dd_size = read(dirp->dd_fd, dirp->dd_buf, X DIRBLKSIZ); X if (dirp->dd_size <= 0) X return NULL; X } X if (dirp->dd_loc >= dirp->dd_size) { X dirp->dd_loc = 0; X continue; X } X dp = (struct olddirect *)(dirp->dd_buf + dirp->dd_loc); X dirp->dd_loc += sizeof(struct olddirect); X if (dp->od_ino == 0) X continue; X dir.d_ino = dp->od_ino; X strncpy(dir.d_name, dp->od_name, ODIRSIZ); X dir.d_name[ODIRSIZ] = '\0'; /* insure null termination */ X dir.d_namlen = strlen(dir.d_name); X dir.d_reclen = DIRSIZ(&dir); X return (&dir); X } X} X X/* X * close a directory. X */ Xvoid Xclosedir(dirp) Xregister DIR *dirp; X{ X close(dirp->dd_fd); X dirp->dd_fd = -1; X dirp->dd_loc = 0; X free(dirp); X} X X#endif /* EMULATE_NDIR */ SHAR_EOF $shar_touch -am 0327202494 'trn-3.6/ndir.c' && chmod 0644 'trn-3.6/ndir.c' || echo 'restore of trn-3.6/ndir.c failed' shar_count="`wc -c < 'trn-3.6/ndir.c'`" test 2369 -eq "$shar_count" || echo "trn-3.6/ndir.c: original size 2369, current size $shar_count" rm -f _sharnew.tmp fi # ============= trn-3.6/ndir.h ============== if test -f 'trn-3.6/ndir.h' && test X"$1" != X"-c"; then echo 'x - skipping trn-3.6/ndir.h (file already exists)' rm -f _sharnew.tmp else > _sharnew.tmp echo 'x - extracting trn-3.6/ndir.h (text)' sed 's/^X//' << 'SHAR_EOF' > 'trn-3.6/ndir.h' && X/* $Id: ndir.h,v 3.0 1991/09/09 20:23:31 davison Trn $ X */ X/* This software is Copyright 1991 by Stan Barber. X * X * Permission is hereby granted to copy, reproduce, redistribute or otherwise X * use this software as long as: there is no monetary profit gained X * specifically from the use or reproduction of this software, it is not X * sold, rented, traded or otherwise marketed, and this copyright notice is X * included prominently in any copy made. X * X * The authors make no claims as to the fitness or correctness of this software X * for any use whatsoever, and it is provided as is. Any use of this software X * is at the user's own risk. X */ X X#ifdef I_NDIR X#include X#else X#ifdef I_DIRENT X#include X#else X#ifdef I_SYS_NDIR X#include X#else X#ifdef I_SYS_DIR X#include X#else X X#ifndef DEV_BSIZE X#define DEV_BSIZE 512 X#endif X#define DIRBLKSIZ DEV_BSIZE X#define MAXNAMLEN 255 X XDirentry_t { X long d_ino; /* inode number of entry */ X short d_reclen; /* length of this record */ X short d_namlen; /* length of string in d_name */ X char d_name[MAXNAMLEN + 1]; /* name must be no longer than this */ X}; X X/* X * The DIRSIZ macro gives the minimum record length which will hold X * the directory entry. This requires the amount of space in Direntry_t X * without the d_name field, plus enough space for the name with a terminating X * null byte (dp->d_namlen+1), rounded up to a 4 byte boundary. X */ X#undef DIRSIZ X#define DIRSIZ(dp) ((sizeof(Direntry_t)-(MAXNAMLEN+1))+(((dp)->d_namlen+1+3)&~3)) X X/* X * Definitions for library routines operating on directories. X */ Xtypedef struct _dirdesc { X int dd_fd; X long dd_loc; X long dd_size; X char dd_buf[DIRBLKSIZ]; X} DIR; X#ifndef NULL X#define NULL 0 X#endif Xextern DIR *opendir _((char*)); Xextern Direntry_t *readdir _((DIR*)); Xextern long telldir _((DIR*)); Xextern void seekdir _((DIR*)); X#define rewinddir(dirp) seekdir((dirp), (long)0) Xextern void closedir _((DIR*)); X X#endif X#endif X#endif X#endif SHAR_EOF $shar_touch -am 0327202494 'trn-3.6/ndir.h' && chmod 0644 'trn-3.6/ndir.h' || echo 'restore of trn-3.6/ndir.h failed' shar_count="`wc -c < 'trn-3.6/ndir.h'`" test 1976 -eq "$shar_count" || echo "trn-3.6/ndir.h: original size 1976, current size $shar_count" rm -f _sharnew.tmp fi # ============= trn-3.6/ng.c ============== if test -f 'trn-3.6/ng.c' && test X"$1" != X"-c"; then echo 'x - skipping trn-3.6/ng.c (file already exists)' rm -f _sharnew.tmp else > _sharnew.tmp echo 'x - extracting trn-3.6/ng.c (text)' sed 's/^X//' << 'SHAR_EOF' > 'trn-3.6/ng.c' && X/* $Id: ng.c,v 3.0 1992/02/01 03:09:32 davison Trn $ X */ X/* This software is Copyright 1991 by Stan Barber. X * X * Permission is hereby granted to copy, reproduce, redistribute or otherwise X * use this software as long as: there is no monetary profit gained X * specifically from the use or reproduction of this software, it is not X * sold, rented, traded or otherwise marketed, and this copyright notice is X * included prominently in any copy made. X * X * The authors make no claims as to the fitness or correctness of this software X * for any use whatsoever, and it is provided as is. Any use of this software X * is at the user's own risk. X */ X X#include "EXTERN.h" X#include "common.h" X#include "trn.h" X#include "term.h" X#include "final.h" X#include "util.h" X#include "cache.h" X#include "bits.h" X#include "artsrch.h" X#include "help.h" X#include "kfile.h" X#include "rcstuff.h" X#include "head.h" X#include "art.h" X#include "artio.h" X#include "ngstuff.h" X#include "intrp.h" X#include "respond.h" X#include "ngdata.h" X#include "backpage.h" X#include "rcln.h" X#include "sw.h" X#include "last.h" X#include "search.h" X#include "nntp.h" X#include "rthread.h" X#include "rt-select.h" X#include "rt-wumpus.h" X#include "decode.h" X#include "charsubst.h" X#include "INTERN.h" X#include "ng.h" X#include "artstate.h" /* somebody has to do it */ X X/* art_switch() return values */ X X#define AS_NORM 0 X#define AS_INP 1 X#define AS_ASK 2 X#define AS_CLEAN 3 X Xint exit_code = NG_NORM; X Xvoid Xng_init() X{ X X#ifdef KILLFILES X open_kfile(KF_GLOBAL); X#endif X#ifdef CUSTOMLINES X init_compex(&hide_compex); X init_compex(&page_compex); X#endif X} X X/* do newsgroup on line ng with name ngname */ X X/* assumes that we are chdir'ed to NEWSSPOOL, and assures that that is X * still true upon return, but chdirs to NEWSSPOOL/ngname in between X * X * If you can understand this routine, you understand most of the program. X * The basic structure is: X * for each desired article X * for each desired page X * for each line on page X * if we need another line from file X * get it X * if it's a header line X * do special things X * for each column on page X * put out a character X * end loop X * end loop X * end loop X * end loop X * X * (Actually, the pager is in another routine.) X * X * The chief problem is deciding what is meant by "desired". Most of X * the messiness of this routine is due to the fact that people want X * to do unstructured things all the time. I have used a few judicious X * goto's where I thought it improved readability. The rest of the messiness X * arises from trying to be both space and time efficient. Have fun. X */ X Xint Xdo_newsgroup(start_command) Xchar *start_command; /* command to fake up first */ X{ X char oldmode = mode; X#ifdef CHARSUBST X char *whatnext = "%s%sWhat next? [%s]"; X charsubst = charsets; X#else X char *whatnext = "%sWhat next? [%s]"; X#endif X X exit_code = NG_NORM; X localkf_changes = 0; X killfirst = 0; X X if (extractdest) { X free(extractdest); X extractdest = Nullch; X } X if (extractprog) { X free(extractprog); X extractprog = Nullch; X } X X /* initialize the newsgroup data structures */ X X if (!access_ng()) X return -1; X X#ifdef ARTSEARCH X srchahead = (scanon && !ThreadedGroup /* did they say -S? */ X && ((ART_NUM)toread[ng]) >= scanon ? -1 : 0); X#endif X X /* FROM HERE ON, RETURN THRU CLEANUP OR WE ARE SCREWED */ X X forcelast = TRUE; /* if 0 unread, do not bomb out */ X recent_artp = curr_artp = Nullart; X recent_art = curr_art = lastart+1; X prompt = whatnext; X X /* remember what newsgroup we were in for sake of posterity */ X X writelast(); X X /* see if there are any special searches to do */ X X has_normal_kills = FALSE; X#ifdef KILLFILES X open_kfile(KF_LOCAL); X# ifdef VERBOSE X IF(verbose) X kill_unwanted(firstart,"Processing memorized commands...\n\n",TRUE); X ELSE X# endif X# ifdef TERSE X kill_unwanted(firstart,"Auto-processing...\n\n",TRUE); X# endif X#endif X if (!selected_count) X selected_only = FALSE; X top_article(); X X /* do they want a special top line? */ X X firstline = getval("FIRSTLINE",Nullch); X X /* custom line suppression, custom page ending */ X X#ifdef CUSTOMLINES X if (hideline = getval("HIDELINE",Nullch)) X compile(&hide_compex,hideline,TRUE,TRUE); X if (pagestop = getval("PAGESTOP",Nullch)) X compile(&page_compex,pagestop,TRUE,TRUE); X#endif X X /* now read each unread article */ X X rc_changed = doing_ng = TRUE; /* enter the twilight zone */ X if (!unsafe_rc_saves) X checkcount = 0; /* do not checkpoint for a while */ X do_fseek = FALSE; /* start 1st article at top */ X for (; art<=lastart+1; ) { /* for each article */ X mode = 'a'; X X /* do we need to "grow" the newsgroup? */ X X if ((art > lastart || forcegrow) && !keep_the_group_static) { X ART_NUM oldlast = lastart; X#ifdef USE_NNTP X if ((actfp || getngsize(ng) > lastart) X && !nntp_group(ngname,ng)) { X fprintf(stderr,"Your server went south for the winter:\n%s\n", X ser_line); X finalize(1); X } X if (ngmax[ng] > lastart) { X grow_ng(ngmax[ng]); X } X#else X grow_ng(getngsize(ng)); X#endif X if (forcelast && art > oldlast) X art = lastart+1; X } X if (!artp || (artp->flags & AF_TMPMEM) != AF_TMPMEM || art != 0) X artp = find_article(art); X if (start_command) { /* do we have an initial command? */ X hide_pending(); X pushstring(start_command, 0); X free(start_command); X start_command = Nullch; X art = curr_art = lastart+1; X artp = curr_artp = Nullart; X if (input_pending()) X goto reinp_article; X } X if (art>lastart) { /* are we off the end still? */ X ARTICLE *ap; X ART_NUM i; X art = lastart + 1; /* keep pointer references sane */ X if (!forcelast && toread[ng] && selected_only && !selected_count) { X art = curr_art; X artp = curr_artp; X strcpy(buf, "+"); X goto article_level; X } X count_subjects(CS_RETAIN); X for (i = absfirst, ap = article_ptr(i); i <= lastart; i++, ap++) X if (!(ap->flags & (AF_READ|AF_CACHED))) X article_count++; X toread[ng] = (ART_UNREAD)article_count; X if (artp != curr_artp) { X recent_art = curr_art; /* remember last article # (for '-') */ X curr_art = art; /* set current article # */ X recent_artp = curr_artp; X curr_artp = artp; X } X if (erase_screen) X clear(); /* clear the screen */ X else X fputs("\n\n",stdout) FLUSH; X#ifdef VERBOSE X IF(verbose) X printf("End of newsgroup %s.",ngname); X /* print pseudo-article */ X ELSE X#endif X#ifdef TERSE X printf("End of %s",ngname); X#endif X if (article_count) { X if (selected_only) X printf(" (%ld + %ld articles still unread)", X (long)selected_count, X (long)article_count-selected_count); X else X printf(" (%ld article%s still unread)", X (long)article_count,article_count==1?nullstr:"s"); X } X if (redirected) { X if (redirected == nullstr) X printf("\n\n** This group has been disabled by your news admin **"); X else X printf("\n\n** Please start using %s **", redirected); X } else if (!article_count && !forcelast) X goto cleanup; /* actually exit newsgroup */ X mode = 'e'; X prompt = whatnext; X#ifdef ARTSEARCH X srchahead = 0; /* no more subject search mode */ X#endif X fputs("\n\n",stdout) FLUSH; X } X else if (!reread && (was_read(art) || (artp->flags & AF_MISSING) X || (selected_only && !(artp->flags & AF_SEL)))) { X /* has this article been read? */ X inc_art(selected_only,FALSE);/* then skip it */ X continue; X } X else if (!reread && !parseheader(art)) { X oneless(artp); /* mark deleted as read */ X ng_skip(); X } X else { /* we have a real live article */ X if (artp != curr_artp) { X recent_art = curr_art; /* remember last article # (for '-') */ X curr_art = art; /* set current article # */ X recent_artp = curr_artp; X curr_artp = artp; X } X if (!do_fseek) { /* starting at top of article? */ X artline = 0; /* start at the beginning */ X topline = -1; /* and remember top line of screen */ X /* (line # within article file) */ X } X clear(); /* clear screen */ X#ifdef USE_NNTP X if (art == 0 && artp && artp->msgid X && !(artp->flags & AF_CACHED)) { X art = nntp_stat_id(artp->msgid); X if (art) X artp = find_article(art); X } X#endif X if (!artopen(art)) { /* make sure article is found & open */ X char tmpbuf[256]; X ART_LINE linenum; X /* see if we have tree data for this article anyway */ X init_tree(); X sprintf(tmpbuf,"%s: article is not available.",ngname); X if (artp && !(artp->flags & AF_CACHED)) { X if (absfirst < first_cached || last_cached < lastart X || !cached_all_in_range) X sprintf(tmpbuf,"%s: article may show up in a moment.", X ngname); X } X linenum = tree_puts(tmpbuf,0,0); X vwtary(artline,(ART_POS)0); X finish_tree(linenum); X prompt = whatnext; X#ifdef ARTSEARCH X srchahead = 0; X#endif X } X else { /* found it, so print it */ X switch (do_article()) { X case DA_CLEAN: /* quit newsgroup */ X goto cleanup; X case DA_TOEND: /* do not mark as read */ X goto reask_article; X case DA_RAISE: /* reparse command at end of art */ X goto article_level; X case DA_NORM: /* normal end of article */ X break; X } X } X if (art >= absfirst) /* don't mark non-existant articles */ X mark_as_read(); /* mark current article as read */ X do_hiding = TRUE; X#ifdef ROTATION X rotate = FALSE; X#endif X } X X/* if these gotos bother you, think of this as a little state machine */ X Xreask_article: X#ifdef MAILCALL X setmail(FALSE); X#endif X setdfltcmd(); X#ifdef CLEAREOL X if (erase_screen && can_home_clear) X clear_rest(); X#endif /* CLEAREOL */ X unflush_output(); /* disable any ^O in effect */ X standout(); /* enter standout mode */ X /* print prompt, whatever it is */ X interp(cmd_buf, sizeof cmd_buf, mailcall); X#ifdef CHARSUBST X printf(prompt,cmd_buf,current_charsubst(),dfltcmd); X#else X printf(prompt,cmd_buf,dfltcmd); X#endif X un_standout(); /* leave standout mode */ X putchar(' '); X fflush(stdout); Xreinp_article: X reread = FALSE; X forcelast = FALSE; X eat_typeahead(); X#ifdef PENDING X look_ahead(); /* see what we can do in advance */ X cache_until_key(); X#endif X art = curr_art; X artp = curr_artp; X getcmd(buf); X if (errno || *buf == '\f') { X if (LINES < 100 && !int_count) X *buf = '\f'; /* on CONT fake up refresh */ X else { X putchar('\n') FLUSH; /* but only on a crt */ X goto reask_article; X } X } Xarticle_level: X output_chase_phrase = TRUE; X X /* parse and process article level command */ X X switch (art_switch()) { X case AS_INP: /* multichar command rubbed out */ X goto reinp_article; X case AS_ASK: /* reprompt "End of article..." */ X goto reask_article; X case AS_CLEAN: /* exit newsgroup */ X goto cleanup; X case AS_NORM: /* display article art */ X break; X } X } /* end of article selection loop */ X X/* shut down newsgroup */ X Xcleanup: X decode_end(); X#ifdef KILLFILES X kill_unwanted(firstart,"\nCleaning up...\n\n",FALSE); X /* do cleanup from KILL file, if any */ X#endif X chase_xrefs(FALSE); X in_ng = FALSE; /* leave newsgroup state */ X if (artfp != Nullfp) { /* article still open? */ X fclose(artfp); /* close it */ X artfp = Nullfp; /* and tell the world */ X openart = 0; X } X putchar('\n') FLUSH; X deselect_all(); X yankback(); /* do a Y command */ X bits_to_rc(); /* reconstitute .newsrc line */ X doing_ng = FALSE; /* tell sig_catcher to cool it */ X if (!unsafe_rc_saves) X write_rc(); /* and update .newsrc */ X rc_changed = FALSE; /* tell sig_catcher it is ok */ X if (chdir(spool)) { X printf(nocd,spool) FLUSH; X sig_catcher(0); X } X#ifdef KILLFILES X if (localkfp) { X fclose(localkfp); X localkfp = Nullfp; X } X#endif X mode = oldmode; X return exit_code; X} /* Whew! */ X X/* decide what to do at the end of an article */ X Xint Xart_switch() X{ X register ART_NUM i; X X setdef(buf,dfltcmd); X#ifdef VERIFY X printcmd(); X#endif X X switch (*buf) { X case '<': /* goto previous subject/thread */ X visit_prev_thread(); X return AS_NORM; X case '>': /* goto next subject/thread */ X visit_next_thread(); X return AS_NORM; X case 'U': { /* unread some articles */ X char *u_prompt, *u_help_thread; X X if (!artp) { X u_help_thread = nullstr; X#ifdef VERBOSE X IF(verbose) X u_prompt = "\nSet unread: +select or all?"; X ELSE X#endif X#ifdef TERSE X u_prompt = "\nSet unread?"; X#endif X dfltcmd = "+an"; X } X else { X#ifdef VERBOSE X IF(verbose) { X u_prompt = "\n\ XSet unread: +select, thread, subthread, or all?"; X u_help_thread = "\ XType t or SP to mark this thread's articles as unread.\n\ XType s to mark the current article and its descendants as unread.\n"; X } X ELSE X#endif X#ifdef TERSE X { X u_prompt = "\nSet unread?"; X u_help_thread = "\ Xt or SP to mark thread unread.\n\ Xs to mark subthread unread.\n"; X } X#endif X dfltcmd = "+tsan"; X } X reask_unread: X in_char(u_prompt,'u',dfltcmd); X#ifdef VERIFY X printcmd(); X#endif X putchar('\n') FLUSH; X if (*buf == 'h') { X#ifdef VERBOSE X IF(verbose) X { X fputs("\ XType + to enter select thread mode using all the already-read articles.\n\ X(The selected threads will be marked as unread and displayed as usual.)\n\ X",stdout) FLUSH; X fputs(u_help_thread,stdout); X fputs("\ XType a to mark all articles in this group as unread.\n\ XType n to change nothing.\n\ X",stdout) FLUSH; X } X ELSE X#endif X#ifdef TERSE X { X fputs("\ X+ to select threads from the unread.\n\ X",stdout) FLUSH; X fputs(u_help_thread,stdout); X fputs("\ Xa to mark all articles unread.\n\ Xn to change nothing.\n\ X",stdout) FLUSH; X } X#endif X goto reask_unread; X } X else if (*buf == 'n' || *buf == 'q') X return AS_ASK; X else if (*buf == 't' && u_help_thread != nullstr) { X unkill_thread(artp->subj->thread); X if ((artp = first_art(artp->subj)) != Nullart) X art = article_num(artp); X } else if (*buf == 's' && u_help_thread != nullstr) X unkill_subthread(artp); X else if (*buf == 'a') { X register ARTICLE *ap; X check_first(absfirst); X ap = article_ptr(absfirst); X for (i = absfirst; i <= lastart; i++, ap++) X if ((ap->flags & (AF_READ|AF_MISSING)) == AF_READ) { X ap->flags &= ~AF_READ; /* mark as unread */ X toread[ng]++; X } X count_subjects(CS_NORM); X } X else if (*buf == '+') { X *buf = 'U'; X goto run_the_selector; X } X else { X fputs(hforhelp,stdout) FLUSH; X settle_down(); X goto reask_unread; X } X return AS_NORM; X } X case '[': /* goto parent article */ X case '{': /* goto thread's root article */ X if (artp && ThreadedGroup) { X if (!find_parent(*buf == '{')) { X register char *cp = (*buf=='['?"parent":"root"); X#ifdef VERBOSE X IF(verbose) X printf("\nThere is no %s article prior to this one.\n", X cp) FLUSH; X ELSE X#endif X#ifdef TERSE X printf("\nNo prior %s.\n",cp) FLUSH; X#endif X return AS_ASK; X } X reread = TRUE; X return AS_NORM; X } Xnot_threaded: X if (!artp) { X#ifdef VERBOSE X IF(verbose) X fputs("\nYou're at the end of the group.\n",stdout) FLUSH; X ELSE X#endif X#ifdef TERSE X fputs("\nEnd of group.\n",stdout) FLUSH; X#endif X return AS_ASK; X } X#ifdef VERBOSE X IF(verbose) X fputs("\nThis group is not threaded.\n",stdout) FLUSH; X ELSE X#endif X#ifdef TERSE X fputs("\nUnthreaded group.\n",stdout) FLUSH; X#endif X return AS_ASK; X case ']': /* goto child article */ X case '}': /* goto thread's leaf article */ X if (artp && ThreadedGroup) { X if (!find_leaf(*buf == '}')) { X#ifdef VERBOSE X IF(verbose) X fputs("\n\ XThis is the last leaf in this tree.\n",stdout) FLUSH; X ELSE X#endif X#ifdef TERSE X fputs("\nLast leaf.\n",stdout) FLUSH; X#endif X return AS_ASK; X } X reread = TRUE; X return AS_NORM; X } X goto not_threaded; X case '(': /* goto previous sibling */ X case ')': /* goto next sibling */ X if (artp && ThreadedGroup) { X if (!(*buf == '(' ? find_prev_sib() : find_next_sib())) { X register char *cp = (*buf == '(' ? "previous" : "next"); X#ifdef VERBOSE X IF(verbose) X printf("\nThis article has no %s sibling.\n",cp) FLUSH; X ELSE X#endif X#ifdef TERSE X printf("\nNo %s sibling.\n",cp) FLUSH; X#endif X return AS_ASK; X } X reread = TRUE; X return AS_NORM; X } X goto not_threaded; X case 'T': X if (!ThreadedGroup) X goto not_threaded; X /* FALL THROUGH */ X case 'A': X if (!artp) X goto not_threaded; X switch (ask_memorize(*buf)) { X case ',': case 'j': X return AS_NORM; X } X return AS_ASK; X case 'K': X if (!artp) X goto not_threaded; X /* first, write kill-subject command */ X (void)art_search(buf, (sizeof buf), TRUE); X art = curr_art; X artp = curr_artp; X kill_subject(artp->subj,KF_ALL);/* take care of any prior subjects */ X return AS_NORM; X case ',': /* kill this node and all descendants */ X if (!artp) X goto not_threaded; X if (ThreadedGroup) X kill_subthread(artp,KF_ALL); X else if (art >= absfirst && art <= lastart) X mark_as_read(); X return AS_NORM; X case 'J': /* Junk all nodes in this thread */ X if (!artp) X goto not_threaded; X if (ThreadedGroup) { X kill_thread(artp->subj->thread,KF_ALL); X return AS_NORM; X } X /* FALL THROUGH */ X case 'k': /* kill current subject */ X if (!artp) X goto not_threaded; X kill_subject(artp->subj,KF_ALL); X if (!ThreadedGroup || last_cached < lastart) { X *buf = 'k'; X goto normal_search; X } X return AS_NORM; X case 't': X carriage_return(); X#ifndef CLEAREOL X erase_eol(); /* erase the prompt */ X#else X if (erase_screen && can_home_clear) X clear_rest(); X else X erase_eol(); /* erase the prompt */ X#endif /* CLEAREOL */ X fflush(stdout); X page_line = 1; X entire_tree(curr_artp); X return AS_ASK; X case ':': /* execute command on selected articles */ X page_line = 1; X if (!thread_perform()) X return AS_INP; X putchar('\n'); X art = curr_art; X artp = curr_artp; X return AS_ASK; X case 'p': /* find previous unread article */ X do { X dec_art(selected_only,FALSE); X } while (art >= firstart && (was_read(art) || !parseheader(art))); X#ifdef ARTSEARCH X srchahead = 0; X#endif X if (art >= firstart) X return AS_NORM; X art = absfirst; X /* FALL THROUGH */ X case 'P': /* goto previous article */ X dec_art(FALSE,TRUE); X check_dec_art: X if (art < absfirst) { X#ifdef VERBOSE X IF(verbose) X printf("\nThere are no%s%s articles prior to this one.\n", X *buf=='P'?nullstr:" unread", X selected_only?" selected":nullstr) FLUSH; X ELSE X#endif X#ifdef TERSE X printf("\nNo previous%s%s articles\n", X *buf=='P'?nullstr:" unread", X selected_only?" selected":nullstr) FLUSH; X#endif X art = curr_art; X artp = curr_artp; X return AS_ASK; X } X reread = TRUE; X#ifdef ARTSEARCH X srchahead = 0; X#endif X return AS_NORM; X case '-': X if (recent_art >= 0) { X art = recent_art; X artp = recent_artp; X reread = TRUE; X forcelast = TRUE; X#ifdef ARTSEARCH X srchahead = -(srchahead != 0); X#endif X return AS_NORM; X } X else { X exit_code = NG_MINUS; X return AS_CLEAN; X } X case 'n': /* find next unread article? */ X if (art > lastart) { X if (!toread[ng]) X return AS_CLEAN; X top_article(); X } X#ifdef ARTSEARCH X else if (scanon && !ThreadedGroup && srchahead) { X *buf = Ctl('n'); X if (!next_art_with_subj()) X goto normal_search; X return AS_NORM; X } X#endif X else { X inc_art(selected_only,FALSE); X if (art > lastart) X top_article(); X } X#ifdef ARTSEARCH X srchahead = 0; X#endif X return AS_NORM; X case 'N': /* goto next article */ X if (art > lastart) X if (!first_subject) { X art = absfirst; X artp = article_ptr(art); X } else { X artp = first_subject->articles; X if (artp->flags & AF_MISSING) X inc_art(FALSE,TRUE); X else X art = article_num(artp); X } X else X inc_art(FALSE,TRUE); X if (art <= lastart) X reread = TRUE; X else X forcelast = TRUE; X#ifdef ARTSEARCH X srchahead = 0; X#endif X return AS_NORM; X case '$': X art = lastart+1; X artp = Nullart; X forcelast = TRUE; X#ifdef ARTSEARCH X srchahead = 0; X#endif X return AS_NORM; X case '1': case '2': case '3': /* goto specified article */ X case '4': case '5': case '6': /* or do something with a range */ X case '7': case '8': case '9': case '.': X forcelast = TRUE; X switch (numnum()) { X case NN_INP: X return AS_INP; X case NN_ASK: X return AS_ASK; X case NN_REREAD: X reread = TRUE; X#ifdef ARTSEARCH X if (srchahead) X srchahead = -1; X#endif X break; X case NN_NORM: X if (was_read(art)) { X top_article(); X pad(just_a_sec/3); X } X else { X putchar('\n'); X return AS_ASK; X } X break; X } X return AS_NORM; X case Ctl('k'): X edit_kfile(); X return AS_ASK; X case Ctl('n'): /* search for next article with same subject */ X case Ctl('p'): /* search for previous article with same subject */ X if (*buf == Ctl('n')? next_art_with_subj() : prev_art_with_subj()) X return AS_NORM; X case '/': case '?': Xnormal_search: X#ifdef ARTSEARCH X { /* search for article by pattern */ X char cmd = *buf; X X reread = TRUE; /* assume this */ X page_line = 1; X switch (art_search(buf, (sizeof buf), TRUE)) { X case SRCH_ERROR: X art = curr_art; X return AS_ASK; X case SRCH_ABORT: X art = curr_art; X return AS_INP; X case SRCH_INTR: X#ifdef VERBOSE X IF(verbose) X printf("\n(Interrupted at article %ld)\n",(long)art) FLUSH; X ELSE X#endif X#ifdef TERSE X printf("\n(Intr at %ld)\n",(long)art) FLUSH; X#endif X art = curr_art; /* restore to current article */ X return AS_ASK; X case SRCH_DONE: X fputs("done\n",stdout) FLUSH; X pad(just_a_sec/3); /* 1/3 second */ X if (!srchahead) { X art = curr_art; X return AS_ASK; X } X top_article(); X reread = FALSE; X return AS_NORM; X case SRCH_SUBJDONE: X#ifdef UNDEF X fputs("\n\n\n\nSubject not found.\n",stdout) FLUSH; X pad(just_a_sec/3); /* 1/3 second */ X#endif X top_article(); X reread = FALSE; X return AS_NORM; X case SRCH_NOTFOUND: X fputs("\n\n\n\nNot found.\n",stdout) FLUSH; X art = curr_art; /* restore to current article */ X return AS_ASK; X case SRCH_FOUND: X if (cmd == Ctl('n') || cmd == Ctl('p')) { X oldsubject = TRUE; X reread = FALSE; X } X break; X } X return AS_NORM; X } X#else /* !ARTSEARCH */ X buf[1] = '\0'; X notincl(buf); X return AS_ASK; X#endif X case 'u': /* unsubscribe from this newsgroup? */ X rcchar[ng] = NEGCHAR; X return AS_CLEAN; X case 'M': X if (art <= lastart) { X delay_unmark(artp); X oneless(artp); X printf("\nArticle %ld will return.\n",(long)art) FLUSH; X } X return AS_ASK; X case 'm': X if (art >= absfirst && art <= lastart) { X unmark_as_read(); X printf("\nArticle %ld marked as still unread.\n",(long)art) FLUSH; X } X return AS_ASK; X case 'c': /* catch up */ X switch (ask_catchup()) { X case 'n': X return AS_ASK; X case 'u': X return AS_CLEAN; X } X art = lastart+1; X artp = Nullart; X forcelast = FALSE; X return AS_NORM; X case 'Q': X exit_code = NG_ASK; X /* FALL THROUGH */ X case 'q': /* go back up to newsgroup level? */ X return AS_CLEAN; X case 'j': X putchar('\n') FLUSH; X if (art >= absfirst && art <= lastart) X mark_as_read(); X return AS_ASK; X case 'h': { /* help? */ X int cmd; X X if ((cmd = help_art()) > 0) X pushchar(cmd); X return AS_ASK; X } X case '&': X if (switcheroo()) /* get rest of command */ X return AS_INP; /* if rubbed out, try something else */ X return AS_ASK; X case '#': X#ifdef VERBOSE X IF(verbose) X printf("\nThe last article is %ld.\n",(long)lastart) FLUSH; X ELSE X#endif X#ifdef TERSE X printf("\n%ld\n",(long)lastart) FLUSH; X#endif X return AS_ASK; X case '+': /* enter selection mode */ Xrun_the_selector: X *buf = do_selector(*buf); X switch (*buf) { X case '+': X putchar('\n') FLUSH; X return AS_ASK; X case 'Q': X exit_code = NG_ASK; X /* FALL THROUGH */ X case 'q': X break; X case 'N': X exit_code = NG_SELNEXT; X break; X case 'P': X exit_code = NG_SELPRIOR; X break; X default: X if (toread[ng]) X return AS_NORM; X break; X } X return AS_CLEAN; X case '=': { /* list subjects */ X char tmpbuf[256]; X ART_NUM oldart = art; X int cmd, len; X char *s; X char *subjline = getval("SUBJLINE",Nullch); X ARTICLE *ap = article_ptr(firstart); X X page_init(); X for (i=firstart; i<=lastart && !int_count; i++, ap++) { X if (!(ap->flags & AF_READ) && (s = fetchsubj(i,FALSE)) != Nullch) { X sprintf(tmpbuf,"%5ld ", i); X len = strlen(tmpbuf); X if (subjline) { X art = i; X interp(tmpbuf + len, sizeof tmpbuf - len, subjline); X } X else X safecpy(tmpbuf + len, s, sizeof tmpbuf - len); X if (cmd = print_lines(tmpbuf,NOMARKING)) { X if (cmd > 0) X pushchar(cmd); X break; X } X } X } X int_count = 0; X art = oldart; X return AS_ASK; X } X case '^': X top_article(); X#ifdef ARTSEARCH X srchahead = 0; X#endif X return AS_NORM; X#ifdef DEBUG X case 'D': X printf("\nFirst article: %ld\n",(long)firstart) FLUSH; X { X ARTICLE *ap = article_ptr(firstart); X for (i = firstart; i <= lastart && !int_count; i++, ap++) { X if (ap->subj) X printf("%5ld %c %s\n",i,(was_read(i)?'y':'n'), X ap->subj->str) FLUSH; X } X } X int_count = 0; X return AS_ASK; X#endif X case 'v': X if (art <= lastart) { X reread = TRUE; X do_hiding = FALSE; X } X return AS_NORM; X#ifdef ROTATION X case Ctl('x'): X#endif X case Ctl('r'): X#ifdef ROTATION X rotate = (*buf==Ctl('x')); X#endif X if (art <= lastart) X reread = TRUE; X else X forcelast = TRUE; X return AS_NORM; X#ifdef ROTATION X case 'X': X rotate = !rotate; X /* FALL THROUGH */ X#else X case Ctl('x'): X case 'x': X case 'X': X notincl("x"); X return AS_ASK; X#endif X case 'l': case Ctl('l'): /* refresh screen */ X refresh_screen: X if (art <= lastart) { X reread = TRUE; X clear(); X do_fseek = TRUE; X artline = topline; X if (artline < 0) X artline = 0; X } X return AS_NORM; X case Ctl('^'): X carriage_return(); X erase_eol(); /* erase the prompt */ X#ifdef MAILCALL X setmail(TRUE); /* force a mail check */ X#endif X return AS_ASK; X#ifdef INNERSEARCH X case Ctl('e'): X if (art <= lastart) { X reread = TRUE; X do_fseek = TRUE; X innerlight = artline - 1; X topline = artline; X innersearch = artsize; X gline = 0; X hide_everything = 'b'; X } X return AS_NORM; X#endif X case 'B': /* back up one line */ X case 'b': case Ctl('b'): /* back up a page */ X if (art <= lastart) { X ART_LINE target; X X reread = TRUE; X clear(); X do_fseek = TRUE; X if (*buf == 'B') X target = topline - 1; X else { X target = topline - (LINES - 2); X if (marking && (marking_areas & BACKPAGE_MARKING)) { X highlight = topline; X } X } X artline = topline; X if (artline >= 0) do { X artline--; X } while(artline >= 0 && artline > target && vrdary(artline-1) >= 0); X topline = artline; X if (artline < 0) X artline = 0; X } X return AS_NORM; X case '!': /* shell escape */ X if (escapade()) X return AS_INP; X return AS_ASK; X case 'C': { X cancel_article(); X return AS_ASK; X } X case 'Z': X case 'z': { X supersede_article(); /* supersedes */ X return AS_ASK; X } X case 'R': X case 'r': { /* reply? */ X reply(); X return AS_ASK; X } X case 'F': X case 'f': { /* followup command */ X followup(); X forcegrow = TRUE; /* recalculate lastart */ X return AS_ASK; X } X case Ctl('f'): { /* forward? */ X forward(); X return AS_ASK; X } X case '|': X case 'w': case 'W': X case 's': case 'S': /* save command */ X case 'e': /* extract command */ X if (save_article() == SAVE_ABORT) X return AS_INP; X int_count = 0; X return AS_ASK; X case 'E': X if (decode_fp) X decode_end(); X else X putchar('\n') FLUSH; X return AS_ASK; X case 'Y': /* yank back M articles */ X yankback(); X top_article(); /* from the beginning */ X return AS_NORM; /* pretend nothing happened */ X#ifdef STRICTCR X case '\n': X fputs(badcr,stdout) FLUSH; X return AS_ASK; X#endif X case '_': X if (!finish_dblchar()) X return AS_INP; X switch (buf[1] & 0177) { X case 'P': X art--; X goto check_dec_art; X case 'N': X if (art > lastart) X art = absfirst; X else X art++; X if (art <= lastart) X reread = TRUE; X#ifdef ARTSEARCH X srchahead = 0; X#endif X return AS_NORM; X case '+': X if (!artp) X goto not_threaded; X if (ThreadedGroup) { X select_arts_thread(artp, 0); X printf("\nSelected all articles in this thread.\n"); X } else { X select_arts_subject(artp, 0); X printf("\nSelected all articles in this subject.\n"); X } X if ((artp = first_art(artp->subj)) != Nullart) { X if (art == article_num(artp)) X return AS_ASK; X art = article_num(artp); X } X return AS_NORM; X case '-': X if (!artp) X goto not_threaded; X if (sel_mode == SM_THREAD) { X deselect_arts_thread(artp); X printf("\nDeselected all articles in this thread.\n"); X } else { X deselect_arts_subject(artp); X printf("\nDeselected all articles in this subject.\n"); X } X return AS_ASK; X#ifdef CHARSUBST X case 'C': X if (!*(++charsubst)) X charsubst = charsets; X goto refresh_screen; X#endif X case 'a': case 's': case 't': case 'T': X *buf = buf[1]; X goto run_the_selector; X } X /* FALL THROUGH */ X default: X printf("\n%s",hforhelp) FLUSH; X settle_down(); X break; X } X return AS_ASK; X} X X#ifdef MAILCALL X/* see if there is any mail */ X Xvoid Xsetmail(force) Xbool_int force; X{ X if (force) X mailcount = 0; X if (!(mailcount++)) { X char *mailfile = filexp(getval("MAILFILE",MAILFILE)); X X if (stat(mailfile,&filestat) < 0 || !filestat.st_size X || filestat.st_atime > filestat.st_mtime) X mailcall = nullstr; X else X mailcall = getval("MAILCALL","(Mail) "); X } X mailcount %= 5; /* check every 5 articles */ X} X#endif X Xvoid Xsetdfltcmd() X{ X if (!toread[ng]) { X if (art > lastart) X dfltcmd = "qnp"; X else X dfltcmd = "npq"; X } X else { X#ifdef ARTSEARCH X if (srchahead) X dfltcmd = "^Nnpq"; X else X#endif X dfltcmd = "npq"; X } X} X X/* Ask the user about catching-up the current group. Returns 'y' if yes, X** 'n' or 'N' if no ('N' means we used one line when in the selector), X** or 'u' for yes with unsubscribe. Actually performs the catchup and X** unsubscription as needed. X*/ Xchar Xask_catchup() X{ X char ch; X bool use_one_line = (mode == 't'); X int leave = 0; X X if (!use_one_line) X putchar('\n') FLUSH; Xreask_catchup: X#ifdef VERBOSE X IF(verbose) X in_char("Do you really want to mark everything as read?",'C',"yn#h"); X ELSE X#endif X#ifdef TERSE X in_char("Really?",'C',"ynh"); X#endif X#ifdef VERIFY X printcmd(); X#endif X if ((ch = *buf) == 'h') { X use_one_line = FALSE; X#ifdef VERBOSE X IF(verbose) X fputs("\n\ XType y or SP to mark all articles as read.\n\ XType n to leave articles marked as they are.\n\ XEnter a number to mark all but the last # articles as read.\n\ XType u to mark everything read and unsubscribe.\n\n\ X",stdout) FLUSH; X ELSE X#endif X#ifdef TERSE X fputs("\n\ Xy or SP to mark all read.\n\ Xn to forget it.\n\ Xu to mark all and unsubscribe.\n\n\ X",stdout) FLUSH; X#endif X goto reask_catchup; X } X if (ch == 'n' || ch == 'q') { X if (use_one_line) X return 'N'; X putchar('\n') FLUSH; X return 'n'; X } X if (ch == '#') { X use_one_line = FALSE; X in_char("\nEnter the number of articles to leave unread: ", 'C', "0"); X if ((ch = *buf) == '0') X ch = 'y'; X } X if (isdigit(ch)) { X buf[1] = FINISHCMD; X if (!finish_command(FALSE)) { X use_one_line = FALSE; X putchar('\n') FLUSH; X goto reask_catchup; X } X else { X leave = atoi(buf); X ch = 'y'; X } X } X if (ch != 'y' && ch != 'u') { X use_one_line = FALSE; X printf("\n%s\n", hforhelp) FLUSH; X settle_down(); X goto reask_catchup; X } X if (mode == 'n') { X putchar('\n') FLUSH; X catch_up(ng, leave); X } X else { X int i; X ARTICLE *ap; X for (i = firstart, ap = article_ptr(i); i <= lastart-leave; i++, ap++) X ap->flags = ((ap->flags & ~sel_mask) | AF_READ); X selected_count = selected_subj_cnt = selected_only = 0; X toread[ng] = 0; X if (dmcount) X yankback(); X putchar('\n') FLUSH; X } X if (ch == 'u') { X rcchar[ng] = NEGCHAR; X printf("(If you meant to hit 'y' instead of 'u', press '-'.)\n"); X } X return ch; X} X Xchar Xask_memorize(ch) Xchar_int ch; X{ X bool thread_cmd = (ch == 'T'); X bool use_one_line = (mode == 't'); X char *mode_string = (thread_cmd? "thread" : "subject"); X char *mode_phrase = (thread_cmd? "replies to this article" : X "this subject and all replies"); X ART_NUM art_hold = art; X ARTICLE *artp_hold = artp; X X if (!use_one_line) X putchar('\n') FLUSH; X sprintf(cmd_buf,"Memorize %s command:", mode_string); Xreask_memorize: X in_char(cmd_buf, 'm', "+.j,cC"); X#ifdef VERIFY X printcmd(); X#endif X if ((ch = *buf) == 'h') { X use_one_line = FALSE; X#ifdef VERBOSE X IF(verbose) X printf("\n\ XType + or SP to auto-select this %s (i.e. includes future articles).\n\ XType . to auto-select %s.\n\ XType j to auto-kill (junk) this %s.\n\ XType , to auto-kill %s.\n\ XType c to clear all selection/killing on this %s.\n\ XType C to clear all selection/killing on %s.\n\ XType q to abort the operation.\n\n\ X",mode_string,mode_phrase,mode_string,mode_phrase,mode_string,mode_phrase) FLUSH; X ELSE X#endif X#ifdef TERSE X printf("\n\ X+ or SP auto-selects this %s.\n\ X. auto-selects %s.\n\ Xj auto-kills this %s.\n\ X, auto-kills %s.\n\ Xc clears auto-commands for this %s.\n\ XC clears auto-commands for %s.\n\ Xq aborts.\n\n\ X",mode_string,mode_phrase,mode_string,mode_phrase,mode_string,mode_phrase) FLUSH; X#endif X goto reask_memorize; X } X if (ch == 'q') { X if (use_one_line) X return 'Q'; X putchar('\n'); X return 'q'; X } X if (ch == '+') { X if (!thread_cmd) { X (void)art_search(buf, (sizeof buf), TRUE); X art = art_hold; X artp = artp_hold; X ch = '.'; X } else X ch = (use_one_line? '+' : '.'); X if (thread_cmd) X select_arts_thread(artp, AUTO_SELECTALL); X else X select_arts_subject(artp, 0); X if (mode != 't') X printf("\nSelection memorized.\n"); X } else if (ch == '.') { X if (!thread_cmd) { X (void)art_search(buf, (sizeof buf), TRUE); X art = art_hold; X artp = artp_hold; X } else X ch = (use_one_line? '+' : '.'); X select_subthread(artp,thread_cmd? AUTO_SELECT : 0); X if (mode != 't') X printf("\nSelection memorized.\n"); X } else if (ch == 'j') { X if (!thread_cmd) { X *buf = 'K'; X (void)art_search(buf, (sizeof buf), TRUE); X art = art_hold; X artp = artp_hold; X } X if (thread_cmd) X kill_thread(artp->subj->thread,KF_ALL|KF_KILLFILE); X else X kill_subject(artp->subj,KF_ALL); X if (mode != 't') X printf("\nKill memorized.\n"); X } else if (ch == ',') { X if (!thread_cmd) { X (void)art_search(buf, (sizeof buf), TRUE); X art = art_hold; X artp = artp_hold; X } X kill_subthread(artp,KF_ALL|(thread_cmd?KF_KILLFILE:0)); X if (mode != 't') X printf("\nKill memorized.\n"); X } else if (ch == 'c') { X if (thread_cmd) X clear_thread(artp->subj->thread); X else X clear_subject(artp->subj); X } else if (ch == 'C') { X clear_subthread(artp); X } else { X use_one_line = FALSE; X printf("\n%s\n", hforhelp) FLUSH; X settle_down(); X goto reask_memorize; X } X if (!use_one_line) X putchar('\n') FLUSH; X return ch; X} SHAR_EOF $shar_touch -am 1118220194 'trn-3.6/ng.c' && chmod 0644 'trn-3.6/ng.c' || echo 'restore of trn-3.6/ng.c failed' shar_count="`wc -c < 'trn-3.6/ng.c'`" test 35273 -eq "$shar_count" || echo "trn-3.6/ng.c: original size 35273, current size $shar_count" rm -f _sharnew.tmp fi # ============= trn-3.6/ng.h ============== if test -f 'trn-3.6/ng.h' && test X"$1" != X"-c"; then echo 'x - skipping trn-3.6/ng.h (file already exists)' rm -f _sharnew.tmp else > _sharnew.tmp echo 'x - extracting trn-3.6/ng.h (text)' sed 's/^X//' << 'SHAR_EOF' > 'trn-3.6/ng.h' && X/* $Id: ng.h,v 3.0 1991/09/09 20:23:31 davison Trn $ X */ X/* This software is Copyright 1991 by Stan Barber. X * X * Permission is hereby granted to copy, reproduce, redistribute or otherwise X * use this software as long as: there is no monetary profit gained X * specifically from the use or reproduction of this software, it is not X * sold, rented, traded or otherwise marketed, and this copyright notice is X * included prominently in any copy made. X * X * The authors make no claims as to the fitness or correctness of this software X * for any use whatsoever, and it is provided as is. Any use of this software X * is at the user's own risk. X */ X XEXT ART_NUM art INIT(0); /* current or prospective article # */ X XEXT ART_NUM recent_art; /* previous article # for '-' command */ XEXT ART_NUM curr_art; /* current article # */ XEXT ARTICLE *recent_artp INIT(0);/* article_ptr equivilents */ XEXT ARTICLE *curr_artp INIT(0); XEXT ARTICLE *artp INIT(0); /* the article ptr we use when art is 0 */ X XEXT int checkcount INIT(0); /* how many articles have we read */ X /* in the current newsgroup since */ X /* the last checkpoint? */ XEXT int docheckwhen INIT(20); /* how often to do checkpoint */ X X#ifdef MAILCALL XEXT int mailcount INIT(0); /* check for mail when 0 mod 10 */ X#endif XEXT char *mailcall INIT(nullstr); XEXT bool forcelast INIT(FALSE); /* ought we show "End of newsgroup"? */ XEXT bool forcegrow INIT(FALSE); /* do we want to recalculate size */ X /* of newsgroup, e.g. after posting? */ X X#define NG_ERROR -1 X#define NG_NORM 0 X#define NG_ASK 1 X#define NG_MINUS 2 X#define NG_SELPRIOR 3 X#define NG_SELNEXT 4 X Xvoid ng_init _((void)); Xint do_newsgroup _((char*)); Xint art_switch _((void)); X#ifdef MAILCALL Xvoid setmail _((bool_int)); X#endif Xvoid setdfltcmd _((void)); Xchar ask_catchup _((void)); Xchar ask_memorize _((char_int)); SHAR_EOF $shar_touch -am 0711223693 'trn-3.6/ng.h' && chmod 0644 'trn-3.6/ng.h' || echo 'restore of trn-3.6/ng.h failed' shar_count="`wc -c < 'trn-3.6/ng.h'`" test 1846 -eq "$shar_count" || echo "trn-3.6/ng.h: original size 1846, current size $shar_count" rm -f _sharnew.tmp fi # ============= trn-3.6/ngdata.c ============== if test -f 'trn-3.6/ngdata.c' && test X"$1" != X"-c"; then echo 'x - skipping trn-3.6/ngdata.c (file already exists)' rm -f _sharnew.tmp else > _sharnew.tmp echo 'x - extracting trn-3.6/ngdata.c (text)' sed 's/^X//' << 'SHAR_EOF' > 'trn-3.6/ngdata.c' && X/* $Id: ngdata.c,v 3.0 1992/02/01 03:09:32 davison Trn $ X */ X/* This software is Copyright 1991 by Stan Barber. X * X * Permission is hereby granted to copy, reproduce, redistribute or otherwise X * use this software as long as: there is no monetary profit gained X * specifically from the use or reproduction of this software, it is not X * sold, rented, traded or otherwise marketed, and this copyright notice is X * included prominently in any copy made. X * X * The authors make no claims as to the fitness or correctness of this software X * for any use whatsoever, and it is provided as is. Any use of this software X * is at the user's own risk. X */ X X#include "EXTERN.h" X#include "common.h" X#include "rcstuff.h" X#include "trn.h" X#include "cache.h" SHAR_EOF : || echo 'restore of trn-3.6/ngdata.c failed' fi echo 'End of archive part 5' echo 'File trn-3.6/ngdata.c is continued in part 6' echo 6 > _sharseq.tmp exit 0