home *** CD-ROM | disk | FTP | other *** search
- /* RFP.C */
- static char sccsid[] = "@(#)rfp.c 1.3 94/01/20 (c)1993 thalerd";
- #include <stdio.h>
- #include <string.h>
- #include <sys/types.h>
- #include <sys/time.h>
- #include "config.h"
- #include "struct.h"
- #include "globals.h"
- #include "rfp.h"
- #include "item.h"
- #include "macro.h"
- #include "driver.h"
- #include "lib.h"
- #include "sum.h"
- #include "xalloc.h"
- #include "arch.h"
- #include "system.h"
- #include "files.h"
- #include "range.h"
- #include "sep.h"
- #include "news.h"
- #include "stats.h" /* for get_config */
-
- extern FILE *ext_fp;
- extern short ext_first,ext_last;
-
- /* Commands available in RFP mode */
- static dispatch_t rfp_cmd[]={
- "cen_sor", censor,
- "scr_ibble", censor,
- "e_nter", enter,
- "pr_eserve", preserve,
- "po_stpone", preserve,
- "hide", preserve,
- "p_ass", preserve,
- "n_ew", preserve,
- "wait", preserve,
- "tree", tree,
- "*freeze", freeze,
- "*thaw", freeze,
- "*forget", freeze,
- "*retire", freeze,
- "*unretire", freeze,
- "r_espond", rfp_respond,
- "ps_eudonym", rfp_respond,
- "*rem_ember", remember,
- "*unfor_get", remember,
- "*kill", do_kill,
- "*f_ind", do_find,
- "*lo_cate", do_find,
- /* "*fix_seen", fixseen, this by itself doesn't work */
- "reply", reply,
- 0, 0
- };
-
- /******************************************************************************/
- /* DISPATCH CONTROL TO APPROPRIATE RFP MODE FUNCTION */
- /******************************************************************************/
- char /* RETURNS: 0 on abort, 1 else */
- rfp_cmd_dispatch(argc,argv) /* ARGUMENTS: */
- int argc; /* Number of arguments */
- char **argv; /* Argument list */
- {
- short a,b,c;
- int i,j;
-
- for (i=0; rfp_cmd[i].name; i++) {
- if (match(argv[0],rfp_cmd[i].name))
- return rfp_cmd[i].func(argc,argv);
- else if (rfp_cmd[i].name[0]=='*' && match(argv[0],rfp_cmd[i].name+1)) {
- char buff[MAX_LINE_LENGTH];
-
- mode = M_OK;
- st_glob.r_first = st_glob.r_last+1;
- sprintf(buff,"%s %d",compress(rfp_cmd[i].name+1),st_glob.i_current);
- for (j=1; j<argc; j++) {
- strcat(buff," ");
- strcat(buff,argv[j]);
- }
- return command(buff,0);
- }
- }
-
- /* Command dispatch */
- if (match(argv[0],"h_eader")) {
- show_header();
- } else if (match(argv[0],"text")) { /* re-read from 0 */
- st_glob.r_first = 0;
- st_glob.r_last = MAX_RESPONSES;
- show_range();
- } else if (match(argv[0],"a_gain")) { /* re-read same range */
- sepinit(IS_ITEM|IS_ALL);
- show_header();
- st_glob.r_first = ext_first;
- st_glob.r_last = ext_last;
- if (st_glob.r_first>0)
- show_nsep(ext_fp); /* nsep between header and responses */
- show_range();
- } else if (match(argv[0],"^")
- || match(argv[0],"fi_rst")) {
- st_glob.r_first = 1;
- st_glob.r_last = MAX_RESPONSES;
- show_range();
- } else if (match(argv[0],".")
- || match(argv[0],"th_is")
- || match(argv[0],"cu_rrent")) {
- st_glob.r_first = st_glob.r_current;
- st_glob.r_last = MAX_RESPONSES;
- show_range();
- } else if (match(argv[0],"$")
- || match(argv[0],"l_ast")) {
- st_glob.r_first = st_glob.r_max;
- st_glob.r_last = MAX_RESPONSES;
- show_range();
- } else if (match(argv[0],"up")
- || match(argv[0],"par_ent")) {
- short a;
-
- if ((a=parent(st_glob.r_current)) < 0)
- printf("No previous response\n");
- else {
- st_glob.r_first = a;
- st_glob.r_last = a;
- show_range();
- }
- } else if (match(argv[0],"chi_ldren")
- || match(argv[0],"do_wn")) {
- short a;
-
- /* Find 1st child */
- if ((a = child(st_glob.r_current)) < 0)
- printf("No children\n");
- else {
- st_glob.r_first = a;
- st_glob.r_last = a;
- show_range();
- }
- } else if (match(argv[0],"sib_ling")
- || match(argv[0],"ri_ght")) {
- short a;
-
- /* Find next sibling */
- if ((a = sibling(st_glob.r_current)) < 0)
- printf("No more siblings\n");
- else {
- st_glob.r_first = a;
- st_glob.r_last = a;
- show_range();
- }
- } else if (match(argv[0],"sync_hronous")) { mode = M_OK; /* KKK */ }
- else if (match(argv[0],"async_hronous")) { mode = M_OK; /* KKK */ }
- else if (match(argv[0],"si_nce")) {
- time_t t;
- short i;
-
- i=0;
- t=since(argc,argv,&i);
- for (i=st_glob.r_max; i>=0; i--) {
- if (!re[i].date) get_resp(ext_fp,&(re[i]),(short)GR_HEADER,i);
- if (re[i].date<t) break;
- }
- st_glob.r_first = i+1;
- st_glob.r_last = MAX_RESPONSES;
- show_range();
- } else if (match(argv[0],"onl_y")) {
- if (argc>2) {
- printf("Bad parameters near \"%s\"\n",argv[2]);
- return 2;
- } else if (argc>1 && sscanf(argv[1],"%hd",&a)==1) {
- st_glob.r_first = a;
- st_glob.r_last = a;
- show_range();
- } else
- wputs("You must specify a comment number\n");
- } else if (argc && sscanf(argv[0],"%hd-%hd",&a,&b)==2) {
- if (b<a) { c=a; a=b; b=c; }
- if (a<0) {
- printf("Response #%d is too small\n",a);
- } else if (b>st_glob.r_max) {
- printf("Response #%d is too big (last %d)\n",a,st_glob.r_max);
- } else {
- st_glob.r_first = a;
- st_glob.r_last = b;
- show_range();
- }
- } else if (argc && (sscanf(argv[0],"%hd",&a)==1
- || !strcmp(argv[0],"-") || !strcmp(argv[0],"+"))) {
- if (!strcmp(argv[0],"-")) a = -1;
- if (!strcmp(argv[0],"+")) a = 1;
- if (argv[0][0]=='+' || argv[0][0]=='-')
- a += st_glob.r_current;
- if (a<0) {
- printf("Response #%d is too small\n",a);
- } else if (a>st_glob.r_max) {
- printf("Response #%d is too big (last %d)\n",a,st_glob.r_max);
- } else {
- st_glob.r_first = a;
- st_glob.r_last = MAX_RESPONSES;
- show_range();
- }
- } else {
- a=misc_cmd_dispatch(argc,argv);
- if (!a) preserve(argc,argv);
- return a;
- }
- return 1;
- }
-
- /******************************************************************************/
- /* ADD A NEW RESPONSE */
- /******************************************************************************/
- int
- add_response(this,text,idx,sum,part,stt,art,mid,uid,login,fullname,resp)
- sumentry_t *this; /* New item summary */
- char **text; /* New item text */
- short idx;
- sumentry_t *sum;
- partentry_t *part;
- status_t *stt;
- long art;
- char *mid;
- uid_t uid;
- char *login;
- char *fullname;
- short resp;
- {
- short item,line,nr;
- char buff2[MAX_LINE_LENGTH];
- FILE *fp;
-
- item = stt->i_current;
- nr = sum[ item-1 ].nr;
- sprintf(buff2, "%s/_%d", conflist[idx].location, item);
-
- /* Begin critical section */
- if (fp=mopen(buff2, O_A|O_NOCREATE)) {
- short n;
-
- /* was: update before open, in case of a link - why? (was wrong) */
- if (!art)
- refresh_sum(item,idx,sum,part,stt);
-
- n = sum[item-1].nr - nr;
- if (n>1) {
- printf("Warning: %d comments slipped in ahead of yours at %d-%d!\n",
- n,nr,sum[item-1].nr-1);
- } else if (n==1) {
- printf("Warning: a comment slipped in ahead of yours at %d!\n",
- sum[item-1].nr-1);
- } else if (!(flags & O_STAY))
- stt->r_last = -1;
-
- re[sum[item-1].nr].offset = ftell(fp);
- fprintf(fp,",R%04X\n,U%d,%s\n,A%s\n,D%lX\n",
- RF_NORMAL,uid,login,fullname,(art)? this->last : time((time_t *)0));
- if (resp)
- fprintf(fp,",P%d\n",resp-1);
- fprintf(fp,",T\n");
- re[sum[item-1].nr].parent = resp;
- re[sum[item-1].nr].textoff = ftell(fp);
- re[sum[item-1].nr].numchars = -1;
- if (art) {
- fprintf(fp,",N%06ld\n",art);
- fprintf(fp,",M%s\n",mid);
- } else {
- for (line=0; line<xsizeof(text); line++) {
- if (text[line][0]==',') fprintf(fp,",,%s\n",text[line]);
- else fprintf(fp,"%s\n", text[line]);
- }
- }
- if (fprintf(fp,",E\n")>=0) {
-
- /* Update seen */
- stt->r_current = stt->r_max = sum[item-1].nr;
- /* if (!(flags & O_METOO) && stt->r_lastseen==sum[item-1].nr) */
- time(&(part[item-1].last));
- if (!(flags & O_METOO)) {
- part[item-1].nr = sum[item-1].nr;
- stt->r_lastseen = stt->r_current+1;
- }
-
- sum[item-1].last = time((time_t *)0);
- sum[item-1].nr++;
- save_sum(sum,(short)(item-1),idx,stt);
-
- } else
- error("writing response","");
- mclose(fp);
-
- }
- /* End critical section */
-
- xfree(text);
- }
-
- /******************************************************************************/
- /* ENTER A RESPONSE INTO THE CURRENT ITEM */
- /******************************************************************************/
- void /* RETURNS: (nothing) */
- do_respond(ps,resp) /* ARGUMENTS: */
- int ps; /* Use a pseudo? */
- short resp; /* Response to prev. response # */
- {
- short nr;
- char buff[MAX_LINE_LENGTH],
- pseudo[MAX_LINE_LENGTH],
- **file;
- unsigned char omode;
- FILE *fp;
- char **config;
-
- /* Check for valid permissions and arguments */
- if (st_glob.c_status & CS_NORESPONSE) {
- printf("You only have read access.\n");
- return;
- }
-
- if (sum[st_glob.i_current-1].flags & IF_FROZEN) {
- wputs("Item is frozen!\n");
- return;
- }
- nr = sum[ st_glob.i_current-1 ].nr;
- if (resp>nr) {
- printf("Highest response # is %d\n",nr-1);
- return;
- }
-
- /* Get pseudo */
- if (ps) {
- printf("What's your handle? ");
- if (!ngets(buff, st_glob.inp))
- return;
- if (strlen(buff))
- strcpy(pseudo,buff);
- else {
- wputs("Response aborted! Returning to current item.\n");
- return;
- }
- } else strcpy(pseudo,st_glob.fullname);
-
- if (nr >= MAX_RESPONSES) {
- wputs("Too many responses on this item!\n");
- return;
- }
-
- #ifdef NEWS
- if (st_glob.c_security & CT_NEWS) {
- char rnh[MAX_LINE_LENGTH];
-
- if (!resp) resp=nr;
-
- if (!(config = get_config(confidx)))
- return;
- sprintf(buff,"%s/%s/%d",NEWSDIR,dot2slash(config[CF_NEWSGROUP]),
- st_glob.i_current);
-
- if (resp>0) {
- if ((fp=mopen(buff,O_R))==NULL) return;
- get_resp(fp,&(re[resp-1]),GR_ALL,resp-1);
- mclose(fp);
- }
-
- make_rnhead(re,resp);
- if (resp>0)
- xfree(re[resp-1].text);
- sprintf(rnh,"%s/.rnhead",home);
- sprintf(buff,"Pnews -h %s",rnh);
- unix_cmd(buff);
- rm(rnh,SL_USER);
- return;
- } else
- #endif
- if (text_loop(1,1)) { /* success */
- omode = mode;
- mode = M_OK;
- if (!(file = grab_file(work,"cf.buffer",0)))
- wputs("can't open cfbuffer\n");
- else if (!xsizeof(file)) {
- wputs("No text in buffer!\n");
- xfree(file);
- } else {
- add_response(&(sum[st_glob.i_current-1]),file,confidx,sum,part,
- &st_glob,0, NULL,uid,login,pseudo,resp);
- }
-
- if (flags & O_STAY)
- mode = omode;
- } else
- wputs("Response aborted! Returning to current item.\n");
-
- /* Delete text buffer */
- sprintf(buff,"%s/cf.buffer",work);
- rm(buff,SL_USER);
- }
-
- /******************************************************************************/
- /* ADD A RESPONSE TO THE CURRENT ITEM */
- /******************************************************************************/
- int /* RETURNS: (nothing) */
- respond(argc,argv) /* ARGUMENTS: */
- int argc; /* Number of arguments */
- char **argv; /* Argument list */
- {
- char buff[MAX_LINE_LENGTH];
- char act[MAX_ITEMS];
- short j,fl;
-
- /* Check for valid permissions and arguments */
- if (st_glob.c_status & CS_NORESPONSE) {
- printf("You only have read access.\n");
- return 1;
- }
-
- rangeinit(&st_glob,act);
- refresh_sum(0,confidx,sum,part,&st_glob);
- st_glob.r_first = -1;
-
- fl = 0;
- if (argc<2) {
- printf("Error, no item specified! (try HELP RANGE)\n");
- } else { /* Process args */
- range(argc,argv,&fl,act,sum,&st_glob,0);
- }
-
- /* Process items */
- for (j=st_glob.i_first; j<=st_glob.i_last && !(status & S_INT); j++) {
- if (!act[j-1] || !sum[j-1].flags) continue;
-
- #ifdef NEWS
- if (st_glob.c_security & CT_NEWS) {
- char **config;
-
- if (!(config = get_config(confidx)))
- return 1;
- sprintf(buff,"%s/%s/%d",NEWSDIR,dot2slash(config[CF_NEWSGROUP]),
- j);
- } else
- #endif
- sprintf(buff,"%s/_%d",conflist[confidx].location,j);
- st_glob.i_current=j;
- show_header();
- if (status & S_REDIRECT) spclose(st_glob.outp);
- do_respond(argc>0 && match(argv[0],"ps_eudonym"),st_glob.r_first+1);
- }
- return 1;
- }
-
- /******************************************************************************/
- /* ENTER A RESPONSE IN THE CURRENT ITEM */
- /******************************************************************************/
- int /* RETURNS: (nothing) */
- rfp_respond(argc,argv) /* ARGUMENTS: */
- int argc; /* Number of arguments */
- char **argv; /* Argument list */
- {
- short a= -1;
-
- if (argc>2 || (argc>1 && (sscanf(argv[1],"%hd",&a)<1 || a<0))) {
- printf("Bad parameters near \"%s\"\n",argv[(argc>2)?2:1]);
- return 2;
- } else
- do_respond(argc>0 && match(argv[0],"ps_eudonym"),(short)a+1);
-
- return 1;
- }
-
- void
- dump_reply(sep)
- char *sep;
- {
- sepinit(IS_START);
- itemsep(sep,0);
- for (st_glob.l_current=0;
- st_glob.l_current<xsizeof(re[st_glob.r_current].text)
- && !(status & S_INT);
- st_glob.l_current++) {
- sepinit(IS_ITEM);
- itemsep(sep,0);
- }
- sepinit(IS_CFIDX);
- itemsep(sep,0);
- }
-
- /******************************************************************************/
- /* MAIL A REPLY TO THE AUTHOR OF A RESPONSE */
- /******************************************************************************/
- int /* RETURNS: (nothing) */
- reply(argc,argv) /* ARGUMENTS: */
- int argc; /* Number of arguments */
- char **argv; /* Argument list */
- {
- char buff[MAX_LINE_LENGTH];
- short i;
- FILE *fp,*pp;
- flag_t ss;
- register int cpid,wpid;
- int statusp;
-
- /* Validate arguments */
- if (argc<2 || sscanf(argv[1],"%hd",&i)<1) {
- printf("You must specify a comment number.\n");
- return 1;
- } else if (argc>2) {
- printf("Bad parameters near \"%s\"\n",argv[2]);
- return 2;
- }
- refresh_sum(0,confidx,sum,part,&st_glob);
- if (i<0 || i>=sum[st_glob.i_current - 1].nr) {
- wputs("Can't go that far! near \"<newline>\"\n");
- return 1;
- }
-
- if (re[i].flags & RF_CENSORED) {
- wputs("Cannot reply to censored response!\n");
- return 1;
- }
- if (re[i].offset < 0) {
- printf("Offset error.\n"); /* should never happen */
- return 1;
- }
-
- /* Get complete text */
- #ifdef NEWS
- if (st_glob.c_security & CT_NEWS) {
- char **config;
-
- if (!(config = get_config(confidx)))
- return 1;
- sprintf(buff,"%s/%s/%d",NEWSDIR,dot2slash(config[CF_NEWSGROUP]),st_glob.i_current);
- } else
- #endif
- sprintf(buff,"%s/_%d",conflist[confidx].location,st_glob.i_current);
- if ((fp=mopen(buff,O_R))==NULL) return 1;
- get_resp(fp,&(re[i]),GR_ALL,i);
- mclose(fp);
-
- /* Fork & setuid down when creating cf.buffer */
- if (cpid=fork()) { /* parent */
- if (cpid<0) return -1; /* error: couldn't fork */
- while ((wpid = wait(&statusp)) != cpid && wpid != -1);
- /* post = !statusp; */
- } else { /* child */
- if (setuid(getuid())) error("setuid","");
- setgid(getgid());
-
- /* Save to cf.buffer */
- sprintf(buff,"%s/cf.buffer",work);
- if ((fp=mopen(buff,O_W))==NULL) {
- xfree( re[i].text );
- return 1;
- }
-
- pp = st_glob.outp;
- ss = status;
- st_glob.r_current = i;
- st_glob.outp = fp;
- status |= S_REDIRECT;
-
- dump_reply("replysep");
-
- st_glob.outp = pp;
- status = ss;
-
- dump_reply("replysep");
-
- mclose(fp);
- exit(0);
- }
-
- /* Invoke mailer */
- sprintf(buff,"mail %s",re[i].login);
- command(buff,0);
-
- xfree( re[i].text );
- mode = M_RFP;
- return 1;
- }
-
- /******************************************************************************/
- /* CENSOR A RESPONSE IN THE CURRENT ITEM */
- /******************************************************************************/
- int /* RETURNS: (nothing) */
- censor(argc,argv) /* ARGUMENTS: */
- int argc; /* Number of arguments */
- char **argv; /* Argument list */
- {
- char buff[MAX_LINE_LENGTH],over[MAX_LINE_LENGTH];
- short i,typ,j,k;
- FILE *fp;
- char **text; short len;
-
- typ = (match(argv[0],"scr_ibble"))? RF_CENSORED|RF_SCRIBBLED : RF_CENSORED;
-
- /* Validate arguments */
- if (argc<2 || sscanf(argv[1],"%hd",&i)<1) {
- printf("You must specify a comment number.\n");
- return 1;
- } else if (argc>2) {
- printf("Bad parameters near \"%s\"\n",argv[2]);
- return 2;
- }
- refresh_sum(0,confidx,sum,part,&st_glob);
- if (i<0 || i>=sum[st_glob.i_current - 1].nr) {
- wputs("Can't go that far! near \"<newline>\"\n");
- return 1;
- }
-
- /* Check for permission to censor */
- if (!(st_glob.c_status & CS_FW) && uid!=re[i].uid) {
- wputs("You can't do that!\n");
- return 1;
- }
- if (sum[st_glob.i_current-1].flags & IF_FROZEN) {
- wputs("Cannot censor frozen items!\n");
- return 1;
- }
-
- if ((re[i].flags & typ)==typ) return 1; /* already done */
- if (re[i].offset < 0) {
- printf("Offset error.\n"); /* should never happen */
- return 1;
- }
-
- sprintf(buff,"%s/_%d",conflist[confidx].location,st_glob.i_current);
- if ((fp=mopen(buff,O_RPLUS))!=NULL) {
- if (fseek(fp,re[i].offset,0))
- error("fseeking in ",buff);
- fprintf(fp,",R%04d\n",typ);
-
- /* log it and overwrite it, unless it's a news article */
- #ifdef NEWS
- if (!re[i].article) {
- #endif
- get_resp(fp,&(re[i]),GR_ALL,i);
- fseek(fp,re[i].textoff,0);
- text = re[i].text;
- if (typ & RF_SCRIBBLED) {
- sprintf(over,"%s %s %s ",login,get_date(time((time_t *)0),0),st_glob.fullname);
- len = strlen(over);
- for (j=re[i].numchars; j>76; j-=76) {
- for (k=0; k<75; k++)
- fputc(over[k%len],fp);
- fputc('\n',fp);
- }
- for (k=0; k<j-1; k++)
- fputc(over[k%len],fp);
- fputc('\n',fp);
- }
- #ifdef NEWS
- }
- #endif
- mclose(fp);
- }
-
- /* free_sum(sum); unneeded, always SF_FAST */
-
- /* Write to censorlog */
- sprintf(buff,"%s/censored",bbsdir);
- if (fp=mopen(buff,O_A|O_PRIVATE)) {
- fprintf(fp,",C %s item %d resp %d rflg %d %s,%d %s date %s\n",
- conflist[confidx].location, st_glob.i_current, i, typ,
- login, uid, get_date(time((time_t *)0),0), st_glob.fullname);
- fprintf(fp,",R%04X\n,U%d,%s\n,A%s\n,D%lX\n,T\n",
- re[i].flags,re[i].uid,re[i].login,re[i].fullname,re[i].date);
- for (j=0; j<xsizeof(text); j++)
- fprintf(fp,"%s\n",text[j]);
- fprintf(fp,",E\n");
- mclose(fp);
- }
- xfree( re[i].text );
- re[i].flags=typ;
- return 1;
- }
-
- short stack[MAX_RESPONSES],top=0;
- void
- traverse(i)
- short i;
- {
- short c,l,s;
-
- printf("%s%3d", (top)?"-":" ", i);
- stack[top++]=i;
- c=child(i);
- if (c<0) putchar('\n');
- else traverse(c);
-
- top--;
- if (!top) return;
-
- c=sibling(i);
- if (c>=0) {
- for (l=1; l<=top; l++) {
- printf(" "); /* printf("(%d)",stack[l]); */
- s=sibling(stack[l]);
- if (s<0) putchar(' ');
- else if (l<top) putchar('|');
- else putchar( (sibling(s)<0)?'\\':'+' );
- }
- traverse(c);
- }
- }
-
- /******************************************************************************/
- /* DISPLAY RESPONSE TREE */
- /******************************************************************************/
- int /* RETURNS: (nothing) */
- tree(argc,argv) /* ARGUMENTS: */
- int argc; /* Number of arguments */
- char **argv; /* Argument list */
- {
- short i=0;
-
- /* Validate arguments */
- if (argc>2 || (argc>1 && sscanf(argv[1],"%hd",&i)<1)) {
- printf("Bad parameters near \"%s\"\n",argv[2]);
- return 2;
- }
- refresh_sum(0,confidx,sum,part,&st_glob);
- if (i<0 || i>=sum[st_glob.i_current-1].nr) {
- wputs("Can't go that far! near \"<newline>\"\n");
- return 1;
- }
- traverse(i);
- return 1;
- }
-
- /******************************************************************************/
- /* PRESERVE RESPONSES IN THE CURRENT ITEM */
- /******************************************************************************/
- int /* RETURNS: (nothing) */
- preserve(argc,argv) /* ARGUMENTS: */
- int argc; /* Number of arguments */
- char **argv; /* Argument list */
- {
- short i;
- short i_i;
-
- if (match(argv[0],"pr_eserve") || match(argv[0],"po_stpone")
- || match(argv[0],"n_ew") || match(argv[0],"wait")) {
- wputs("This item will still be new.\n");
- st_glob.r_last = -2;
- } else
- st_glob.r_last = -1; /* re-read nothing */
-
- /* Lots of ways to stop, so check inverse */
- i_i = st_glob.i_current - 1;
- if (!match(argv[0],"pr_eserve") && !match(argv[0],"po_stpone")
- && !match(argv[0],"p_ass") && !match(argv[0],"hide")) {
- if (st_glob.opt_flags & OF_REVERSE)
- st_glob.i_current = st_glob.i_first;
- else
- st_glob.i_current = st_glob.i_last;
- wputs("Stopping.\n");
- status |= S_STOP;
- }
-
- if (argc<2) {
- mode = M_OK;
- return 1;
- }
-
- /* Validate arguments */
- if (sscanf(argv[1],"%hd",&i)<1) {
- printf("You must specify a comment number.\n");
- return 1;
- } else if (argc>2) {
- printf("Bad parameters near \"%s\"\n",argv[2]);
- return 2;
- }
- refresh_sum(0,confidx,sum,part,&st_glob);
- if (i<0 || i>=sum[i_i].nr) {
- wputs("Can't go that far! near \"<newline>\"\n");
- return 1;
- }
-
- /* Do it */
- part[i_i].nr = st_glob.r_lastseen = i;
- if (st_glob.r_last == -2)
- st_glob.r_last = -1;
- else
- time(&(part[i_i].last));
- mode = M_OK;
-
- return 1;
- }
-
- short
- sibling(r)
- short r;
- {
- short a,p;
-
- /* Find next sibling */
- p = parent(r);
- a=r+1;
- if (!re[a].date) get_resp(ext_fp,&(re[a]),GR_HEADER,a);
- while (a<=st_glob.r_max && parent(a)!=p) {
- a++;
- if (!re[a].date) get_resp(ext_fp,&(re[a]),GR_HEADER,a);
- }
- if (a>st_glob.r_max) return -1;
- else return a;
- }
-
- short
- parent(r)
- short r;
- {
- return (re[r].parent < 1)? r-1 : re[r].parent-1;
- }
-
- short
- child(r)
- short r;
- {
- short a,p;
-
- /* Find 1st child */
- a = p = r+1;
- if (!re[a].date) get_resp(ext_fp,&(re[a]),GR_HEADER,a);
- if (re[a].parent && re[a].parent!=p) {
- a++;
- if (!re[a].date) get_resp(ext_fp,&(re[a]),GR_HEADER,a);
- while (a<=st_glob.r_max && re[a].parent!=p) {
- a++;
- if (!re[a].date) get_resp(ext_fp,&(re[a]),GR_HEADER,a);
- }
- }
- return (a>st_glob.r_max)? -1 : a;
- }
-