Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Posting-Version: version B 2.10.2 9/3/84; site genrad.UUCP Path: utzoo!decvax!genrad!sources-request From: sources-request@genrad.UUCP Newsgroups: mod.sources Subject: rn version 4.3 (kit 6 of 9) Message-ID: <827@genrad.UUCP> Date: Sat, 11-May-85 07:56:57 EDT Article-I.D.: genrad.827 Posted: Sat May 11 07:56:57 1985 Date-Received: Sun, 12-May-85 02:53:25 EDT Sender: john@genrad.UUCP Organization: System Development Corporation R&D, Santa Monica Lines: 2864 Approved: john@genrad.UUCP From: lwall@sdcrdcf.UUCP (Larry Wall) ---------------- cut here --------------- #! /bin/sh # Make a new directory for the rn sources, cd to it, and run kits 1 thru 9 # through sh. When all 9 kits have been run, read README. echo "This is rn kit 6 (of 9). If kit 6 is complete, the line" echo '"'"End of kit 6 (of 9)"'" will echo at the end.' echo "" export PATH || (echo "You didn't use sh, you clunch." ; kill $$) echo Extracting util.c cat >util.c <<'!STUFFY!FUNK!' /* $Header: util.c,v 4.3 85/05/01 11:51:44 lwall Exp $ * * $Log: util.c,v $ * Revision 4.3 85/05/01 11:51:44 lwall * Baseline for release with 4.3bsd. * */ #include "EXTERN.h" #include "common.h" #include "final.h" #include "ndir.h" #include "INTERN.h" #include "util.h" void util_init() { ; } /* fork and exec a shell command */ int doshell(shl,s) char *s, *shl; { int status, pid, w; register int (*istat)(), (*qstat)(); int (*signal())(); char *shell; #ifdef SIGTSTP sigset(SIGTSTP,SIG_DFL); sigset(SIGCONT,SIG_DFL); #endif if (shl != Nullch) shell = shl; else if ((shell = getenv("SHELL")) == Nullch || !*shell) shell = PREFSHELL; if ((pid = vfork()) == 0) { if (*s) execl(shell, shell, "-c", s, 0); else execl(shell, shell, Nullch, Nullch, 0); _exit(127); } #ifndef lint istat = signal(SIGINT, SIG_IGN); qstat = signal(SIGQUIT, SIG_IGN); #else istat = Null(int (*)()); qstat = Null(int (*)()); #endif lint waiting = TRUE; while ((w = wait(&status)) != pid && w != -1) ; if (w == -1) status = -1; waiting = FALSE; signal(SIGINT, istat); signal(SIGQUIT, qstat); #ifdef SIGTSTP sigset(SIGTSTP,stop_catcher); sigset(SIGCONT,cont_catcher); #endif return status; } static char nomem[] = "rn: out of memory!\n"; /* paranoid version of malloc */ char * safemalloc(size) MEM_SIZE size; { char *ptr; char *malloc(); ptr = malloc(size?size:1); /* malloc(0) is NASTY on our system */ if (ptr != Nullch) return ptr; else { fputs(nomem,stdout) FLUSH; sig_catcher(0); } /*NOTREACHED*/ } /* paranoid version of realloc */ char * saferealloc(where,size) char *where; MEM_SIZE size; { char *ptr; char *realloc(); ptr = realloc(where,size?size:1); /* realloc(0) is NASTY on our system */ if (ptr != Nullch) return ptr; else { fputs(nomem,stdout) FLUSH; sig_catcher(0); } /*NOTREACHED*/ } /* safe version of string copy */ char * safecpy(to,from,len) char *to; register char *from; register int len; { register char *dest = to; if (from != Nullch) for (len--; len && (*dest++ = *from++); len--) ; *dest = '\0'; return to; } /* safe version of string concatenate, with \n deletion and space padding */ char * safecat(to,from,len) char *to; register char *from; register int len; { register char *dest = to; len--; /* leave room for null */ if (*dest) { while (len && *dest++) len--; if (len) { len--; *(dest-1) = ' '; } } if (from != Nullch) while (len && (*dest++ = *from++)) len--; if (len) dest--; if (*(dest-1) == '\n') dest--; *dest = '\0'; return to; } /* copy a string up to some (non-backslashed) delimiter, if any */ char * cpytill(to,from,delim) register char *to, *from; register int delim; { for (; *from; from++,to++) { if (*from == '\\' && from[1] == delim) from++; else if (*from == delim) break; *to = *from; } *to = '\0'; return from; } /* return ptr to little string in big string, NULL if not found */ char * instr(big, little) char *big, *little; { register char *t, *s, *x; for (t = big; *t; t++) { for (x=t,s=little; *s; x++,s++) { if (!*x) return Nullch; if (*s != *x) break; } if (!*s) return t; } return Nullch; } /* effective access */ #ifdef SETUIDGID int eaccess(filename, mod) char *filename; int mod; { int protection, euid; mod &= 7; /* remove extraneous garbage */ if (stat(filename, &filestat) < 0) return -1; euid = geteuid(); if (euid == ROOTID) return 0; protection = 7 & (filestat.st_mode >> (filestat.st_uid == euid ? 6 : (filestat.st_gid == getegid() ? 3 : 0) )); if ((mod & protection) == mod) return 0; errno = EACCES; return -1; } #endif /* * Get working directory */ #ifdef GETWD #define dot "." #define dotdot ".." static char *name; static DIR *dirp; static int off; static struct stat d, dd; static struct direct *dir; char * getwd(np) char *np; { long rdev, rino; *np++ = '/'; *np = 0; name = np; off = -1; stat("/", &d); rdev = d.st_dev; rino = d.st_ino; for (;;) { stat(dot, &d); if (d.st_ino==rino && d.st_dev==rdev) goto done; if ((dirp = opendir(dotdot)) == Null(DIR *)) prexit("getwd: cannot open ..\n"); stat(dotdot, &dd); chdir(dotdot); if(d.st_dev == dd.st_dev) { if(d.st_ino == dd.st_ino) goto done; do if ((dir = readdir(dirp)) == Null(struct direct *)) prexit("getwd: read error in ..\n"); while (dir->d_ino != d.st_ino); } else do { if ((dir = readdir(dirp)) == Null(struct direct *)) prexit("getwd: read error in ..\n"); stat(dir->d_name, &dd); } while(dd.st_ino != d.st_ino || dd.st_dev != d.st_dev); cat(); closedir(dirp); } done: name--; if (chdir(name) < 0) { printf("getwd: can't cd back to %s\n",name) FLUSH; sig_catcher(0); } return (name); } void cat() { register i, j; i = -1; while (dir->d_name[++i] != 0); if ((off+i+2) > 1024-1) return; for(j=off+1; j>=0; --j) name[j+i+1] = name[j]; if (off >= 0) name[i] = '/'; off=i+off+1; name[off] = 0; for(--i; i>=0; --i) name[i] = dir->d_name[i]; } void prexit(cp) char *cp; { write(2, cp, strlen(cp)); sig_catcher(0); } #else char * getwd(np) /* shorter but slower */ char *np; { FILE *popen(); FILE *pipefp = popen("/bin/pwd","r"); if (pipefd == Nullfp) { printf("Can't run /bin/pwd\n") FLUSH; finalize(1); } fgets(np,512,pipefp); np[strlen(np)-1] = '\0'; /* wipe out newline */ pclose(pipefp); return np; } #endif /* just like fgets but will make bigger buffer as necessary */ char * get_a_line(original_buffer,buffer_length,fp) char *original_buffer; register int buffer_length; FILE *fp; { register int bufix = 0; register int nextch; register char *some_buffer_or_other = original_buffer; do { if (bufix >= buffer_length) { buffer_length *= 2; if (some_buffer_or_other == original_buffer) { /* currently static? */ some_buffer_or_other = safemalloc((MEM_SIZE)buffer_length+1); strncpy(some_buffer_or_other,original_buffer,buffer_length/2); /* so we must copy it */ } else { /* just grow in place, if possible */ some_buffer_or_other = saferealloc(some_buffer_or_other, (MEM_SIZE)buffer_length+1); } } if ((nextch = getc(fp)) == EOF) return Nullch; some_buffer_or_other[bufix++] = (char) nextch; } while (nextch && nextch != '\n'); some_buffer_or_other[bufix] = '\0'; len_last_line_got = bufix; return some_buffer_or_other; } /* copy a string to a safe spot */ char * savestr(str) char *str; { register char *newaddr = safemalloc((MEM_SIZE)(strlen(str)+1)); strcpy(newaddr,str); return newaddr; } int makedir(dirname,nametype) register char *dirname; int nametype; { #ifdef MAKEDIR register char *end; register char *s; char tmpbuf[1024]; register char *tbptr = tmpbuf+5; for (end = dirname; *end; end++) ; /* find the end */ if (nametype == MD_FILE) { /* not to create last component? */ for (--end; end != dirname && *end != '/'; --end) ; if (*end != '/') return 0; /* nothing to make */ *end = '\0'; /* isolate file name */ } strcpy(tmpbuf,"mkdir"); s = end; for (;;) { if (stat(dirname,&filestat) >= 0) { /* does this much exist? */ *s = '/'; /* mark this as existing */ break; } s = rindex(dirname,'/'); /* shorten name */ if (!s) /* relative path! */ break; /* hope they know what they are doing */ *s = '\0'; /* mark as not existing */ } for (s=dirname; s <= end; s++) { /* this is grody but efficient */ if (!*s) { /* something to make? */ sprintf(tbptr," %s",dirname); tbptr += strlen(tbptr); /* make it, sort of */ *s = '/'; /* mark it made */ } } if (nametype == MD_DIR) /* don't need final slash unless */ *end = '\0'; /* a filename follows the dir name */ return (tbptr==tmpbuf+5 ? 0 : doshell(sh,tmpbuf)); /* exercise our faith */ #else sprintf(cmd_buf,"%s %s %d", filexp(DIRMAKER), dirname, nametype); return doshell(sh,cmd_buf); #endif } #ifdef SETENV static bool firstsetenv = TRUE; extern char **environ; void setenv(nam,val) char *nam, *val; { register int i=envix(nam); /* where does it go? */ if (!environ[i]) { /* does not exist yet */ if (firstsetenv) { /* need we copy environment? */ int j; #ifndef lint char **tmpenv = (char**) /* point our wand at memory */ safemalloc((MEM_SIZE) (i+2) * sizeof(char*)); #else char **tmpenv = Null(char **); #endif lint firstsetenv = FALSE; for (j=0; j *curlen) { /* need more room? */ if (*curlen) *strptr = saferealloc(*strptr,(MEM_SIZE)newlen); else *strptr = safemalloc((MEM_SIZE)newlen); *curlen = newlen; } } void setdef(buffer,dflt) char *buffer,*dflt; { #ifdef STRICTCR if (*buffer == ' ') #else if (*buffer == ' ' || *buffer == '\n') #endif { if (*dflt == '^' && isupper(dflt[1])) *buffer = Ctl(dflt[1]); else *buffer = *dflt; } } !STUFFY!FUNK! echo Extracting respond.c cat >respond.c <<'!STUFFY!FUNK!' /* $Header: respond.c,v 4.3 85/05/01 11:47:04 lwall Exp $ * * $Log: respond.c,v $ * Revision 4.3 85/05/01 11:47:04 lwall * Baseline for release with 4.3bsd. * */ #include "EXTERN.h" #include "common.h" #include "intrp.h" #include "head.h" #include "term.h" #include "ng.h" #include "util.h" #include "rn.h" #include "intrp.h" #include "artio.h" #include "final.h" #include "INTERN.h" #include "respond.h" static char nullart[] = "\nNull article\n"; void respond_init() { ; } int save_article() { bool use_pref; register char *s, *c; char altbuf[CBUFLEN]; int iter; bool interactive = (buf[1] == FINISHCMD); if (!finish_command(interactive)) /* get rest of command */ return SAVE_ABORT; use_pref = isupper(*buf); #ifdef ASYNC_PARSE parse_maybe(art); #endif savefrom = (*buf=='w' || *buf=='W' ? htype[PAST_HEADER].ht_minpos : 0); if (artopen(art) == Nullfp) { #ifdef VERBOSE IF(verbose) fputs("\n\ Saving null articles is not very productive! :-)\n\ ",stdout) FLUSH; ELSE #endif #ifdef TERSE fputs(nullart,stdout) FLUSH; #endif return SAVE_DONE; } if (chdir(cwd)) { printf(nocd,cwd) FLUSH; sig_catcher(0); } if (savedest) free(savedest); if ((s = index(buf,'|')) != Nullch) { /* is it a pipe command? */ s++; /* skip the | */ while (*s == ' ') s++; safecpy(altbuf,filexp(s),sizeof altbuf); savedest = altbuf; interp(cmd_buf, (sizeof cmd_buf), getval("PIPESAVER",PIPESAVER)); /* then set up for command */ resetty(); /* restore tty state */ if (use_pref) /* use preferred shell? */ doshell(Nullch,cmd_buf); /* do command with it */ else doshell(sh,cmd_buf); /* do command with sh */ noecho(); /* and stop echoing */ crmode(); /* and start cbreaking */ savedest = savestr(savedest); } else { /* normal save */ bool there, mailbox; char *savename = getval("SAVENAME",SAVENAME); s = buf+1; /* skip s or S */ if (*s == '-') { /* if they are confused, skip - also */ #ifdef VERBOSE IF(verbose) fputs("Warning: '-' ignored. This isn't readnews.\n",stdout) FLUSH; ELSE #endif #ifdef TERSE fputs("'-' ignored.\n",stdout) FLUSH; #endif s++; } for (; *s == ' '; s++); /* skip spaces */ safecpy(altbuf,filexp(s),sizeof altbuf); s = altbuf; if (! index(s,'/')) { interp(buf, (sizeof buf), getval("SAVEDIR",SAVEDIR)); if (makedir(buf,MD_DIR)) /* ensure directory exists */ strcpy(buf,cwd); if (*s) { for (c = buf; *c; c++) ; *c++ = '/'; strcpy(c,s); /* add filename */ } s = buf; } for (iter = 0; (there = stat(s,&filestat) >= 0) && (filestat.st_mode & S_IFDIR); iter++) { /* is it a directory? */ c = (s+strlen(s)); *c++ = '/'; /* put a slash before filename */ interp(c, s==buf?(sizeof buf):(sizeof altbuf), iter ? "News" : savename ); /* generate a default name somehow or other */ if (index(c,'/')) { /* yikes, a '/' in the filename */ makedir(s,MD_FILE); } } if (*s != '/') { /* relative path? */ c = (s==buf ? altbuf : buf); sprintf(c, "%s/%s", cwd, s); s = c; /* absolutize it */ } s = savedest = savestr(s); /* doesn't move any more */ /* make it handy for %b */ if (!there) { if (mbox_always) mailbox = TRUE; else if (norm_always) mailbox = FALSE; else { char *dflt = (instr(savename,"%a") ? "nyq" : "ynq"); sprintf(cmd_buf, "\nFile %s doesn't exist--\n use mailbox format? [%s] ", s,dflt); reask_save: in_char(cmd_buf); putchar('\n') FLUSH; setdef(cmd_buf,dflt); #ifdef VERIFY printcmd(); #endif if (*buf == 'h') { #ifdef VERBOSE IF(verbose) printf("\n\ Type y to create %s as a mailbox.\n\ Type n to create it as a normal file.\n\ Type q to abort the save.\n\ ",s) FLUSH; ELSE #endif #ifdef TERSE fputs("\n\ y to create mailbox.\n\ n to create normal file.\n\ q to abort.\n\ ",stdout) FLUSH; #endif goto reask_save; } else if (*buf == 'n') { mailbox = FALSE; } else if (*buf == 'y') { mailbox = TRUE; } else if (*buf == 'q') { goto s_bomb; } else { fputs(hforhelp,stdout) FLUSH; settle_down(); goto reask_save; } } } else if (filestat.st_mode & S_IFCHR) mailbox = FALSE; else { int tmpfd; tmpfd = open(s,0); if (tmpfd == -1) mailbox = FALSE; else { read(tmpfd,buf,LBUFLEN); c = buf; if (!isspace(MBOXCHAR)) while (isspace(*c)) c++; mailbox = (*c == MBOXCHAR); close(tmpfd); } } safecpy(cmd_buf, filexp(mailbox ? getval("MBOXSAVER",MBOXSAVER) : getval("NORMSAVER",NORMSAVER) ), sizeof cmd_buf); /* format the command */ resetty(); /* make terminal behave */ if (doshell(use_pref?Nullch:SH,cmd_buf)) fputs("Not saved",stdout); else printf("%s to %s %s", there?"Appended":"Saved", mailbox?"mailbox":"file", s); if (interactive) putchar('\n') FLUSH; noecho(); /* make terminal do what we want */ crmode(); } s_bomb: if (chdir(spool) || chdir(ngdir)) { printf(nocd,ngdir) FLUSH; sig_catcher(0); } return SAVE_DONE; } int cancel_article() { char *artid_buf; char *ngs_buf; char *from_buf; char *reply_buf; int myuid = getuid(); int r = -1; if (artopen(art) == Nullfp) { #ifdef VERBOSE IF(verbose) fputs("\n\ Cancelling null articles is your idea of fun? :-)\n\ ",stdout) FLUSH; ELSE #endif #ifdef TERSE fputs(nullart,stdout) FLUSH; #endif return r; } reply_buf = fetchlines(art,REPLY_LINE); from_buf = fetchlines(art,FROM_LINE); artid_buf = fetchlines(art,ARTID_LINE); ngs_buf = fetchlines(art,NGS_LINE); if (!instr(from_buf,sitename) || (!instr(from_buf,logname) && !instr(reply_buf,logname) && #ifdef NEWSADMIN myuid != newsuid && #endif myuid != ROOTID ) ) #ifdef VERBOSE IF(verbose) fputs("You can't cancel someone else's article\n",stdout) FLUSH; ELSE #endif #ifdef TERSE fputs("Not your article\n",stdout) FLUSH; #endif else { tmpfp = fopen(headname,"w"); /* open header file */ if (tmpfp == Nullfp) { printf(cantcreate,headname) FLUSH; goto no_cancel; } interp(buf, (sizeof buf), getval("CANCELHEADER",CANCELHEADER)); fputs(buf,tmpfp); fclose(tmpfp); r = doshell(sh,filexp(getval("CANCEL",CANCEL))); } no_cancel: free(artid_buf); free(ngs_buf); free(from_buf); free(reply_buf); return r; } void reply() { bool incl_body = (*buf == 'R'); char *maildoer = savestr(filexp(getval("MAILPOSTER",MAILPOSTER))); if (artopen(art) == Nullfp) { #ifdef VERBOSE IF(verbose) fputs("\nBut null articles are so dull! :-)\n",stdout) FLUSH; ELSE #endif #ifdef TERSE fputs(nullart,stdout) FLUSH; #endif goto no_reply; } tmpfp = fopen(headname,"w"); /* open header file */ if (tmpfp == Nullfp) { printf(cantcreate,headname) FLUSH; goto no_reply; } interp(buf, (sizeof buf), getval("MAILHEADER",MAILHEADER)); fputs(buf,tmpfp); if (!instr(maildoer,"%h")) #ifdef VERBOSE IF(verbose) printf("\n%s\n(Above lines saved in file %s)\n",buf,headname) FLUSH; ELSE #endif #ifdef TERSE printf("\n%s\n(Header in %s)\n",buf,headname) FLUSH; #endif if (incl_body) { interp(buf, (sizeof buf), getval("YOUSAID",YOUSAID)); fprintf(tmpfp,"%s\n",buf); #ifdef ASYNC_PARSE parse_maybe(art); #endif fseek(artfp,(long)htype[PAST_HEADER].ht_minpos,0); while (fgets(buf,LBUFLEN,artfp) != Nullch) { fprintf(tmpfp,"%s%s",indstr,buf); } fprintf(tmpfp,"\n"); } fclose(tmpfp); interp(cmd_buf, (sizeof cmd_buf), maildoer); invoke(cmd_buf,origdir); UNLINK(headname); /* kill the header file */ no_reply: free(maildoer); } void followup() { bool incl_body = (*buf == 'F'); if (artopen(art) == Nullfp) { #ifdef VERBOSE IF(verbose) fputs("\nNull articles give me indigestion! :-)\n",stdout) FLUSH; ELSE #endif #ifdef TERSE fputs(nullart,stdout) FLUSH; #endif return; } tmpfp = fopen(headname,"w"); if (tmpfp == Nullfp) { printf(cantcreate,headname) FLUSH; return; } interp(buf, (sizeof buf), getval("NEWSHEADER",NEWSHEADER)); fprintf(tmpfp,"%s",buf); if (incl_body) { #ifdef VERBOSE if (verbose) fputs("\n\ (Be sure to double-check the attribution against the signature, and\n\ trim the quoted article down as much as possible.)\n\ ",stdout) FLUSH; #endif interp(buf, (sizeof buf), getval("ATTRIBUTION",ATTRIBUTION)); fprintf(tmpfp,"%s\n",buf); #ifdef ASYNC_PARSE parse_maybe(art); #endif fseek(artfp,(long)htype[PAST_HEADER].ht_minpos,0); while (fgets(buf,LBUFLEN,artfp) != Nullch) { fprintf(tmpfp,"%s%s",indstr,buf); } fprintf(tmpfp,"\n"); } fclose(tmpfp); safecpy(cmd_buf,filexp(getval("NEWSPOSTER",NEWSPOSTER)),sizeof cmd_buf); invoke(cmd_buf,origdir); UNLINK(headname); } void invoke(cmd,dir) char *cmd,*dir; { if (chdir(dir)) { printf(nocd,dir) FLUSH; return; } #ifdef VERBOSE IF(verbose) printf("\n(leaving cbreak mode; cwd=%s)\nInvoking command: %s\n\n", dir,cmd) FLUSH; ELSE #endif #ifdef TERSE printf("\n(-cbreak; cwd=%s)\nInvoking: %s\n\n",dir,cmd) FLUSH; #endif resetty(); /* make terminal well-behaved */ doshell(sh,cmd); /* do the command */ noecho(); /* set no echo */ crmode(); /* and cbreak mode */ #ifdef VERBOSE IF(verbose) fputs("\n(re-entering cbreak mode)\n",stdout) FLUSH; ELSE #endif #ifdef TERSE fputs("\n(+cbreak)\n",stdout) FLUSH; #endif if (chdir(spool) || chdir(ngdir)) { printf(nocd,ngdir) FLUSH; sig_catcher(0); } } !STUFFY!FUNK! echo Extracting sw.c cat >sw.c <<'!STUFFY!FUNK!' /* $Header: sw.c,v 4.3 85/05/01 11:50:54 lwall Exp $ * * $Log: sw.c,v $ * Revision 4.3 85/05/01 11:50:54 lwall * Baseline for release with 4.3bsd. * */ #include "EXTERN.h" #include "common.h" #include "util.h" #include "head.h" #include "only.h" #include "term.h" #include "ng.h" #include "intrp.h" #include "INTERN.h" #include "sw.h" void sw_init(argc,argv,tcbufptr) int argc; char *argv[]; char **tcbufptr; { register int i; interp(*tcbufptr,1024,GLOBINIT); sw_file(tcbufptr,FALSE); safecpy(*tcbufptr,getenv("RNINIT"),1024); if (**tcbufptr) { if (**tcbufptr == '/') { sw_file(tcbufptr,TRUE); } else sw_list(*tcbufptr); } for (i = 1; i < argc; i++) decode_switch(argv[i]); } void sw_file(tcbufptr,bleat) char **tcbufptr; bool bleat; { int initfd = open(*tcbufptr,0); if (initfd >= 0) { fstat(initfd,&filestat); if (filestat.st_size > 1024) *tcbufptr = saferealloc(*tcbufptr,(MEM_SIZE)filestat.st_size); if (filestat.st_size) { read(initfd,*tcbufptr,(int)filestat.st_size); (*tcbufptr)[filestat.st_size-1] = '\0'; /* wipe out last newline */ sw_list(*tcbufptr); } else **tcbufptr = '\0'; close(initfd); } else { if (bleat) printf(cantopen,*tcbufptr) FLUSH; **tcbufptr = '\0'; } } /* decode a list of space separated switches */ void sw_list(swlist) char *swlist; { char *tmplist = safemalloc((MEM_SIZE) strlen(swlist) + 2); /* semi-automatic string */ register char *p, inquote = 0; strcpy(tmplist,swlist); for (p=tmplist; isspace(*p); p++) ; /* skip any initial spaces */ while (*p) { /* "String, or nothing" */ if (!inquote && isspace(*p)) { /* word delimiter? */ *p++ = '\0'; /* chop here */ while (isspace(*p)) /* these will be ignored later */ p++; } else if (inquote == *p) { strcpy(p,p+1); /* delete trailing quote */ inquote = 0; /* no longer quoting */ } else if (!inquote && *p == '"' || *p == '\'') { /* OK, I know when I am not wanted */ inquote = *p; /* remember single or double */ strcpy(p,p+1); /* delete the quote */ } /* (crude, but effective) */ else if (*p == '\\') { /* quoted something? */ if (p[1] == '\n') /* newline? */ strcpy(p,p+2); /* "I didn't see anything" */ else { strcpy(p,p+1); /* delete the backwhack */ p++; /* leave the whatever alone */ } } else p++; /* normal char, leave it alone */ } *++p = '\0'; /* put an extra null on the end */ if (inquote) printf("Unmatched %c in switch\n",inquote) FLUSH; for (p = tmplist; *p; /* p += strlen(p)+1 */ ) { decode_switch(p); while (*p++) ; /* point at null + 1 */ } free(tmplist); /* this oughta be in Ada */ } /* decode a single switch */ void decode_switch(s) register char *s; { while (isspace(*s)) /* ignore leading spaces */ s++; #ifdef DEBUGGING if (debug) printf("Switch: %s\n",s) FLUSH; #endif if (*s != '-' && *s != '+') { /* newsgroup pattern */ setngtodo(s); } else { /* normal switch */ bool upordown = *s == '-' ? TRUE : FALSE; char tmpbuf[LBUFLEN]; s++; switch (*s) { #ifdef TERMMOD case '=': { char *beg = s+1; while (*s && *s != '-' && *s != '+') s++; cpytill(tmpbuf,beg,*s); if (upordown ? strEQ(getenv("TERM"),tmpbuf) : strNE(getenv("TERM"),tmpbuf) ) { decode_switch(s); } break; } #endif #ifdef BAUDMOD case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': if (upordown ? (just_a_sec*10 <= atoi(s)) : (just_a_sec*10 >= atoi(s)) ) { while (isdigit(*s)) s++; decode_switch(s); } break; #endif case '/': #ifdef SETENV setenv("SAVEDIR", upordown ? "%p/%c" : "%p" ); setenv("SAVENAME", upordown ? "%a" : "%^C"); #else notincl("-/"); #endif break; case 'c': checkflag = upordown; break; case 'C': s++; if (*s == '=') s++; docheckwhen = atoi(s); break; case 'd': { s++; if (*s == '=') s++; if (cwd) { chdir(cwd); free(cwd); } cwd = savestr(s); break; } #ifdef DEBUGGING case 'D': s++; if (*s == '=') s++; if (*s) if (upordown) debug |= atoi(s); else debug &= ~atoi(s); else if (upordown) debug |= 1; else debug = 0; break; #endif case 'e': erase_screen = upordown; break; case 'E': #ifdef SETENV s++; if (*s == '=') s++; strcpy(tmpbuf,s); s = index(tmpbuf,'='); if (s) { *s++ = '\0'; setenv(tmpbuf,s); } else setenv(tmpbuf,nullstr); #else notincl("-E"); #endif break; case 'F': s++; indstr = savestr(s); break; #ifdef INNERSEARCH case 'g': gline = atoi(s+1)-1; break; #endif case 'H': case 'h': { register int len, i; char *t; int flag = (*s == 'h' ? HT_HIDE : HT_MAGIC); s++; len = strlen(s); for (t=s; *t; t++) if (isupper(*t)) *t = tolower(*t); for (i=HEAD_FIRST; iinews.c.2.pat <<'!STUFFY!FUNK!' *** inews.old.c Tue Apr 30 14:34:19 1985 --- inews.c Tue Apr 30 14:34:33 1985 *************** *** 416,421 /* * Link ARTICLE into dir for ngname and update active file. */ localize(ngname) char *ngname; { --- 416,424 ----- /* * Link ARTICLE into dir for ngname and update active file. */ + #ifdef DOXREFS + long + #endif localize(ngname) char *ngname; { *************** *** 453,458 mknewsg(cp, ngname); sprintf(bfr, "%s/%ld", cp, ngsize+1); #ifdef VMS if ((f2 = creat(bfr, 0666)) >=0 ) { f1 = open(article, 0); --- 456,466 ----- mknewsg(cp, ngname); sprintf(bfr, "%s/%ld", cp, ngsize+1); + #ifdef LINKART + if (mylink(ARTICLE, bfr) == 0) break; + /* on first file inits ARTICLE, on subsequent */ + /* files "links" to first article */ + #else !LINKART #ifdef VMS if ((f2 = creat(bfr, 0666)) >=0 ) { f1 = open(article, 0); *************** *** 468,473 if (link(ARTICLE, bfr) == 0) break; #endif !VMS e = errno; /* keep log from clobbering it */ logerr("Cannot install article as %s", bfr); if (e != EEXIST) { --- 476,482 ----- if (link(ARTICLE, bfr) == 0) break; #endif !VMS + #endif !LINKART e = errno; /* keep log from clobbering it */ logerr("Cannot install article as %s", bfr); if (e != EEXIST) { *************** *** 494,499 strcpy(firstbufname, bfr); sprintf(bfr, "%s/%ld ", ngname, ngsize+1); addhist(bfr); return TRUE; } --- 503,509 ----- strcpy(firstbufname, bfr); sprintf(bfr, "%s/%ld ", ngname, ngsize+1); addhist(bfr); + #ifndef DOXREFS return TRUE; #else DOXREFS return ngsize+1; *************** *** 495,500 sprintf(bfr, "%s/%ld ", ngname, ngsize+1); addhist(bfr); return TRUE; } /* --- 505,513 ----- addhist(bfr); #ifndef DOXREFS return TRUE; + #else DOXREFS + return ngsize+1; + #endif DOXREFS } /* *************** *** 507,512 char c; struct srec srec; /* struct for sys file lookup */ int is_invalid = FALSE; /* Fill up the rest of header. */ if (mode != PROC) { --- 520,529 ----- char c; struct srec srec; /* struct for sys file lookup */ int is_invalid = FALSE; + #ifdef DOXREFS + register char *nextxref = header.xref; + int numxrefs = 0; + #endif DOXREFS /* Fill up the rest of header. */ if (mode != PROC) { *************** *** 527,532 if (!is_ctl && mode != CREATENG) is_invalid = ngfcheck(mode == PROC); /* Write article to temp file. */ tfp = xfopen(mktemp(ARTICLE), "w"); if ( (c=getc(infp)) == ' ' || c == '\t' ) { --- 544,556 ----- if (!is_ctl && mode != CREATENG) is_invalid = ngfcheck(mode == PROC); + #ifdef LINKART + *ARTICLE = '\0'; /* tell mylink() to snarf the name */ + #else !LINKART + #ifdef DOXREFS + /* Open temp file for article, but link before writing */ + tfp = xfopen(mktemp(ARTICLE), "w"); + #else DOXREFS /* Write article to temp file. */ tfp = xfopen(mktemp(ARTICLE), "w"); if ( (c=getc(infp)) == ' ' || c == '\t' ) { *************** *** 545,550 putc('\n',tfp); fclose(tfp); fclose(infp); if (is_invalid) { logerr("No valid newsgroups found, moved to junk"); --- 569,576 ----- putc('\n',tfp); fclose(tfp); fclose(infp); + #endif DOXREFS + #endif LINKART if (is_invalid) { logerr("No valid newsgroups found, moved to junk"); *************** *** 550,555 logerr("No valid newsgroups found, moved to junk"); if (localize("junk")) savehist(histline); xxit(1); } --- 576,582 ----- logerr("No valid newsgroups found, moved to junk"); if (localize("junk")) savehist(histline); + #ifndef DOXREFS xxit(1); #endif } *************** *** 551,556 if (localize("junk")) savehist(histline); xxit(1); } if (time((time_t)0) > (cgtdate(header.subdate) + DFLTEXP) ){ --- 578,584 ----- savehist(histline); #ifndef DOXREFS xxit(1); + #endif } #ifdef DOXREFS else *************** *** 552,558 savehist(histline); xxit(1); } ! if (time((time_t)0) > (cgtdate(header.subdate) + DFLTEXP) ){ logerr("Article too old, moved to junk"); if (localize("junk")) --- 580,588 ----- xxit(1); #endif } ! #ifdef DOXREFS ! else ! #endif if (time((time_t)0) > (cgtdate(header.subdate) + DFLTEXP) ){ logerr("Article too old, moved to junk"); if (localize("junk")) *************** *** 557,562 logerr("Article too old, moved to junk"); if (localize("junk")) savehist(histline); xxit(1); } --- 587,593 ----- logerr("Article too old, moved to junk"); if (localize("junk")) savehist(histline); + #ifndef DOXREFS xxit(1); #endif } *************** *** 558,563 if (localize("junk")) savehist(histline); xxit(1); } if (is_ctl) { --- 589,595 ----- savehist(histline); #ifndef DOXREFS xxit(1); + #endif } #ifdef DOXREFS else *************** *** 559,565 savehist(histline); xxit(1); } ! if (is_ctl) { control(&header); localize("control"); --- 591,599 ----- xxit(1); #endif } ! #ifdef DOXREFS ! else ! #endif if (is_ctl) { #ifndef DOXREFS control(&header); *************** *** 561,566 } if (is_ctl) { control(&header); localize("control"); } else { --- 595,601 ----- else #endif if (is_ctl) { + #ifndef DOXREFS control(&header); #endif localize("control"); *************** *** 562,567 if (is_ctl) { control(&header); localize("control"); } else { if (s_find(&srec, FULLSYSNAME) == FALSE) --- 597,603 ----- if (is_ctl) { #ifndef DOXREFS control(&header); + #endif localize("control"); } else { if (s_find(&srec, FULLSYSNAME) == FALSE) *************** *** 566,571 } else { if (s_find(&srec, FULLSYSNAME) == FALSE) xerror("Cannot find my name '%s' in %s", FULLSYSNAME, SUBFILE); for (ptr = nbuf; *ptr;) { if (ngmatch(ptr, srec.s_nbuf) || index(ptr,'.') == NULL) localize(ptr); --- 602,611 ----- } else { if (s_find(&srec, FULLSYSNAME) == FALSE) xerror("Cannot find my name '%s' in %s", FULLSYSNAME, SUBFILE); + #ifdef DOXREFS + sprintf(nextxref,"%s ",FULLSYSNAME); + nextxref += strlen(nextxref); + #endif for (ptr = nbuf; *ptr;) { #ifndef DOXREFS if (ngmatch(ptr, srec.s_nbuf) || index(ptr,'.') == NULL) *************** *** 567,572 if (s_find(&srec, FULLSYSNAME) == FALSE) xerror("Cannot find my name '%s' in %s", FULLSYSNAME, SUBFILE); for (ptr = nbuf; *ptr;) { if (ngmatch(ptr, srec.s_nbuf) || index(ptr,'.') == NULL) localize(ptr); while (*ptr++) --- 607,613 ----- nextxref += strlen(nextxref); #endif for (ptr = nbuf; *ptr;) { + #ifndef DOXREFS if (ngmatch(ptr, srec.s_nbuf) || index(ptr,'.') == NULL) localize(ptr); #else DOXREFS *************** *** 569,574 for (ptr = nbuf; *ptr;) { if (ngmatch(ptr, srec.s_nbuf) || index(ptr,'.') == NULL) localize(ptr); while (*ptr++) ; } --- 610,624 ----- #ifndef DOXREFS if (ngmatch(ptr, srec.s_nbuf) || index(ptr,'.') == NULL) localize(ptr); + #else DOXREFS + if (ngmatch(ptr, srec.s_nbuf) || + index(ptr,'.') == NULL) { + sprintf(nextxref,"%s:%ld ",ptr,localize(ptr)); + numxrefs++; + while (*nextxref) + nextxref++; + } + #endif DOXREFS while (*ptr++) ; } *************** *** 577,582 localize("junk"); } } broadcast(); savehist(histline); --- 627,638 ----- localize("junk"); } } + #ifdef DOXREFS + if (numxrefs >= 2) + *(nextxref-1) = '\0'; /* wipe out the last space */ + else + header.xref[0] = '\0'; /* wipe out the whole thing */ + #endif #ifdef LINKART tfp = xfopen(ARTICLE,"w"); /* open 1st article localized */ *************** *** 578,583 } } broadcast(); savehist(histline); xxit(0); --- 634,669 ----- header.xref[0] = '\0'; /* wipe out the whole thing */ #endif + #ifdef LINKART + tfp = xfopen(ARTICLE,"w"); /* open 1st article localized */ + #endif + + #if defined(LINKART) || defined(DOXREFS) + /* Now that xref is constructed, write article to temp file. */ + /* (We ought to detect no room at this point and clean up.) */ + if ( (c=getc(infp)) == ' ' || c == '\t' ) { + header.intnumlines++; + sprintf(header.numlines,"%d",header.intnumlines); + } + lhwrite(&header, tfp); + /* Kludge to get around article truncation problem */ + if (c == ' ' || c == '\t' ) + putc('\n', tfp); + putc(c,tfp); + while (fgets(bfr, BUFLEN, infp) != NULL) + fputs(bfr, tfp); + + if (bfr[strlen(bfr)-1] != '\n') + putc('\n',tfp); + fclose(tfp); + fclose(infp); + #endif LINKART || DOXREFS + + #ifdef DOXREFS + if (is_ctl) /* moved here cuz checkgroups uses ARTICLE! */ + control(&header); + #endif + broadcast(); savehist(histline); xxit(0); *************** *** 853,855 } return(NULL); } --- 939,963 ----- } return(NULL); } + + #ifdef LINKART + mylink(tmpart,linkfrom) + char *tmpart, *linkfrom; + { + struct stat statbuf; + + if (stat(linkfrom,&statbuf)==0) + return -1; + if (!*tmpart) /* first article? */ + strcpy(tmpart,linkfrom); /* just remember name */ + else { + FILE *linkfp = fopen(linkfrom,"w"); + + if (!linkfp) + return -1; + fprintf(linkfp,"%s\n",tmpart); /* do "symbolic link" */ + fclose(linkfp); + } + return 0; + } + #endif LINKART !STUFFY!FUNK! echo Extracting help.c cat >help.c <<'!STUFFY!FUNK!' /* $Header: help.c,v 4.3 85/05/01 11:38:59 lwall Exp $ * * $Log: help.c,v $ * Revision 4.3 85/05/01 11:38:59 lwall * Baseline for release with 4.3bsd. * */ #include "EXTERN.h" #include "common.h" #include "rn.h" #include "term.h" #include "INTERN.h" #include "help.h" void help_init() { ; } int help_page() { int cmd; #ifdef PAGERHELP doshell(sh,filexp(PAGERHELP)); #else page_init(); if ((cmd = print_lines("\ Paging commands:\n\ ",STANDOUT)) || (cmd = print_lines("\n\ SP Display the next page.\n\ x Display the next page decrypted (rot13).\n\ d Display half a page more.\n\ CR Display one more line.\n\ ^R,v,^X Restart the current article (v=verbose header, ^X=rot13).\n\ ",NOMARKING)) || (cmd = print_lines("\ ^B Back up one page.\n\ ^L,X Refresh the screen (X=rot13).\n\ g pat Go to (search forward within article for) pattern.\n\ G Search again for current pattern within article.\n\ ^G Search for next line beginning with \"Subject:\".\n\ TAB Search for next line beginning with a different character.\n\ q Quit the pager, go to end of article. Leave article read or unread.\n\ j Junk this article (mark it read). Goes to end of article.\n\ \n\ ",NOMARKING)) || (cmd = print_lines("\ The following commands skip the rest of the current article, then behave\n\ just as if typed to the 'What next?' prompt at the end of the article:\n\ ",STANDOUT)) || (cmd = print_lines("\n\ n Scan forward for next unread article.\n\ N Go to next article.\n\ ^N Scan forward for next unread article with same title.\n\ p,P,^P Same as n,N,^N, only going backwards.\n\ - Go to previously displayed article.\n\ \n\ ",NOMARKING)) || (cmd = print_lines("\ The following commands also take you to the end of the article.\n\ Type h at end of article for a description of these commands:\n\ ",STANDOUT)) || (cmd = print_lines("\ # $ & / = ? c C f F k K ^K m M number r R ^R s S u v w W Y ^ |\n\ \n\ (To return to the middle of the article after one of these commands, type ^L.)\n\ ",NOMARKING)) ) return cmd; #endif return 0; } int help_art() { int cmd; #ifdef ARTHELP doshell(sh,filexp(ARTHELP)); #else page_init(); if ((cmd = print_lines("\ Article Selection commands:\n\ ",STANDOUT)) || (cmd = print_lines("\n\ n,SP Scan forward for next unread article.\n\ N Go to next article.\n\ ^N Scan forward for next unread article with same subject.\n\ p,P,^P Same as n,N,^N, only going backwards.\n\ - Go to previously displayed article.\n\ ",NOMARKING)) || (cmd = print_lines("\ number Go to specified article.\n\ range{,range} command{:command}\n\ Apply one or more commands to one or more ranges of articles.\n\ Ranges are of the form: number | number-number. You may use . for\n\ the current article, and $ for the last article.\n\ Valid commands are: j, m, M, s, S, and !.\n\ ",NOMARKING)) || (cmd = print_lines("\ /pattern/modifiers\n\ Scan forward for article containing pattern in the subject line.\n\ (Use ?pat? to scan backwards; append h to scan headers, a to scan\n\ entire articles, r to scan read articles, c to make case sensitive.\n\ /pattern/modifiers:command{:command}\n\ Apply one or more commands to the set of articles matching pattern.\n\ Use a K modifier to save entire command to the KILL file for this\n\ newsgroup. Commands m and M, if first, imply an r modifier.\n\ Valid commands are: j, m, M, s, S, and !.\n\ ",NOMARKING)) || (cmd = print_lines("\ f,F Submit a followup article (F = include this article).\n\ r,R Reply through net mail (R = include this article).\n\ s ... Save to file or pipe via sh.\n\ S ... Save via preferred shell.\n\ w,W Like s and S but save without the header.\n\ | ... Same as s|...\n\ C Cancel this article, if yours.\n\ ",NOMARKING)) || (cmd = print_lines("\ ^R,v Restart article (v=verbose).\n\ ^X Restart article, rot13 mode.\n\ c Catch up (mark all articles as read).\n\ ^B Back up one page.\n\ ^L Refresh the screen. You can get back to the pager with this.\n\ X Refresh screen in rot13 mode.\n\ ",NOMARKING)) || (cmd = print_lines("\ ^ Go to first unread article. Disables subject search mode.\n\ $ Go to end of newsgroup. Disables subject search mode.\n\ ",NOMARKING)) || (cmd = print_lines("# Print last article number.\n\ & Print current values of command-line switches.\n\ &switch {switch}\n\ Set or unset more switches.\n\ && Print current macro definitions.\n\ &&def Define a new macro.\n\ j Junk this article (mark it read). Stays at end of article.\n\ m Mark article as still unread.\n\ M Mark article as still unread upon exiting newsgroup or Y command.\n\ ",NOMARKING)) || (cmd = print_lines("\ Y Yank back articles marked temporarily read via M.\n\ k Mark current SUBJECT as read.\n\ K Mark current SUBJECT as read, and save command in KILL file.\n\ = List subjects of unread articles.\n\ u Unsubscribe to this newsgroup.\n\ ^K Edit local KILL file (the one for this newsgroup).\n\ q Quit this newsgroup for now.\n\ Q Quit newsgroup, staying at current newsgroup.\n\ ",NOMARKING)) ) return cmd; #endif return 0; } int help_ng() { int cmd; #ifdef NGHELP doshell(sh,filexp(NGHELP)); #else page_init(); if (cmd = print_lines("\ Newsgroup Selection commands:\n\ ",STANDOUT) ) return cmd; if (ng != nextrcline) { if (cmd = print_lines("\ \n\ y,SP Do this newsgroup now.\n\ .cmd Do this newsgroup, executing cmd as first command.\n\ = Equivalent to .=.\n\ u Unsubscribe from this newsgroup.\n\ c Catch up (mark this newsgroup all read).\n\ ",NOMARKING) ) return cmd; } if ((cmd = print_lines("\ \n\ n Go to the next newsgroup with unread news.\n\ N Go to the next newsgroup.\n\ p Go to the previous newsgroup with unread news.\n\ P Go to the previous newsgroup.\n\ ",NOMARKING)) || (cmd = print_lines("\ - Go to the previously displayed newsgroup.\n\ 1 Go to the first newsgroup.\n\ ^ Go to the first newsgroup with unread news.\n\ $ Go to the last newsgroup.\n\ ",NOMARKING)) || (cmd = print_lines("\ g name Go to the named newsgroup. Subscribe to new newsgroups this way too.\n\ /pat Search forward for newsgroup matching pattern.\n\ ?pat Search backward for newsgroup matching pattern.\n\ (Use * and ? style patterns. Append r to include read newsgroups.)\n\ ",NOMARKING)) || (cmd = print_lines("\ l pat List unsubscribed newsgroups containing pattern.\n\ m name Move named newsgroup elsewhere (no name moves current newsgroup).\n\ o pat Only display newsgroups matching pattern. Omit pat to unrestrict.\n\ a pat Like o, but also scans for unsubscribed newsgroups matching pattern.\n\ L List current .newsrc.\n\ ",NOMARKING)) || (cmd = print_lines("\ & Print current command-line switch settings.\n\ &switch {switch}\n\ Set (or unset) more command-line switches.\n\ && Print current macro definitions.\n\ &&def Define a new macro.\n\ !cmd Shell escape.\n\ ",NOMARKING)) || (cmd = print_lines("\ q Quit rn.\n\ ^K Edit the global KILL file. Use commands like /pattern/j to suppress\n\ pattern in every newsgroup.\n\ v Print version.\n\ ",NOMARKING)) ) return cmd; #endif #ifdef PUSHBACK if (cmd = get_anything()) return cmd; show_macros(); #endif return 0; } #ifdef ESCSUBS int help_subs() { int cmd; #ifdef SUBSHELP doshell(sh,filexp(SUBSHELP)); #else page_init(); if ((cmd = print_lines("\ Valid substitutions are:\n\ ",STANDOUT)) || (cmd = print_lines("\ \n\ a Current article number\n\ A Full name of current article (%P/%c/%a)\n\ b Destination of last save command, often a mailbox\n\ B Bytes to ignore at beginning of last saved article\n\ ",NOMARKING)) || (cmd = print_lines("\ c Current newsgroup, directory form\n\ C Current newsgroup, dot form\n\ d Full name of newsgroup directory (%P/%c)\n\ D Distribution line from current article\ ",NOMARKING)) || (cmd = print_lines("\ f Who the current article is from\n\ F Newsgroups to followup to (from Newsgroups and Followup-To)\n\ h (This help message)\n\ H Host name (yours)\n\ i Message-I.D. line from current article, with <>\n\ I Reference indicator mark (see -F switch)\n\ ",NOMARKING)) || (cmd = print_lines("\ l News administrator's login name, if any\n\ L Login name (yours)\n\ m Current mode, first letter of (init,newsgroup,article,pager,misc)\n\ M Number of article marked with M\n\ n Newsgroups from current article\n\ N Full name (yours)\n\ ",NOMARKING)) || (cmd = print_lines("\ o Organization (yours)\n\ O Original working directory (where you ran rn from)\n\ p Your private news directory (from -d)\n\ P Public news spool directory\n\ ",NOMARKING)) || (cmd = print_lines("\ r Last reference (parent article id)\n\ R References list for followup article\n\ s Subject, with all Re's and (nf)'s stripped off\n\ S Subject, with one Re stripped off\ ",NOMARKING)) || (cmd = print_lines("\ t New To line derived from From and Reply-To (Internet format)\n\ T New To line derived from Path\n\ u Number of unread articles\n\ U Number of unread articles not counting current article\n\ x News library directory\n\ X Rn library directory\n\ z Length of current article in bytes\n\ ",NOMARKING)) || (cmd = print_lines("\ ~ Your home directory\n\ . Directory containing . files\n\ $ Current process number\n\ / Last search string\n\ ESC Run preceding command through % interpretation\n\ ",NOMARKING)) ) return cmd; #endif return 0; } #endif !STUFFY!FUNK! echo Extracting artsrch.c cat >artsrch.c <<'!STUFFY!FUNK!' /* $Header: artsrch.c,v 4.3 85/05/01 11:35:47 lwall Exp $ * * $Log: artsrch.c,v $ * Revision 4.3 85/05/01 11:35:47 lwall * Baseline for release with 4.3bsd. * */ #include "EXTERN.h" #include "common.h" #include "search.h" #include "term.h" #include "util.h" #include "intrp.h" #include "bits.h" #include "kfile.h" #include "head.h" #include "final.h" #include "cheat.h" #include "ng.h" #include "artio.h" #include "INTERN.h" #include "artsrch.h" void artsrch_init() { #ifdef ARTSEARCH #ifdef ZEROGLOB init_compex(&sub_compex); init_compex(&art_compex); #endif #endif } /* search for an article containing some pattern */ #ifdef ARTSEARCH int art_search(patbuf,patbufsiz,get_cmd) char *patbuf; /* if patbuf != buf, get_cmd must */ int patbufsiz; int get_cmd; /* be set to FALSE!!! */ { char *pattern; /* unparsed pattern */ register char cmdchr = *patbuf; /* what kind of search? */ register char *s; bool backward = cmdchr == '?' || cmdchr == Ctl('p'); /* direction of search */ COMPEX *compex; /* which compiled expression */ char *cmdlst = Nullch; /* list of commands to do */ int normal_return = SRCH_NOTFOUND; /* assume no commands */ bool saltaway = FALSE; /* store in KILL file? */ char howmuch; /* search just the subjects */ bool doread; /* search read articles? */ bool foldcase = TRUE; /* fold upper and lower case? */ int_count = 0; if (cmdchr == '/' || cmdchr == '?') { /* normal search? */ if (get_cmd && buf == patbuf) if (!finish_command(FALSE)) /* get rest of command */ return SRCH_ABORT; compex = &art_compex; if (patbuf[1]) { howmuch = 0; doread = FALSE; } else { howmuch = art_howmuch; doread = art_doread; } s = cpytill(buf,patbuf+1,cmdchr);/* ok to cpy buf+1 to buf */ pattern = buf; if (*pattern) { if (*lastpat) free(lastpat); lastpat = savestr(pattern); } if (*s) { /* modifiers or commands? */ for (s++; *s && index("Kharc",*s); s++) { if (*s == 'h') /* scan header */ howmuch = 1; else if (*s == 'a') /* scan article */ howmuch = 2; else if (*s == 'r') /* scan read articles */ doread = TRUE; else if (*s == 'K') /* put into KILL file */ saltaway = TRUE; else if (*s == 'c') /* make search case sensitive */ foldcase = FALSE; } } while (isspace(*s) || *s == ':') s++; if (*s) { if (*s == 'm' || *s == 'M') doread = TRUE; if (*s == 'k') /* grandfather clause */ *s = 'j'; cmdlst = savestr(s); normal_return = SRCH_DONE; } art_howmuch = howmuch; art_doread = doread; if (srchahead) srchahead = -1; } else { register char *h; howmuch = 0; /* just search subjects */ doread = (cmdchr == Ctl('p')); if (cmdchr == Ctl('n')) normal_return = SRCH_SUBJDONE; compex = &sub_compex; pattern = patbuf+1; strcpy(pattern,": *"); h = pattern + strlen(pattern); interp(h,patbufsiz - (h-patbuf),"%s"); /* fetch current subject */ if (cmdchr == 'K') { saltaway = TRUE; cmdchr = 'k'; } if (cmdchr == 'k') { normal_return = SRCH_DONE; cmdlst = savestr("j"); mark_as_read(art); /* this article has this subject */ if (!*h) { #ifdef VERBOSE IF(verbose) fputs("\nCannot delete null subject.\n",stdout) FLUSH; ELSE #endif #ifdef TERSE fputs("\nNull subject.\n",stdout) FLUSH; #endif return SRCH_ABORT; } #ifdef VERBOSE else if (verbose) printf("\nMarking subject \"%s\" as read.\n",h) FLUSH; #endif } else if (!srchahead) srchahead = -1; h[24] = '\0'; /* compensate for notesfiles */ while (*h) { if (index("/\\[.^*$'\"",*h) != Nullch) *h++ = '.'; else h++; } #ifdef DEBUGGING if (debug) { printf("\npattern = %s\n",pattern) FLUSH; } #endif } if ((s = compile(compex,pattern,TRUE,foldcase)) != Nullch) { /* compile regular expression */ printf("\n%s\n",s) FLUSH; return SRCH_ABORT; } #ifdef KILLFILES if (saltaway) { char saltbuf[LBUFLEN]; s = saltbuf; sprintf(s,"/%s/",pattern); s += strlen(s); if (doread) *s++ = 'r'; if (howmuch==1) *s++ = 'h'; else if (howmuch==2) *s++ = 'a'; *s++ = ':'; if (!cmdlst) cmdlst = savestr("j"); safecpy(s,cmdlst,LBUFLEN-(s-saltbuf)); kf_append(saltbuf); } #endif if (cmdlst && index(cmdlst,'=')) normal_return = SRCH_ERROR; /* listing subjects is an error? */ if (get_cmd) { fputs("\nSearching...\n",stdout) FLUSH; /* give them something to read */ } if (backward) { if (cmdlst && art < lastart) art++; /* include current article */ if (doread) check_first(absfirst); } else { if (art > lastart) art = (doread ? absfirst : firstart) - 1; else if (cmdlst && art > absfirst) art--; /* include current article */ check_first(art); } if (srchahead > 0) { if (!backward) art = srchahead - 1; srchahead = -1; } assert(!cmdlst || *cmdlst); for (;;) { if (int_count) { int_count = 0; if (cmdlst) free(cmdlst); return SRCH_INTR; } if (backward ? (--art < absfirst || (!doread && art < firstart)) : (++art > lastart) ) { /* out of articles? */ if (cmdlst) free(cmdlst); return normal_return; } /*NOSTRICT*/ if (doread || !was_read(art)) { if (wanted(compex,art,howmuch)) { /* does the shoe fit? */ if (cmdlst) { if (perform(cmdlst,TRUE)) { if (cmdlst) free(cmdlst); return SRCH_INTR; } } else { if (cmdlst) free(cmdlst); return SRCH_FOUND; } } else if (!cmdlst && ! (art%50)) { printf("...%ld",(long)art); fflush(stdout); } } } } /* determine if article fits pattern */ /* returns TRUE if it exists and fits pattern, FALSE otherwise */ bool wanted(compex, artnum, scope) COMPEX *compex; ART_NUM artnum; char scope; { if (!scope) { char subj_buf[266]; strcpy(subj_buf, "Subject: "); strncpy(subj_buf+9,fetchsubj(artnum,FALSE,FALSE),256); #ifdef DEBUGGING if (debug & DEB_SEARCH_AHEAD) printf("%s\n",subj_buf) FLUSH; #endif return execute(compex,subj_buf) != Nullch; } #ifdef CACHESUBJ else fetchsubj(artnum,FALSE,FALSE);/* might as well get subject handy */ #endif if (artopen(artnum) == Nullfp) /* ensure that article is open */ return FALSE; /* if not, return NO MATCH */ scope--; while (fgets(buf,LBUFLEN,artfp) != Nullch) { /* for each line of article */ if (!scope && index(buf,':') == Nullch && *buf != ' ' && *buf != '\t') /* if headers only and out of header */ return FALSE; /* say no go */ if (execute(compex,buf) != Nullch) { /* does pattern matcher match? */ return TRUE; /* say Eureka */ } } return FALSE; /* out of article, so no match */ } #endif !STUFFY!FUNK! echo Extracting inews.c.1.pat cat >inews.c.1.pat <<'!STUFFY!FUNK!' *** inews.c.1.std Tue Oct 2 16:09:59 1984 --- inews.c.1 Fri Sep 21 14:50:49 1984 *************** *** 483,488 /* * Link ARTICLE into dir for ngname and update active file. */ localize(ngname) char *ngname; { --- 483,491 ----- /* * Link ARTICLE into dir for ngname and update active file. */ + #ifdef DOXREFS + long + #endif localize(ngname) char *ngname; { *************** *** 515,520 } for (;;) { sprintf(bfr, "%s/%ld", dirname(ngname), ngsize+1); if (link(ARTICLE, bfr) == 0) break; e = errno; /* keep log from clobbering it */ fprintf(stderr, "Cannot install article as %s\n", bfr); --- 518,528 ----- } for (;;) { sprintf(bfr, "%s/%ld", dirname(ngname), ngsize+1); + #ifdef LINKART + if (mylink(ARTICLE, bfr) == 0) break; + /* on first file inits ARTICLE, on subsequent */ + /* files "links" to first article */ + #else if (link(ARTICLE, bfr) == 0) break; #endif e = errno; /* keep log from clobbering it */ *************** *** 516,521 for (;;) { sprintf(bfr, "%s/%ld", dirname(ngname), ngsize+1); if (link(ARTICLE, bfr) == 0) break; e = errno; /* keep log from clobbering it */ fprintf(stderr, "Cannot install article as %s\n", bfr); log("Cannot install article as %s", bfr); --- 524,530 ----- /* files "links" to first article */ #else if (link(ARTICLE, bfr) == 0) break; + #endif e = errno; /* keep log from clobbering it */ fprintf(stderr, "Cannot install article as %s\n", bfr); log("Cannot install article as %s", bfr); *************** *** 542,547 strcpy(firstbufname, bfr); sprintf(bfr, "%s/%ld ", ngname, ngsize+1); addhist(bfr); return TRUE; } --- 551,557 ----- strcpy(firstbufname, bfr); sprintf(bfr, "%s/%ld ", ngname, ngsize+1); addhist(bfr); + #ifndef DOXREFS return TRUE; #else DOXREFS return ngsize+1; *************** *** 543,548 sprintf(bfr, "%s/%ld ", ngname, ngsize+1); addhist(bfr); return TRUE; } /* --- 553,561 ----- addhist(bfr); #ifndef DOXREFS return TRUE; + #else DOXREFS + return ngsize+1; + #endif DOXREFS } /* *************** *** 553,558 register char *ptr; register FILE *tfp; int badgroup = 0, goodgroup = 0; /* Fill up the rest of header. */ if (mode != PROC) { --- 566,574 ----- register char *ptr; register FILE *tfp; int badgroup = 0, goodgroup = 0; + #ifdef DOXREFS + register char *nextxref = header.xref; + #endif DOXREFS /* Fill up the rest of header. */ if (mode != PROC) { *************** *** 565,570 if (mode==PROC) log("from %s relay %s", header.from, header.relayversion); /* Write article to temp file. */ tfp = xfopen(mktemp(ARTICLE), "w"); lhwrite(&header, tfp); --- 581,593 ----- if (mode==PROC) log("from %s relay %s", header.from, header.relayversion); + #ifdef LINKART + *ARTICLE = '\0'; /* tell mylink() to snarf the name */ + #else !LINKART + #ifdef DOXREFS + /* Open temp file for article, but link before writing */ + tfp = xfopen(mktemp(ARTICLE), "w"); + #else DOXREFS /* Write article to temp file. */ tfp = xfopen(mktemp(ARTICLE), "w"); lhwrite(&header, tfp); *************** *** 577,582 } fclose(tfp); fclose(infp); if (is_ctl) { control(&header); --- 600,607 ----- } fclose(tfp); fclose(infp); + #endif DOXREFS + #endif LINKART if (is_ctl) { control(&header); *************** *** 593,598 } } } else { for (ptr = nbuf; *ptr;) { if (*ptr == '-') { while (*ptr++) --- 618,627 ----- } } } else { + #ifdef DOXREFS + sprintf(nextxref,"%s ",SYSNAME); + nextxref += strlen(nextxref); + #endif for (ptr = nbuf; *ptr;) { if (*ptr == '-') { while (*ptr++) *************** *** 610,615 } else goodgroup++; if (*nbuf) localize(ptr); while (*ptr++) --- 639,645 ----- } else goodgroup++; + #ifndef DOXREFS if (*nbuf) localize(ptr); #else DOXREFS *************** *** 612,617 goodgroup++; if (*nbuf) localize(ptr); while (*ptr++) ; } --- 642,653 ----- #ifndef DOXREFS if (*nbuf) localize(ptr); + #else DOXREFS + if (*nbuf) + sprintf(nextxref,"%s:%ld ",ptr,localize(ptr)); + while (*nextxref) + nextxref++; + #endif DOXREFS while (*ptr++) ; } *************** *** 616,621 ; } } #ifdef NOFORWARD if (*nbuf) --- 652,663 ----- ; } } + #ifdef DOXREFS + if (goodgroup < 2) + header.xref[0] = '\0'; + else + *(nextxref-1) = '\0'; + #endif #ifdef LINKART tfp = xfopen(ARTICLE,"w"); /* open 1st article localized */ *************** *** 617,622 } } #ifdef NOFORWARD if (*nbuf) #endif --- 659,683 ----- *(nextxref-1) = '\0'; #endif + #ifdef LINKART + tfp = xfopen(ARTICLE,"w"); /* open 1st article localized */ + #endif + + #if defined(LINKART) || defined(DOXREFS) + /* Now that xref is constructed, write article to temp file. */ + /* (We ought to detect no room at this point and clean up.) */ + lhwrite(&header, tfp); + while (fgets(bfr, BUFLEN, infp) != NULL) { + /* + if (!strncmp(bfr, "From ", 5)) + putc('>', tfp); + */ + fputs(bfr, tfp); + } + fclose(tfp); + fclose(infp); + #endif LINKART || DOXREFS + #ifdef NOFORWARD if (*nbuf) #endif *************** *** 861,863 mclose(fd); } } --- 922,946 ----- mclose(fd); } } + + #ifdef LINKART + mylink(tmpart,linkfrom) + char *tmpart, *linkfrom; + { + struct stat statbuf; + + if (stat(linkfrom,&statbuf)==0) + return -1; + if (!*tmpart) + strcpy(tmpart,linkfrom); + else { + FILE *linkfp = fopen(linkfrom,"w"); + + if (!linkfp) + return -1; + fprintf(linkfp,"%s\n",tmpart); + fclose(linkfp); + } + return 0; + } + #endif LINKART !STUFFY!FUNK! echo "" echo "End of kit 6 (of 9)" cat /dev/null >kit6isdone config=true for iskit in 1 2 3 4 5 6 7 8 9; do if test -f kit${iskit}isdone; then echo "You have run kit ${iskit}." else echo "You still need to run kit ${iskit}." config=false fi done case $config in true) echo "You have run all your kits. Please read README and then type Configure." chmod 755 Configure ;; esac : I do not append .signature, but someone might mail this. exit