home *** CD-ROM | disk | FTP | other *** search
- /* LIB.C */
- static char sccsid[] = "@(#)lib.c 1.34 93/06/09 Copyright (c)1993 thalerd";
- #include <stdio.h>
- #include <string.h>
- #include <sys/types.h>
- #include <sys/file.h>
- #include <sys/stat.h>
- #include <time.h>
- #include <errno.h>
- #include <fcntl.h> /* to get O_CREAT, etc */
- #include <ctype.h>
- #include <signal.h> /* to get sigvec stuff */
- #ifndef linux
- extern char *sys_errlist[]; /* standard error messages, usu. in errno.h */
- #endif
- #include "config.h"
- #include "struct.h"
- #include "xalloc.h"
- #include "globals.h"
- #include "lib.h"
- #include "macro.h"
- #include "system.h"
- #include "main.h"
- #include "files.h"
-
- /******************************************************************************/
- /* FIND INDEX OF ELT IN ARR AT OR AFTER START, -1 IF NOT FOUND */
- /******************************************************************************/
- short /* RETURNS: index of elt or -1 */
- searcha(elt,arr,start) /* ARGUMENTS: */
- char *elt; /* String to search for */
- char **arr; /* String array to search */
- short start; /* Index to start looking at */
- {
- short i,l;
- l=xsizeof(arr);
- for (i=start; i<l; i++)
- if (!strcmp(arr[i],elt)) return i;
- return -1;
- }
-
- /******************************************************************************/
- /* CHECK FOR A PARTIAL STRING MATCH (required_optional) */
- /******************************************************************************/
- char /* RETURNS: 1 if match, 0 else */
- match(ent,und) /* ARGUMENTS: */
- char *ent, /* String entered by user */
- *und; /* String with underlines to match */
- {
- char *q;
- short n;
-
- q=strchr(und,'_'); /* "_optional" */
- n=(q)? q-und : strlen(und); /* number of required chars */
- if (!n) return !strlen(ent); /* dont match "" with anything but "" */
- if (strnicmp(ent,und,n)) return 0; /* match before _ */
- if (q && strnicmp(ent+n,q+1,strlen(ent)-n)) return 0; /* match after _ */
- if (strlen(ent) > strlen(und)-(q!=0)) return 0; /* no extra chars */
- return 1;
- }
-
- /******************************************************************************/
- /* READ A FILE INTO AN ARRAY OF STRINGS (1 ELT PER LINE) */
- /******************************************************************************
- Function: char **grab_file(char *dir,char *filename, char flags)
- Called by: main
- Arguments: Filename to grab
- Returns: Array of char *'s with lines of file
- Calls:
- Description: This function will read in an entire file of text into
- memory, dynamically allocating enough space to hold it.
- *******************************************************************************/
- #define MAX_LINES 5000
- #define HEADER_LINES 6
- char ** /* RETURNS: (nothing) */
- grab_file(dir,filename,fl) /* ARGUMENTS: */
- char *dir; /* Directory containing file */
- char *filename; /* Filename to read into memory */
- char fl; /* Flags (see lib.h) */
- {
- char **mem;
- FILE *fp;
- char buff[MAX_LINE_LENGTH],buff2[MAX_LINE_LENGTH];
- short lines, max;
-
- if (filename)
- sprintf(buff,"%s/%s",dir,filename);
- else
- strcpy(buff,dir);
- if ((fp=mopen(buff,(fl & GF_SILENT)? O_R|O_SILENT : O_R))==NULL)
- return 0;
- max=(fl & GF_HEADER)? HEADER_LINES : MAX_LINES;
- mem=xalloc(max,sizeof(char *));
- if (flags & O_DEBUG)
- printf("MEM: %x size=%d want %d eltsize=%d\n", mem, sizeof(mem),
- max, sizeof(char *));
- if (fl & GF_WORD) /* count each word as a line */
- for (lines=0; lines<max && fscanf(fp,"%s",buff2)==1; ) {
- if (buff2[0]=='#' && (fl & GF_IGNCMT))
- fgets(buff2, MAX_LINE_LENGTH, fp);
- else
- mem[lines++]=xstrdup(buff2);
- }
- else {
- /* for (lines=0; lines<max && ngets(buff2,fp) && !(status & S_INT); lines++) */
- for (lines=0; lines<max && ngets(buff2,fp); ) {
- if (buff2[0]!='#' || !(fl & GF_IGNCMT))
- mem[lines++]=xstrdup(buff2);
- }
- }
- mclose(fp);
- if (lines<max) mem=xrealloc(mem,lines);
- else if (lines==MAX_LINES) {
- printf("Error: %s too long\n",buff);
- mem=xrealloc(mem,(short)0);
- }
- return mem;
- }
-
- /******************************************************************************/
- /* GRAB SOME MORE OF A FILE UNTIL WE FIND SOME STRING */
- /******************************************************************************/
- char ** /* RETURNS: (nothing) */
- grab_more(fp,end,fl) /* ARGUMENTS: */
- FILE *fp; /* Input file pointer */
- char *end; /* String to stop after */
- char fl; /* Flags (see lib.h) */
- {
- char **mem;
- char buff[MAX_LINE_LENGTH];
- short lines,max;
-
- max=(fl & GF_HEADER)? HEADER_LINES : MAX_LINES;
- mem=xalloc(max,sizeof(char *));
- if (flags & O_DEBUG)
- printf("MEM: %x size=%d want %d eltsize=%d\n", mem, sizeof(mem),
- max, sizeof(char *));
- if (fl & GF_WORD) /* count each word as a line */
- for (lines=0; lines<max && fscanf(fp,"%s",buff)==1; lines++) {
- mem[lines]=xstrdup(buff);
- if (end && !strcmp(buff,end)) break;
- }
- else
- for (lines=0; lines<max && ngets(buff,fp); lines++) {
- if (end && buff[0]==end[0] && buff[1]==end[0])
- mem[lines]=xstrdup(buff+2);
- else
- mem[lines]=xstrdup(buff);
- if (end && (!strcmp(buff,end) || !strncmp(buff,",R",2))) break;
- }
- if (lines<max) mem=xrealloc(mem,lines);
- return mem;
- }
-
- /* return static string of fields */
- void
- implode(buff,arr,sep,start)
- char *buff;
- char **arr;
- char *sep;
- short start;
- {
- short i,s;
-
- buff[0]='\0';
- s = xsizeof(arr);
- if (s>start) strcpy(buff,arr[start]);
- for (i=start+1; i<s; i++) {
- strcat(buff,sep);
- strcat(buff,arr[i]);
- }
- }
-
- /******************************************************************************/
- /* SPLIT A STRING INTO AN ARRAY OF FIELDS */
- /******************************************************************************/
- char ** /* RETURNS: (nothing) */
- explode(str,sep) /* ARGUMENTS: */
- char *str; /* Filename to read into memory */
- char *sep; /* Field separator string */
- {
- char **mem,*ln,*nstr;
- short lines;
-
- mem=xalloc(MAX_LINES,sizeof(char *));
- nstr=xstrdup(str);
-
- if (sep) {
- ln=strtok(nstr,sep);
- for (lines=0; ln && lines<MAX_LINES; lines++) {
- while (*ln == ' ') ln++; /* skip leading spaces */
- mem[lines]=xstrdup(ln);
- while (strlen(mem[lines]) && mem[lines][ strlen(mem[lines])-1 ] == ' ')
- mem[lines][ strlen(mem[lines])-1 ] = 0; /* trash trailing spaces */
- ln = strtok(NIL,sep);
- }
- } else {
- mem[0]=xstrdup(str);
- lines=1;
- }
-
- mem=xrealloc(mem,lines);
- xfree(nstr);
- return mem;
- }
-
- /******************************************************************************/
- /* APPEND A LINE TO A FILE */
- /******************************************************************************
- Function: char write_file(char *filename, char *string)
- Called by:
- Arguments: filename to put stuff in, string to put there
- Returns: 1 on success, 0 if error
- Calls:
- Description: Appends a block of text to a file with a single operation.
- Locks & unlocks file to be safe.
- *******************************************************************************/
- char /* RETURNS: 1 on success, 0 if error */
- write_file(filename,str) /* ARGUMENTS: */
- char *filename; /* Filename to append to */
- char *str; /* Block of text to write */
- {
- FILE *fp;
- long mod=O_A;
-
- if (st_glob.c_status & CT_BASIC) mod |= O_PRIVATE;
- if ((fp=mopen(filename,mod))==NULL) return 0;
- fwrite(str,strlen(str),1,fp);
- mclose(fp);
- return 1;
- }
-
- /******************************************************************************/
- /* DUMP A FILE TO THE OUTPUT */
- /******************************************************************************
- Function: char cat(char *dir, char *filename)
- Called by:
- Arguments: filename to display
- Returns: 1 on success, 0 on failure
- Calls:
- Description: Copies a file to the screen (not grab_file)
- *******************************************************************************/
- char /* RETURNS: (nothing) */
- cat(dir,filename) /* ARGUMENTS: */
- char *dir; /* Directory containing file */
- char *filename; /* Filename to display */
- {
- FILE *fp;
- int c;
- char buff[MAX_LINE_LENGTH];
-
- if (filename)
- sprintf(buff,"%s/%s",dir,filename);
- else
- strcpy(buff,dir);
- if (flags & O_DEBUG) printf("cat: %s\n",buff);
- if ((fp=mopen(buff,O_R))==NULL) return 0;
- while ((c=fgetc(fp))!=EOF && !(status & S_INT)) wputchar(c);
- mclose(fp);
- return 1;
- }
- extern char pipebuf[MAX_LINE_LENGTH];
- /******************************************************************************/
- /* DUMP A FILE TO THE OUTPUT THROUGH A PAGER */
- /******************************************************************************
- char /* RETURNS: (nothing) */
- more(dir,filename) /* ARGUMENTS: */
- char *dir; /* Directory containing file */
- char *filename; /* Filename to display */
- {
- FILE *fp,*pp;
- char buff[MAX_LINE_LENGTH];
- int c;
-
- /* Need to check if pager exists */
- if (!pipebuf[0]) strcpy(pipebuf,expand("pager",DM_VAR));
- if (!(flags & O_BUFFER) || !pipebuf[0])
- return cat(dir,filename);
-
- if (filename)
- sprintf(buff,"%s/%s",dir,filename);
- else
- strcpy(buff,dir);
- if (flags & O_DEBUG) printf("CAT: %s\n",buff);
- if ((fp=mopen(buff,O_R))==NULL) return 0;
- open_pipe();
- while ((c=fgetc(fp))!=EOF)
- if (fputc(c,st_glob.outp)==EOF) break;
- spclose(st_glob.outp);
- mclose(fp);
- status &= ~S_INT;
- return 1;
- }
-
- /******************************************************************************/
- /* GET INPUT WITHOUT ECHOING IT */
- /******************************************************************************/
- char * /* RETURNS: text entered */
- get_password() /* ARGUMENTS: (none) */
- {
- static char buff[MAX_LINE_LENGTH];
- short i=0,c;
-
- unix_cmd("/bin/stty -echo");
- while ((c=getchar())!=10 && c!=13 && c!= -1 && i<MAX_LINE_LENGTH)
- buff[i++]=c;
- buff[i]=0;
- putchar('\n');
- unix_cmd("/bin/stty echo");
- return buff;
- }
-
- /******************************************************************************/
- /* GET INPUT WITHOUT OVERFLOWING BUFFER */
- /******************************************************************************/
- char * /* RETURNS: text entered */
- ngets(str,fp) /* ARGUMENTS: */
- char *str; /* Input buffer */
- FILE *fp; /* Input stream */
- {
- char *ok;
- int i,j,strip=0;
- char buff[MAX_LINE_LENGTH];
- struct sigvec vec;
-
- if (fp==st_glob.inp) {
- if (status & S_REDIRECT)
- spclose(st_glob.outp);
-
- /* Make INT abort fgets() */
- sigvec(SIGINT, NULL, &vec);
- vec.sv_flags |= SV_INTERRUPT;
- sigvec(SIGINT, &vec, NULL);
- }
-
- ok=fgets(str,MAX_LINE_LENGTH,fp);
-
- if (fp==st_glob.inp) {
-
- /* Stop INT from aborting fgets() */
- sigvec(SIGINT, NULL, &vec);
- vec.sv_flags &= ~SV_INTERRUPT;
- sigvec(SIGINT, &vec, NULL);
-
- if (!ok) {
- if (fp==stdin) {
- clearerr(fp);
- printf("\n");
- } else {
- mclose(fp);
- st_glob.inp = stdin;
- return ngets(str, st_glob.inp);
- }
- }
- }
- if (ok)
- str[ strlen(str)-1 ] =0; /* trash newline */
- else if ((status & S_INT) && (fp==st_glob.inp)) {
- /* for systems where interrupts abort fgets */
- str[0]='\0';
- return str;
- }
-
- if ((fp==st_glob.inp) && (flags & O_STRIP)) {
- for (i=j=0; i<strlen(str); i++) {
- if (isprint(str[i]) || isspace(str[i])) buff[j++]=str[i];
- else {
- printf("%s ^%c",(strip++)? "" : "Stripping bad input:", str[i]+64);
- }
- }
- if (strip) printf("\n");
- buff[j]='\0';
- strcpy(str,buff);
- }
- return ok;
- }
-
- /******************************************************************************/
- /* GET INPUT UNTIL USER SAYS YES OR NO */
- /******************************************************************************/
- char /* RETURNS: 1 for yes, 0 no */
- get_yes(pr) /* ARGUMENTS: */
- char *pr; /* Prompt */
- {
- char buff[MAX_LINE_LENGTH];
-
- for(;;) {
- if (status & S_MOTIF)
- wgets(buff,pr);
- else {
- wputs(pr);
- if (!ngets(buff,st_glob.inp)) return 0;
- }
- if (match(buff,"n_on") || match(buff,"nop_e")) return 0;
- if (match(buff,"y_es") || match(buff,"ok")) return 1;
- printf("Try yes or no.\n");
- }
- }
-
- #ifdef NOSTRNICMP
- /******************************************************************************/
- /* STANDARD strnicmp() CODE FOR THOSE OS'S WHICH DON'T HAVE IT */
- /******************************************************************************/
- int
- strnicmp(a,b,n)
- char *a,*b;
- int n;
- {
- char *s;
- for (s=a; (tolower(*s) == tolower(*b)) && (s-a < n); s++, b++)
- if (*s == '\0')
- return 0;
- if (s-a >= n) return 0;
- return tolower(*s) - tolower(*b);
- }
- #endif
-
- /******************************************************************************/
- /* READ IN ASSOCIATIVE LIST */
- /* ! and # begin comments and are not part of the list */
- /* =filename chains to another file */
- /******************************************************************************/
- char /* RETURNS: 1 on success, 0 error */
- grab_list(dir,filename,list,size) /* ARGUMENTS: */
- char *dir; /* Directory containing file */
- char *filename; /* Filename to read from */
- assoc_t list[]; /* Array to fill in */
- short *size; /* Size of array */
- {
- FILE *fp;
- char buff[MAX_LINE_LENGTH],name[MAX_LINE_LENGTH],*loc;
-
- if (filename && dir) sprintf(name,"%s/%s",dir,filename);
- else if (dir) strcpy(name,dir);
- else if (filename) strcpy(name,filename);
- else return 0;
-
- if ((fp=mopen(name,O_R|O_SILENT))==NULL) {
- error("grabbing list ",name);
- return 0;
- }
-
- do {
- loc=ngets(buff,fp);
- } while(loc && (buff[0]=='#' || buff[0]=='!'));
- if (!loc) {
- (void)fprintf(stderr,"Error: %s is empty.\n",name);
- return 0;
- }
- list[0].name = xstrdup("");
- list[0].location = xstrdup(buff);
- if (flags & O_DEBUG) printf("Default: '%s'\n",buff);
- if (strchr(buff,':'))
- (void)fprintf(stderr,"Warning: %s may be missing default.\n",name);
-
- for (*size =1; ngets(buff,fp) && (*size)<MAX_LIST_LENGTH; ) {
- if (flags & O_DEBUG) printf("Buff: '%s'\n",buff);
- if (buff[0]=='#' || buff[0]=='\0') continue;
- if (loc = strchr(buff,':')) {
- strncpy(name,buff,loc-buff);
- name[loc-buff]=0;
- loc++;
-
- list[*size].name = xstrdup(name);
- list[*size].location = xstrdup(loc);
- if (flags & O_DEBUG)
- printf("Name: '%s' Dir: '%s'\n",list[*size].name,
- list[*size].location);
- (*size)++;
-
- /* Chain to another file */
- } else if (buff[0]=='=' && strlen(buff)>1) {
- mclose(fp);
-
- if (buff[1]=='%') sprintf(name,"%s/%s",bbsdir,buff+2);
- else if (dir) sprintf(name,"%s/%s",dir,buff+1);
- else strcpy(name,buff+1);
-
- if ((fp=mopen(name,O_R|O_SILENT))==NULL) {
- error("grabbing list ",name);
- return 1;
- }
- ngets(buff,fp); /* read magic line */
- if (flags & O_DEBUG) printf("grab_list: magic %s\n",buff);
-
- } else {
- (void)fprintf(stderr,"UNK Bad line read: %s\n",buff);
- }
- }
- mclose(fp);
- if (*size == MAX_LIST_LENGTH)
- printf("Warning: list length exceeded.\n");
- return 1;
- }
-
- /******************************************************************************/
- /* CONVERT TIMESTAMP INTO A STRING IN VARIOUS FORMATS */
- /******************************************************************************/
- char * /* RETURNS: Date string */
- get_date(t,sty) /* ARGUMENTS: */
- time_t t; /* Timestamp */
- char sty; /* Output style */
- {
- static char buff[MAX_LINE_LENGTH];
- struct tm *tms;
- static char *fmt[]={
- #ifdef NOEDATE
- /* 0 */ "%a %b %d %H:%M:%S %Y", /* dates must be in 05 format */
- /* 1 */ "%a, %b %d, %Y (%H:%M)",
- #else
- /* 0 */ "%a %b %e %H:%M:%S %Y", /* dates need not have leading 0 */
- /* 1 */ "%a, %b %e, %Y (%H:%M)",
- #endif
- /* 2 */ "%a",
- /* 3 */ "%b",
- /* 4 */ "%e",
- /* 5 */ "%y",
- /* 6 */ "%Y",
- /* 7 */ "%H",
- /* 8 */ "%M",
- /* 9 */ "%S",
- /* 10 */ "%I",
- /* 11 */ "%p",
- /* 12 */ "%p",
- #ifdef NOEDATE
- /* 13 */ "(%H:%M:%S) %B %d, %Y"
- #else
- /* 13 */ "(%H:%M:%S) %B %e, %Y"
- #endif
- };
-
- tms = localtime(&t);
- if (sty<0 || sty>13) sty=0;
- strftime(buff,MAX_LINE_LENGTH,fmt[sty],tms);
- return buff;
- }
-
- /******************************************************************************/
- /* GENERATE STRING WITHOUT ANY "'_s IN IT */
- /******************************************************************************/
- char * /* RETURNS: New string */
- noquote(s,x) /* ARGUMENTS: */
- char *s; /* Original string */
- int x; /* Remove _'s too? */
- {
- static char buff[MAX_LINE_LENGTH];
- char *p,*q,qu=0;
-
- q=s;
- if (*q=='"' || *q=='\'') { qu= *q; q++; }
- for (p=buff; *q; q++)
- if (x==0 || *q != '_')
- *p++ = *q;
- *p=0;
- p--;
- if (p>=buff && *p==qu) *p=0;
- return buff;
- }
-
- /******************************************************************************/
- /* GENERATE STRING WITHOUT ANY _'s IN IT */
- /******************************************************************************/
- char * /* RETURNS: New string */
- compress(s) /* ARGUMENTS: */
- char *s; /* Original string */
- {
- static char buff[MAX_LINE_LENGTH];
- char *p,*q;
-
- for (p=buff,q=s; *q; q++)
- if (*q != '_')
- *p++ = *q;
- *p=0;
- return buff;
- }
-
- void
- error(str1,str2)
- char *str1,*str2;
- {
- FILE *fp;
- char errorlog[MAX_LINE_LENGTH];
- char timestamp[MAX_LINE_LENGTH];
- time_t t;
-
- if (errno)
- fprintf(stderr,"Got error %d (%s) in %s%s\n",errno,sys_errlist[errno],
- str1,str2);
- sprintf(errorlog,"%s/errorlog",bbsdir);
- if (fp=fopen(errorlog,"a")) {
- time(&t);
- strcpy(timestamp,ctime(&t)+4);
- timestamp[20]='\0';
- if (errno)
- fprintf(fp,"%-8s %s Got error %d (%s) in %s%s\n",
- login, timestamp, errno,sys_errlist[errno],str1,str2);
- else
- fprintf(fp,"%-8s %s WARNING: %s%s\n", login, timestamp, str1,str2);
- fclose(fp);
- }
- }
-
- char *
- lower_case(arg)
- char *arg;
- {
- char lwr[MAX_LINE_LENGTH];
- int i;
-
- for (i=0; i<=strlen(arg); i++)
- lwr[i] = tolower(arg[i]);
- return lwr;
- }
-