home *** CD-ROM | disk | FTP | other *** search
- /*
- * (c) Copyright 1990, Kim Fabricius Storm. All rights reserved.
- *
- * Master/slave communication and locking.
- */
-
- #include "config.h"
- #include <signal.h>
- #include <errno.h>
- #include <pwd.h>
- #include "proto.h"
-
- import char *master_directory, *db_directory;
-
- /*
- * When setting a lock, we must check a little later that
- * we really got the lock set, i.e. that another process
- * didn't set it at the same time!
- */
-
- #define LOCK_SAFETY 5 /* seconds */
-
- /*
- * proto_lock(program, mode)
- *
- * Returns:
- * -1 Not running.
- * 0 Running, no permission (PL_WAKEUP_SOFT)
- * 0 Lock set (PL_SET)
- * 1 Lock not set (PL_SET) (another is running)
- * 1 Locked and running (PL_WAKEUP)
- * pid Locked and running (PL_CHECK)
- */
-
- proto_lock(prog, command)
- {
- FILE *m_pid;
- int try, pid;
- char buf[10], *any, *lock;
-
- switch (prog) {
- case I_AM_MASTER:
- case I_AM_EXPIRE:
- lock = relative(master_directory, "MPID");
- break;
- case I_AM_SPEW:
- lock = relative(master_directory, "WPID");
- break;
- #ifdef ACCOUNTING
- case I_AM_ACCT:
- lock = relative(db_directory, "LCK..acct");
- break;
- #endif
- case I_AM_NN:
- lock = relative(nn_directory, "LOCK");
- break;
- default:
- sys_error("Invalid LOCK prog");
- }
-
- if (command == PL_TRANSFER) {
- m_pid = open_file(lock, OPEN_UPDATE|MUST_EXIST);
- fprintf(m_pid, "%d\n", process_id);
- fclose(m_pid);
- return 1;
- }
-
- if (command == PL_CLEAR)
- goto rm_lock;
-
- try = 1;
- again:
-
- m_pid = open_file(lock, OPEN_READ);
- if (m_pid == NULL) goto no_lock;
- any = fgets(buf, 10, m_pid);
- fclose(m_pid);
-
- if (any == NULL || (pid = atoi(buf)) <= 2) {
- /* lock file is corrupted! */
- if (who_am_i == I_AM_NN) goto rm_lock;
- if (--try < 0) goto rm_lock;
- sleep(LOCK_SAFETY); /* maybe it is being written */
- goto again;
- }
-
- if (kill(pid, command == PL_TERMINATE ? SIGHUP : SIGALRM) == 0) {
- switch (command) {
- case PL_SET_QUICK:
- sleep(1);
- goto again;
-
- case PL_SET_WAIT:
- case PL_CLEAR_WAIT:
- sleep(30);
- goto again;
-
- case PL_CHECK:
- return pid;
-
- default:
- return 1;
- }
- }
-
- if (command == PL_CHECK)
- return (errno == EPERM) ? pid : -1;
- if (command == PL_WAKEUP_SOFT)
- return (errno == EPERM) ? 0 : -1;
-
- /* lock file contains a non-existing process, or a process with */
- /* wrong owner, ie. neither master or expire, so remove it */
-
- rm_lock:
- unlink(lock);
-
- no_lock:
- if (command != PL_SET && command != PL_SET_QUICK && command != PL_SET_WAIT)
- return -1;
-
- m_pid = open_file(lock, OPEN_CREATE);
- if (m_pid == NULL) return 1; /* failed to lock (permission?) */
- fprintf(m_pid, "%d\n", process_id);
- fclose(m_pid);
-
- /* a user will not start nn twice at the exact same time! */
- if (who_am_i == I_AM_NN || command == PL_SET_QUICK) return 0;
-
- sleep(LOCK_SAFETY);
-
- m_pid = open_file(lock, OPEN_READ);
- if (m_pid == NULL) return 1; /* somebody stole the lock file */
- any = fgets(buf, 10, m_pid);
- fclose(m_pid);
-
- if (any == NULL || atoi(buf) != process_id) return 1;
-
- return 0; /* lock is set */
- }
-
- send_master(command, gh, opt, arg)
- char command;
- group_header *gh;
- char opt;
- long arg;
- {
- FILE *gate;
-
- gate = open_file(relative(master_directory, "GATE"), OPEN_APPEND);
-
- if (gate == NULL) {
- printf("Cannot send to master (check GATE file)\n");
- return;
- }
-
- fprintf(gate, "%c;%ld;%c;%ld;%s %s;\n",
- command, gh == NULL ? -1L : gh->group_num, opt, arg,
- user_name(), date_time((time_t)0));
-
- fclose(gate);
-
- log_entry('A', "SEND %c %s %c %ld",
- command, gh == NULL ? "(all)" : gh->group_name, opt, arg);
-
- if (who_am_i == I_AM_ADMIN)
- proto_lock(I_AM_MASTER, PL_WAKEUP_SOFT);
- }
-
-