This is proto.c in view mode; [Download] [Up]
/* * (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" #ifndef ACCOUNTING #ifdef AUTHORIZE #define ACCOUNTING #endif #endif import char *master_directory, *db_directory; #define HOSTBUF 80 export char proto_host[HOSTBUF]; /* host having the lock */ /* * 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) */ static write_lock(lock, operation) char *lock, *operation; { FILE *m_pid; char host[HOSTBUF]; m_pid = open_file(lock, OPEN_CREATE); if (m_pid == NULL) sys_error("Cannot %s lock file: %s", operation, lock); gethostname(host, HOSTBUF); fprintf(m_pid, "%d\n%s\n", process_id, host); fclose(m_pid); } static int read_lock(lock) char *lock; { FILE *m_pid; char host[HOSTBUF]; char pid[10]; pid[0] = NUL; proto_host[0] = NUL; m_pid = open_file(lock, OPEN_READ); if (m_pid == NULL) return -2; /* no lock */ fgets(pid, 10, m_pid); fgets(proto_host, HOSTBUF, m_pid); fclose(m_pid); if (pid[0] == NUL) return 0; /* corrupted lock */ if (proto_host[0] != NUL) { substchr(proto_host, NL, NUL); gethostname(host, HOSTBUF); if (strncmp(proto_host, host, HOSTBUF) != 0) return -1; /* locked by another host */ proto_host[0] = NUL; } return atoi(pid); } 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) { write_lock(lock, "transfer"); return 1; } if (command == PL_CLEAR) goto rm_lock; try = 1; again: switch (pid = read_lock(lock)) { case -2: goto no_lock; case -1: /* wrong host */ return 1; case 0: case 1: case 2: /* corrupted lock file */ 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; default: break; } 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; write_lock(lock, "create"); /* 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); if (read_lock(lock) != process_id) return 1; /* somebody stole the lock file */ return 0; /* lock is set */ } FILE *open_gate_file(mode) int mode; { char *gate, *err; FILE *gf; gate = relative(master_directory, "GATE"); gf = open_file(gate, mode); err = NULL; switch (mode) { case OPEN_READ: if (gf != NULL) { if (unlink(gate) == 0) break; err = "unlink"; break; } if (errno != ENOENT) err = "read"; break; default: if (gf != NULL) chmod(gate, 0644); /* override restrictive umask */ /* caller must complain if cannot open! */ break; } if (err != NULL) { sys_warning("Cannot %s %s (err=%d). Check modes!!", err, gate, errno); if (gf != NULL) fclose(gf); return NULL; } return gf; } send_master(command, gh, opt, arg) char command; group_header *gh; char opt; long arg; { FILE *gate; gate = open_gate_file(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); }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.