home *** CD-ROM | disk | FTP | other *** search
- /*
- * (c) Copyright 1990, Kim Fabricius Storm. All rights reserved.
- *
- * Global declarations and auxiliary functions.
- */
-
- #include <signal.h>
- #include <errno.h>
- #include <pwd.h>
- #include "config.h"
- #include "patchlevel.h"
-
- export char *home_directory;
- export char *nn_directory; /* ~/.nn */
- export char *news_directory; /* /usr/spool/news */
- export char *news_lib_directory; /* /usr/lib/news */
- export char *lib_directory; /* /usr/local/lib/nn */
- export char *master_directory; /* = lib */
- export char *help_directory; /* = lib/help */
- export char *bin_directory = BIN_DIRECTORY;
-
- export char *db_directory; /* /usr/spool/nn or NEWS_DIR/.nn */
- export char *db_data_directory; /* ..../DATA or undefined */
-
- export char *news_active; /* NLIB/active or DB/ACTIVE */
-
- export char *pager;
-
- export char *log_file; /* = lib/Log */
- export char *log_entry_filter = NULL;
-
- export char *temp_file;
-
- #ifndef TMP_DIRECTORY
- #define TMP_DIRECTORY "/usr/tmp"
- #endif
- export char *tmp_directory = TMP_DIRECTORY;
-
- export char version_id[32];
-
- export unsigned short user_id, group_id;
- export int process_id;
- export int who_am_i;
- export int dont_write_console = 0;
-
- #ifdef HAVE_MULTIGROUP
- #ifndef NGROUPS
- #include <sys/param.h>
- #endif
- #ifndef GIDSET_TYPE
- #define GIDSET_TYPE int
- #endif
- static int ngroups;
- static GIDSET_TYPE gidset[NGROUPS];
-
- static in_grplist(gid)
- GIDSET_TYPE gid;
- {
- int n;
-
- for (n = 0; n < ngroups; ++n)
- if (gidset[n] == gid) return 1;
-
- return 0;
- }
-
- #define group_access(gpid) in_grplist((GIDSET_TYPE)(gpid))
- #else
- #define group_access(gid) ((gid) == group_id)
- #endif
-
- /* signal handler interface */
-
- export int s_hangup = 0; /* hangup signal */
- export int s_keyboard = 0; /* keyboard interrupt */
- export int s_pipe = 0; /* broken pipe */
- export int s_redraw = 0; /* redraw signal (if job control) */
-
- sig_type catch_hangup(n)
- {
- signal(n, SIG_IGN);
-
- s_hangup++;
- }
-
- static sig_type catch_keyboard(n)
- {
- s_keyboard++;
-
- #ifdef RESET_SIGNAL_WHEN_CAUGHT
- signal(n, catch_keyboard);
- #endif
- }
-
- static sig_type catch_pipe(n)
- {
- s_pipe++;
-
- #ifdef RESET_SIGNAL_WHEN_CAUGHT
- signal(n, catch_pipe);
- #endif
- }
-
- #ifdef HAVE_JOBCONTROL
- static sig_type catch_suspend(n)
- {
- s_redraw++;
-
- #ifdef RESET_SIGNAL_WHEN_CAUGHT
- signal(n, catch_suspend);
- #endif
-
- suspend_nn();
- }
- #endif
-
-
- init_global()
- {
- unsigned short getuid(), getgid();
- int getpid();
- int suspend_nn();
-
- if (who_am_i != I_AM_NN) {
- signal(SIGINT, SIG_IGN);
- signal(SIGQUIT, SIG_IGN);
- }
- signal(SIGTERM, catch_hangup);
- signal(SIGHUP, catch_hangup);
- signal(SIGPIPE, catch_pipe);
- signal(SIGALRM, SIG_IGN);
-
- #ifdef SIGPWR
- signal(SIGPWR, catch_hangup);
- #endif
-
- sprintf(version_id, "%s.%d #%d", RELEASE, PATCHLEVEL,
- #include "update.h"
- );
-
- user_id = getuid();
-
- #ifdef HAVE_MULTIGROUP
- ngroups = getgroups(NGROUPS, gidset); /* Get users's group set */
- group_id = gidset[0]; /* not used, but just in case... */
- #else
- group_id = getgid();
- #endif
-
- process_id = getpid();
-
- #ifdef NEWS_DIRECTORY
- news_directory = NEWS_DIRECTORY;
- #else
- news_directory = "/usr/spool/news";
- #endif
-
- #ifdef DB_DIRECTORY
- db_directory = DB_DIRECTORY;
- #else
- db_directory = mk_file_name(news_directory, ".nn");
- #endif
-
- #ifdef ACCOUNTING
- if (who_am_i == I_AM_ACCT)
- return 0;
- #endif
-
- #ifdef DB_DATA_DIRECTORY
- db_data_directory = DB_DATA_DIRECTORY;
- #else
- #ifdef DB_DIRECTORY
- db_data_directory = mk_file_name(db_directory, "DATA");
- #else
- db_data_directory = NULL;
- #endif
- #endif
-
- #ifdef NEWS_LIB_DIRECTORY
- news_lib_directory = NEWS_LIB_DIRECTORY;
- #else
- news_lib_directory = "/usr/lib/news";
- #endif
-
- /* this may later be changed by nntp_check */
- news_active = mk_file_name(news_lib_directory, "active");
-
- #ifdef CLIENT_DIRECTORY
- lib_directory = CLIENT_DIRECTORY;
- #else
- lib_directory = LIB_DIRECTORY;
- #endif
-
- #ifdef MASTER_DIRECTORY
- master_directory = MASTER_DIRECTORY;
- #else
- master_directory = lib_directory;
- #endif
-
- #ifdef HELP_DIRECTORY
- help_directory = HELP_DIRECTORY;
- #else
- help_directory = mk_file_name(lib_directory, "help");
- #endif
-
- #ifdef LOG_FILE
- log_file = LOG_FILE;
- #else
- log_file = mk_file_name(lib_directory, "Log");
- #endif
-
- if (who_am_i == I_AM_MASTER || who_am_i == I_AM_SPEW)
- return 0;
-
- signal(SIGINT, catch_keyboard);
- signal(SIGQUIT, catch_keyboard);
- #ifdef HAVE_JOBCONTROL
- signal(SIGTSTP, catch_suspend);
- #endif
-
- if ((home_directory = getenv("HOME")) == NULL)
- user_error("No HOME environment variable");
-
- if ((pager = getenv("PAGER")) == NULL)
- pager = DEFAULT_PAGER;
-
- nn_directory = mk_file_name(home_directory, ".nn");
-
- if (who_am_i != I_AM_ADMIN && !file_exist(nn_directory, "drwx")) {
- if (who_am_i != I_AM_NN) return -1;
- if (mkdir(nn_directory, 0755) < 0)
- user_error("Cannot create %s directory", nn_directory);
- return 1;
- }
-
- return 0;
- }
-
- new_temp_file()
- {
- static char buf[FILENAME];
- static char *temp_dir = NULL;
-
- if (temp_dir == NULL)
- if ((temp_dir = getenv("TMPDIR")) == NULL)
- temp_dir = tmp_directory; /* just to make test above false */
- else
- tmp_directory = temp_dir;
-
- sprintf(buf, "%s/nn.XXXXXX", tmp_directory);
- mktemp(buf);
- temp_file = buf;
- }
-
-
- FILE *open_file(name, mode)
- char *name;
- int mode;
- {
- FILE *f;
- int fd;
- extern int errno;
-
- if ((mode & DONT_CREATE) && !file_exist(name, (char *)NULL))
- return NULL;
-
- switch (mode & 0x0f) {
-
- case OPEN_READ:
-
- f = fopen(name, "r");
- break;
-
- case OPEN_UPDATE:
-
- /* f = fopen(name, "r+"); -- not reliable on many systems (sigh) */
-
- if ((fd = open(name, O_WRONLY)) >= 0) {
- if ((f = fdopen(fd, "w")) != NULL) return f;
- close(fd);
- }
-
- /* fall thru */
-
- case OPEN_CREATE:
-
- f = fopen(name, "w");
- break;
-
- case OPEN_APPEND:
-
- f = fopen(name, "a");
- break;
-
- case OPEN_CREATE_RW:
-
- f = fopen(name, "w+"); /* not safe on all systems -- beware */
- break;
-
- default:
-
- sys_error("Illegal mode: open_file(%s, 0x%x)", name, mode);
- }
-
- if (f) {
- if (mode & OPEN_UNLINK) unlink(name);
- return f;
- }
-
- if ((mode & MUST_EXIST) == 0) return NULL;
-
- sys_error("Cannot open file %s, mode=0x%x, errno=%d", name, mode, errno);
-
- return NULL;
- }
-
-
-
-
- /*
- * relative -- concat directory name and file name
- */
-
- char *relative(dir, name)
- char *dir, *name;
- {
- static char concat_path[FILENAME];
-
- sprintf(concat_path, "%s/%s", dir, name);
- return concat_path;
- }
-
-
- char *mk_file_name(dir, name)
- char *dir, *name;
- {
- char *buf;
-
- buf = newstr(strlen(dir) + strlen(name) + 2);
- sprintf(buf, "%s/%s", dir, name);
-
- return buf;
- }
-
-
- char *home_relative(dir)
- char *dir;
- {
- if (dir) {
- if (*dir == '/')
- return copy_str(dir);
- else {
- if (*dir == '~' && *++dir == '/') dir++;
- return mk_file_name(home_directory, dir);
- }
- }
- return NULL;
- }
-
-
- char *copy_str(str)
- char *str;
- {
- char *new;
-
- new = newstr(strlen(str) + 1);
- if (new) strcpy(new, str);
-
- return new;
- }
-
- time_t m_time(f)
- FILE *f;
- {
- struct stat st;
-
- if (fstat(fileno(f), &st) < 0) return 0;
- return st.st_mtime;
- }
-
-
- time_t file_exist(name, mode)
- char *name;
- char *mode;
- {
- struct stat statb;
- extern int errno;
-
- if (stat(name, &statb)) return 0;
-
- if (mode == NULL) return statb.st_mtime;
-
- while (*mode) {
- switch (*mode++) {
- case 'd':
- if ((statb.st_mode & S_IFMT) == S_IFDIR) continue;
- errno = ENOTDIR;
- return 0;
- case 'f':
- if ((statb.st_mode & S_IFMT) == S_IFREG) continue;
- if ((statb.st_mode & S_IFMT) == 0000000) continue;
- if ((statb.st_mode & S_IFMT) == S_IFDIR) {
- errno = EISDIR;
- return 0;
- }
- break;
- case 'r':
- if ((statb.st_mode & 0400) && statb.st_uid == user_id) continue;
- if ((statb.st_mode & 0040) && group_access(statb.st_gid)) continue;
- if ((statb.st_mode & 0004)) continue;
- break;
- case 'w':
- if ((statb.st_mode & 0200) && statb.st_uid == user_id) continue;
- if ((statb.st_mode & 0020) && group_access(statb.st_gid)) continue;
- if ((statb.st_mode & 0002)) continue;
- break;
- case 'x':
- if ((statb.st_mode & 0100) && statb.st_uid == user_id) continue;
- if ((statb.st_mode & 0010) && group_access(statb.st_gid)) continue;
- if ((statb.st_mode & 0001)) continue;
- break;
- }
- errno = EACCES;
- return 0;
- }
-
- /* all modes are ok */
- return statb.st_mtime;
- }
-
-
- #ifdef HAVE_SYSLOG
- #include <syslog.h>
- #endif /* HAVE_SYSLOG */
-
-
- static enter_log(type, va_tail)
- char type;
- va_tdcl
- {
- FILE *log;
- char *msg, buf[512];
-
- if (log_entry_filter != NULL)
- for (msg = log_entry_filter; *msg; msg++)
- if (*msg == type) return 1;
-
- msg = va_arg1(char *);
- vsprintf(buf, msg, va_args2toN);
-
- /* cannot use relative: one of the args may be generated by it */
-
- log = open_file(log_file, OPEN_APPEND);
- if (log == NULL) return 0;
-
- fprintf(log, "%c: %s (%s): %s\n", type,
- date_time((time_t)0), user_name(), buf);
-
- fclose(log);
- return 1;
- }
-
- /*VARARGS*/
- sys_error(va_alist)
- va_dcl
- {
- char buf[512];
- char *fmt;
- FILE *f;
- use_vararg;
-
- start_vararg;
- enter_log('E', va_args1toN);
- end_vararg;
-
- start_vararg;
- fmt = va_arg1(char *);
- vsprintf(buf, fmt, va_args2toN);
- end_vararg;
-
- if (who_am_i == I_AM_MASTER) {
- if (dont_write_console) nn_exit(7);
- #ifndef HAVE_SYSLOG
- f = open_file("/dev/console", OPEN_CREATE);
- if (f == NULL) nn_exit(8);
- fprintf(f, "\n\rNNMASTER FATAL ERROR\n\r%s\n\n\r", buf);
- fclose(f);
- #else /* HAVE_SYSLOG */
- openlog("nnmaster", LOG_CONS, LOG_DAEMON);
- syslog(LOG_ALERT, "%s", buf);
- closelog();
- #endif /* HAVE_SYSLOG */
- nn_exit(7);
- }
- user_error("%s", buf);
- }
-
- /*VARARGS*/
- log_entry(va_alist)
- va_dcl
- {
- int type, rval;
- use_vararg;
-
- start_vararg;
- type = va_arg1(int);
- rval = enter_log(type, va_args2toN);
- end_vararg;
-
- return rval;
- }
-
- char *user_name()
- {
- static char *user = NULL;
- struct passwd *pw, *getpwuid();
-
- if (who_am_i == I_AM_MASTER) return "M";
- if (who_am_i == I_AM_EXPIRE) return "X";
-
- if (user == NULL) {
- pw = getpwuid((int)user_id);
- if (pw == NULL) user = "?";
- user = copy_str(pw->pw_name);
- }
-
- return user;
- }
-
- time_t cur_time()
- {
- time_t t;
-
- time(&t);
- return t;
- }
-
- char *date_time(t)
- time_t t;
- {
- char *str;
-
- if (t == (time_t)0) t = cur_time();
- str = ctime(&t);
-
- str[16] = 0;
- return str+4;
- }
-
- char *plural(n)
- long n;
- {
- return n != 1 ? "s" : "";
- }
-
- /*
- * memory management
- */
-
- /* #define MEM_DEBUG /* trace memory usage */
-
- static mem_error(t, bytes)
- int t;
- int32 bytes;
- {
- char buf[200];
-
- if (t == 1) {
- sprintf(buf, "Alloc failed: unsigned too short to represent %ld bytes",
- (long)bytes);
- } else {
- sprintf(buf, "Out of memory - cannot allocate %ld bytes",
- (long)bytes);
- }
-
- sys_error(buf);
- }
-
- char *mem_obj(size, nelt)
- unsigned size;
- int32 nelt;
- {
- unsigned n;
- char *obj, *calloc();
-
- n = nelt;
- if (n != nelt) mem_error(1, nelt);
-
- obj = calloc(n, size);
- #ifdef MEM_DEBUG
- printf("CALLOC(%u,%u) => %lx\n", n, size, (long)obj);
- #endif
- if (obj == NULL) mem_error(2, (int32)(size * nelt));
- return obj;
- }
-
- char *mem_str(nelt)
- int32 nelt;
- {
- unsigned n;
- char *obj, *malloc();
-
- n = nelt;
- if (n != nelt) mem_error(1, nelt);
-
- obj = malloc(n);
- #ifdef MEM_DEBUG
- printf("MALLOC(%u) => %lx\n", n, (long)obj);
- #endif
- if (obj == NULL) mem_error(2, nelt);
- return obj;
- }
-
- char *mem_resize(obj, size, nelt)
- char *obj;
- unsigned size;
- int32 nelt;
- {
- unsigned n;
- char *realloc(), *obj1;
-
- if (obj == NULL)
- return mem_obj(size, nelt);
-
- nelt *= size;
-
- n = nelt;
- if (n != nelt) mem_error(1, nelt);
-
- obj1 = realloc(obj, n);
- #ifdef MEM_DEBUG
- printf("REALLOC(%lx, %u) => %lx\n", (long)obj, n, (long)obj1);
- #endif
- if (obj1 == NULL) mem_error(2, (int32)size);
- return obj1;
- }
-
- mem_free(obj)
- char *obj;
- {
- #ifdef MEM_DEBUG
- printf("FREE(%lx)\n", (long)obj);
- #endif
- if (obj != NULL) free(obj);
- }
-
- #ifndef HAVE_MKDIR
-
- mkdir(path, mode)
- char *path;
- int mode;
- {
- char command[FILENAME*2 + 20];
-
- sprintf(command, "{ mkdir %s && chmod %o %s ; } > /dev/null 2>&1",
- path, mode, path);
- return system(command) != 0 ? -1 : 0;
- }
- #endif
-