/* This software is Copyright 1989, 1990, 1992, 1993 by various individuals. Please see the accompanying file COPYRIGHT for details. */ #include #include #include #include #include #include "db.h" #include "help.h" #include "defs.h" #include "config.h" #include "params.h" #include "externs.h" #include "strings.h" #include "interface.h" static void update_index(const char *indxfile, const char *textfile) { long int pos; int n; int lineno; int lineinc; int ntopics; help_indx entry; FILE *rfp; FILE *wfp; char line[LINE_SIZE+1]; char *topic; fprintf(stderr,"Updating index file:%s\n",indxfile); rfp = fopen(textfile,"r"); if (! rfp) { fprintf(stderr,"can't open %s for reading\n",textfile); return; } wfp = fopen(indxfile,"w"); if (! wfp) { fprintf(stderr,"can't open %s for writing\n",indxfile); fclose(rfp); return; } pos = 0; lineno = 0; ntopics = 0; lineinc = 1; while (fgets(&line[0],sizeof(line),rfp) == &line[0]) { lineno += lineinc; lineinc = 1; n = strlen(line); if ((n > 0) && (line[n-1] != '\n')) { fprintf(stderr,"line %d: line too long\n",lineno); lineinc = 0; } if (index(&line[0],'\t')) { fprintf(stderr,"%s contains a tab (line %d)\n",textfile,lineno); } #if 0 /* mustn't modify n at this point */ if (index(&line[0],'\t')) { int inc; int outgrew; fprintf(stderr,"%s contains a tab (line %d), patching\n",textfile,lineno); outgrew = 0; for (i=0;line[i];i++) { if (line[i] == '\t') { line[i] = ' '; inc = ((i + 8) & ~7) - i - 1; if (inc > 0) { n += inc; if (n >= sizeof(line)) { outgrew += n - (sizeof(line)-1); n = sizeof(line) - 1; } bcopy(line+i+1,line+i+1+inc,n-(i+1+inc)+1); for (;inc>0;inc--) line[i+inc] = ' '; } } } if (outgrew) { fprintf(stderr,"%s line %d too long after fixup, lost last %d char%s\n",textfile,lineno,outgrew,(outgrew==1)?"":"s"); } } #endif if (! strncmp(line,HELP_TOPIC_MARK,sizeof(HELP_TOPIC_MARK)-1)) { ntopics ++; if (ntopics > 1) { entry.loc.len = pos - entry.loc.pos; if (fwrite(&entry,sizeof(entry),1,wfp) != 1) { fprintf(stderr,"error writing %s\n",indxfile); fclose(wfp); fclose(rfp); unlink(indxfile); return; } } line[n-1] = '\0'; topic = &line[3]; while (*topic && (*topic == ' ')) topic ++; strncpy(&entry.topic[0],topic,TOPIC_NAME_LEN); entry.topic[TOPIC_NAME_LEN] = '\0'; entry.loc.pos = pos + n; } else { if (lineno == 1) { fprintf(stderr,"%s doesn't begin with a topic marker\n",textfile); fclose(wfp); fclose(rfp); unlink(indxfile); return; } } pos += n; } entry.loc.len = pos - entry.loc.pos; if (fwrite(&entry,sizeof(entry),1,wfp) != 1) { fprintf(stderr,"error writing %s\n",indxfile); fclose(rfp); fclose(wfp); unlink(indxfile); return; } fclose(rfp); fclose(wfp); } void spit_file(dbref player, const char *filename) { FILE *f; char buf[BUFFER_LEN]; char *p; if((f = fopen(filename, "r")) == NULL) { sprintf(buf, "Sorry, %s is broken. Management has been notified.", filename); notify(player, buf); fputs("spit_file:", stderr); perror(filename); } else { while(fgets(buf, sizeof buf, f)) { for(p = buf; *p; p++) if(*p == '\n') { *p = '\0'; break; } notify(player, buf); } fclose(f); } } void do_help(dbref player, const char *arg1, const char *deftopic, const char *indxfile, const char *textfile) { int textfd; int indxfd; int i; int listmatches; int prefcount; int looped; FILE *fp; help_filepart best; help_indx indxent; struct stat textstat; struct stat indxstat; char buf[BUFFER_LEN]; looped = 0; top:; textfd = open(textfile,O_RDONLY,0); if (textfd < 0) { i = errno; sprintf(&buf[0],"Sorry, %s is (temporarily, we hope) broken.",deftopic); notify(player,&buf[0]); log_status("Can't open %s for reading: %s\n",textfile,strerror(i)); return; } fstat(textfd,&textstat); indxfd = open(indxfile,O_RDONLY,0); if (indxfd < 0) { if (errno != ENOENT) { i = errno; sprintf(&buf[0],"Sorry, %s is (temporarily, we hope) broken.",deftopic); notify(player,&buf[0]); log_status("Can't open %s for reading: %s\n",indxfile,strerror(i)); close(textfd); return; } indxstat.st_mtime = 0; } else { fstat(indxfd,&indxstat); } if (indxstat.st_mtime < textstat.st_mtime) { close(indxfd); update_index(indxfile,textfile); indxfd = open(indxfile,O_RDONLY,0); if (indxfd < 0) { i = errno; sprintf(&buf[0],"Sorry, %s is (temporarily, we hope) broken.",deftopic); notify(player,&buf[0]); log_status("Can't open %s for reading after update: %s\n",indxfile,strerror(i)); close(textfd); return; } } fp = fdopen(indxfd,"r"); if (fp == 0) { close(textfd); close(indxfd); sprintf(&buf[0],"Sorry, %s is rather ill.",deftopic); notify(player,&buf[0]); log_status("Can't fdopen %s\n",indxfile); return; } if (!arg1 || !*arg1) arg1 = deftopic; listmatches = 0; if ((arg1[0] == '?') && (arg1[1] == ' ')) { listmatches = 1; while (*++arg1 == ' ') ; if (!*arg1) { sprintf(&buf[0],"Use plain `%s' for a list of topics.",deftopic); notify(player,&buf[0]); fclose(fp); close(textfd); return; } } prefcount = 0; while (fread(&indxent,sizeof(indxent),1,fp) == 1) { if (string_prefix(&indxent.topic[0],arg1)) { prefcount ++; if (listmatches) { if (prefcount == 1) { sprintf(&buf[0],"Matches for %s in %s:",arg1,deftopic); notify(player,&buf[0]); } notify(player,&indxent.topic[0]); } else { best = indxent.loc; if (!string_compare(&indxent.topic[0],arg1)) { prefcount = 1; break; } } } } if (listmatches) { if (prefcount == 0) { sprintf(&buf[0],"No match for %s found in %s.",arg1,deftopic); } else { sprintf(&buf[0],"%d match%s found.",prefcount,(prefcount==1)?"":"es"); } notify(player,&buf[0]); fclose(fp); close(textfd); return; } fclose(fp); if (prefcount == 0) { sprintf(&buf[0],"No %s for `%s'.",deftopic,arg1); notify(player,&buf[0]); close(textfd); return; } if (prefcount > 1) { sprintf(&buf[0],"`%s %s' is ambiguous; %d matches found.",deftopic,arg1,prefcount); notify(player,&buf[0]); sprintf(&buf[0],"Use `%s ? %s' to list them.",deftopic,arg1); notify(player,&buf[0]); close(textfd); return; } fp = fdopen(textfd,"r"); if (fp == 0) { close(textfd); sprintf(&buf[0],"Sorry, %s is rather ill.",deftopic); notify(player,&buf[0]); log_status("Can't fdopen %s\n",textfile); return; } if (fseek(fp,best.pos,0) < 0) { if (looped) { sprintf(&buf[0],"Sorry, %s is out of order.",deftopic); notify(player,&buf[0]); fclose(fp); return; } looped = 1; unlink(indxfile); fclose(fp); goto top; } while (fgets(&buf[0],sizeof(buf),fp)) { if (!strncmp(&buf[0],HELP_TOPIC_MARK,strlen(HELP_TOPIC_MARK))) break; i = strlen(&buf[0]); if ((i > 0) && (buf[i-1] == '\n')) buf[--i] = '\0'; if (i == 0) { buf[0] = ' '; buf[1] = '\0'; } notify(player,&buf[0]); } fclose(fp); }