home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume22 / nn6.4 / part19 / proto.c < prev   
Encoding:
C/C++ Source or Header  |  1990-06-07  |  3.6 KB  |  169 lines

  1. /*
  2.  *    (c) Copyright 1990, Kim Fabricius Storm.  All rights reserved.
  3.  *
  4.  *    Master/slave communication and locking.
  5.  */
  6.  
  7. #include "config.h"
  8. #include <signal.h>
  9. #include <errno.h>
  10. #include <pwd.h>
  11. #include "proto.h"
  12.  
  13. import char *master_directory, *db_directory;
  14.  
  15. /*
  16.  *    When setting a lock, we must check a little later that
  17.  *    we really got the lock set, i.e. that another process
  18.  *    didn't set it at the same time!
  19.  */
  20.  
  21. #define LOCK_SAFETY    5    /* seconds */
  22.  
  23. /*
  24.  *    proto_lock(program, mode)
  25.  *
  26.  *    Returns:
  27.  *    -1    Not running.
  28.  *    0    Running, no permission (PL_WAKEUP_SOFT)
  29.  *    0    Lock set (PL_SET)
  30.  *    1    Lock not set (PL_SET)  (another is running)
  31.  *    1       Locked and running (PL_WAKEUP)
  32.  *    pid    Locked and running (PL_CHECK)
  33.  */
  34.  
  35. proto_lock(prog, command)
  36. {
  37.     FILE *m_pid;
  38.     int try, pid;
  39.     char buf[10], *any, *lock;
  40.  
  41.     switch (prog) {
  42.      case I_AM_MASTER:
  43.      case I_AM_EXPIRE:
  44.     lock = relative(master_directory, "MPID");
  45.     break;
  46.      case I_AM_SPEW:
  47.     lock = relative(master_directory, "WPID");
  48.     break;
  49. #ifdef ACCOUNTING
  50.      case I_AM_ACCT:
  51.     lock = relative(db_directory, "LCK..acct");
  52.     break;
  53. #endif
  54.      case I_AM_NN:
  55.     lock = relative(nn_directory, "LOCK");
  56.     break;
  57.      default:
  58.     sys_error("Invalid LOCK prog");
  59.     }
  60.  
  61.     if (command == PL_TRANSFER) {
  62.     m_pid = open_file(lock, OPEN_UPDATE|MUST_EXIST);
  63.     fprintf(m_pid, "%d\n", process_id);
  64.     fclose(m_pid);
  65.     return 1;
  66.     }
  67.  
  68.     if (command == PL_CLEAR)
  69.     goto rm_lock;
  70.  
  71.     try = 1;
  72.  again:
  73.  
  74.     m_pid = open_file(lock, OPEN_READ);
  75.     if (m_pid == NULL) goto no_lock;
  76.     any = fgets(buf, 10, m_pid);
  77.     fclose(m_pid);
  78.  
  79.     if (any == NULL || (pid = atoi(buf)) <= 2) {
  80.     /* lock file is corrupted! */
  81.     if (who_am_i == I_AM_NN) goto rm_lock;
  82.     if (--try < 0) goto rm_lock;
  83.     sleep(LOCK_SAFETY);    /* maybe it is being written */
  84.     goto again;
  85.     }
  86.  
  87.     if (kill(pid, command == PL_TERMINATE ? SIGHUP : SIGALRM) == 0) {
  88.     switch (command) {
  89.      case PL_SET_QUICK:
  90.         sleep(1);
  91.         goto again;
  92.  
  93.      case PL_SET_WAIT:
  94.      case PL_CLEAR_WAIT:
  95.         sleep(30);
  96.         goto again;
  97.  
  98.      case PL_CHECK:
  99.         return pid;
  100.  
  101.      default:
  102.         return 1;
  103.     }
  104.     }
  105.  
  106.     if (command == PL_CHECK)
  107.     return (errno == EPERM) ? pid : -1;
  108.     if (command == PL_WAKEUP_SOFT)
  109.     return (errno == EPERM) ? 0 : -1;
  110.  
  111.     /* lock file contains a non-existing process, or a process with */
  112.     /* wrong owner, ie. neither master or expire, so remove it */
  113.  
  114.  rm_lock:
  115.     unlink(lock);
  116.  
  117.  no_lock:
  118.     if (command != PL_SET && command != PL_SET_QUICK && command != PL_SET_WAIT)
  119.     return -1;
  120.  
  121.     m_pid = open_file(lock, OPEN_CREATE);
  122.     if (m_pid == NULL) return 1;    /* failed to lock (permission?) */
  123.     fprintf(m_pid, "%d\n", process_id);
  124.     fclose(m_pid);
  125.  
  126.     /* a user will not start nn twice at the exact same time! */
  127.     if (who_am_i == I_AM_NN || command == PL_SET_QUICK) return 0;
  128.  
  129.     sleep(LOCK_SAFETY);
  130.  
  131.     m_pid = open_file(lock, OPEN_READ);
  132.     if (m_pid == NULL) return 1; /* somebody stole the lock file */
  133.     any = fgets(buf, 10, m_pid);
  134.     fclose(m_pid);
  135.  
  136.     if (any == NULL || atoi(buf) != process_id) return 1;
  137.  
  138.     return 0;    /* lock is set */
  139. }
  140.  
  141. send_master(command, gh, opt, arg)
  142. char command;
  143. group_header *gh;
  144. char opt;
  145. long arg;
  146. {
  147.     FILE *gate;
  148.  
  149.     gate = open_file(relative(master_directory, "GATE"), OPEN_APPEND);
  150.  
  151.     if (gate == NULL) {
  152.     printf("Cannot send to master (check GATE file)\n");
  153.     return;
  154.     }
  155.  
  156.     fprintf(gate, "%c;%ld;%c;%ld;%s %s;\n",
  157.         command, gh == NULL ? -1L : gh->group_num, opt, arg,
  158.         user_name(), date_time((time_t)0));
  159.  
  160.     fclose(gate);
  161.  
  162.     log_entry('A', "SEND %c %s %c %ld",
  163.           command, gh == NULL ? "(all)" : gh->group_name, opt, arg);
  164.  
  165.     if (who_am_i == I_AM_ADMIN)
  166.     proto_lock(I_AM_MASTER, PL_WAKEUP_SOFT);
  167. }
  168.  
  169.