/* For best results in visual layout while viewing this file, set tab stops to every 4 columns. */ /* lib.c */ #include #include #include #include #include "host.h" #include "lib.h" static int changedir(); /* MKDIR - like mkdir() but create intermediate directories as well This routine has dependency on the path separator characters being '/', we should relove that somehow someday. */ int MKDIR(path) char *path; { char *cp = path; if (*cp == '\0') return 0; /* see if we need to make any intermediate directories */ while ((cp = strchr(cp, '/')) != nil(char)) { *cp = '\0'; mkdir(path); *cp = '/'; cp++; } /* make last dir */ return mkdir(path); } /*MKDIR*/ /* CHIDR - like chdir() but create the directory if necessary */ int CHDIR(path) char *path; { if (*path == '\0') return 0; MKDIR(path); /* change to last directory */ return changedir(path); } /*CHDIR*/ /* FOPEN - like fopen() but create imtermediate directories This routine has dependency on the path separator characters being '/', we should relove that somehow someday. */ FILE *FOPEN(name, mode, ftype) char *name, *mode, ftype; { char *last; FILE *results; /* are we opening for write or append */ FILEMODE(ftype); results = fopen(name, mode); if ((results != nil(FILE)) || (*mode == 'r')) return results; /* verify all intermediate directories in the path exist */ if ((last = strrchr(name, '/')) != nil(char)) { *last = '\0'; MKDIR(name); *last = '/'; } /* now try open again */ return fopen(name, mode); } /*FOPEN*/ int CREAT(name, mode, ftyp) char *name; int mode; char ftyp; { char *last; int results; /* are we opening for write or append */ FILEMODE(ftyp); results = creat(name, mode); if (results != -1) return results; /* see if we need to make any intermediate directories */ if ((last = strrchr(name, '/')) != nil(char)) { *last = '\0'; MKDIR(name); *last = '/'; } /* now try open again */ return creat(name, mode); } /*CREAT*/ /* getargs - return a list of pointers to tokens in the given line */ int getargs(line, flds) char *line, **flds; { int i = 0; while ((*line != '\0') && (*line != '\n')) { if (isspace(*line)) line++; else { *flds++ = line; i++; while(!isspace(*line) && (*line != '\0')) line++; if (isspace(*line)) *line++ = '\0'; } } return i; } /*getargs*/ static char *S_tzoffset; /* the following table contols the configurations files processing */ static struct Table { char *sym, **loc, must, sys; } table[] = { "mailbox", &mailbox, TRUE, FALSE, "name", &name, TRUE, FALSE, "home", &homedir, TRUE, FALSE, "maildir", &maildir, TRUE, TRUE, "newsdir", &newsdir, TRUE, TRUE, "confdir", &confdir, TRUE, TRUE, "spooldir", &spooldir, TRUE, TRUE, "pubdir", &pubdir, TRUE, TRUE, "tempdir", &tempdir, TRUE, TRUE, "domain", &domain, TRUE, TRUE, "nodename", &nodename, TRUE, TRUE, "mailserv", &mailserv, TRUE, TRUE, "indevice", &E_indevice, FALSE, TRUE, "inspeed", &E_inspeed, FALSE, TRUE, "editor", &E_editor, FALSE, FALSE, "pager", &E_pager, FALSE, FALSE, "tzoffset", &S_tzoffset, TRUE, TRUE, "tzname", &E_tzname, FALSE, TRUE, "filesent", &E_filesent, FALSE, FALSE, "signature", &E_signature, FALSE, FALSE, nil(char) }; /* getconfig - process a configuration file */ static int getconfig(fp, sysmode) FILE *fp; int sysmode; { struct Table *tptr; for ( ; ; ) { char buff[80], *cp; if (fgets(buff, sizeof buff, fp) == nil(char)) break; /* end of file */ if ((*buff == '\n') || (*buff == '#')) continue; /* comment line */ if (*(cp = buff + strlen(buff) - 1) == '\n') *cp = '\0'; if ((cp = strchr(buff, '=')) == nil(char)) continue; *cp++ = '\0'; strlwr(buff); for (tptr = table; tptr->sym != nil(char); tptr++) if (equal(buff, tptr->sym)) { if (tptr->sys && !sysmode) printmsg(0, "user specified system parameter \"%s\" ignored.", tptr->sym); else { if (*(tptr->loc) != nil(char)) free(*(tptr->loc)); /* free the previous one */ *(tptr->loc) = strdup(cp); } break; } } /*for*/ return TRUE; } /*getconfig*/ /* configure - define the global parameters of UUPC */ int configure() { char *sysrc, *usrrc; FILE *fp; int success, ok; struct Table *tptr; if (!getrcnames(&sysrc, &usrrc)) return FALSE; for (tptr = table; tptr->sym != nil(char); tptr++) *(tptr->loc) = nil(char); if ((fp = FOPEN(sysrc, "r", TEXT)) == nil(FILE)) { printmsg(0, "cannot open system configuration file \"%s\"", sysrc); return FALSE; } ok = getconfig(fp, TRUE); fclose(fp); if (!ok) return FALSE; if (usrrc == nil(char)) return TRUE; if ((fp = FOPEN(usrrc, "r", TEXT)) == nil(FILE)) { printmsg(0, "cannot open user configuration file \"%s\"", usrrc); return FALSE; } ok = getconfig(fp, FALSE); fclose(fp); if (!ok) return FALSE; success = TRUE; for (tptr = table; tptr->sym != nil(char); tptr++) { if (tptr->must && (*(tptr->loc) == nil(char))) { printmsg(0, "configuration parameter \"%s\" must be set.", tptr->sym); success = FALSE; } } /* convert time zone offset to internal form */ { register int x; x = atoi(S_tzoffset); E_tzoffset = (x < 0) ? -1 : 1; x = abs(x); E_tzoffset *= (x / 100) * 60 + x % 100; free(S_tzoffset); } return success; } /*configure*/ /* p r i n t m s g Print an error message if its severity level is high enough. Print message on standard output if not in remote mode (call-in). Always log the error message into the log file. */ int debuglevel = 1; int logecho = FALSE; FILE *logfile = stdout; /*VARARGS1*/ void printmsg(level, fmt, a1, a2, a3, a4, a5) int level; char *fmt; char *a1, *a2, *a3, *a4, *a5; { char msg[256]; if (level <= debuglevel) { sprintf(msg, fmt, a1, a2, a3, a4, a5); strcat(msg, "\n"); if (logecho) fputs(msg, stdout); fprintf(logfile, "(%d) ", level); fputs(msg, logfile); } } /*printmsg*/ /* changedir - like chdir() but also changes the current drive */ static int changedir(path) char *path; { if ((*path != '\0') && (path[1] == ':')) { unsigned char drive; if (((drive = toupper(*path)) >= 'A') && (drive <= 'Z')) setdisk(drive - (unsigned char)'A'); else return -1; } return chdir(path); } /*changedir*/