home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume14 / sharedmem / part03 < prev    next >
Encoding:
Internet Message Format  |  1988-05-17  |  45.9 KB

  1. Subject:  v14i096:  Shared memory emulation for 4.2BSD, Part03/04
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rsalz@uunet.UU.NET
  5.  
  6. Submitted-by: libes@cme-durer.ARPA (Don Libes)
  7. Posting-number: Volume 14, Issue 96
  8. Archive-name: sharedmem/part03
  9.  
  10. #! /bin/sh
  11. # This is a shell archive.  Remove anything before this line, then unpack
  12. # it by saving it into a file and typing "sh file".  To overwrite existing
  13. # files, type "sh file -c".  You can also feed this as standard input via
  14. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  15. # will see the following message at the end:
  16. #        "End of archive 3 (of 4)."
  17. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  18. if test -f 'doc/usenix/abstract.trf' -a "${1}" != "-c" ; then 
  19.   echo shar: Will not clobber existing file \"'doc/usenix/abstract.trf'\"
  20. else
  21. echo shar: Extracting \"'doc/usenix/abstract.trf'\" \(6265 characters\)
  22. sed "s/^X//" >'doc/usenix/abstract.trf' <<'END_OF_FILE'
  23. X.RP
  24. X.TL
  25. XUser-Level Shared Variables (in a Hierarchical Control Environment)
  26. X.AU
  27. XDon Libes
  28. X.AI
  29. XFactory Automation Systems Division
  30. XNational Bureau of Standards
  31. XGaithersburg, MD  20899
  32. X.PP
  33. XWe have implemented a shared variable system for UNIX 4.2 that emulates a
  34. Xshared or common memory.
  35. X.IP \(bu
  36. XShared variables provide an alternate style of communications
  37. Xto message passing or pipes.  
  38. X.IP \(bu
  39. XThis system is all user level code and requires no kernel
  40. Xmodifications.  It is accessible from a variety of languages.
  41. X.IP \(bu
  42. XWe are using this system in a real application - an automated
  43. Xfactory.
  44. X.PP
  45. X.SH
  46. XI   User View
  47. X.PP
  48. XA server, the Common Memory Manager (CMM), acts on requests to access shared
  49. Xvariables.  Typical requests are read, write, and declare.  Variables are
  50. Xstructured and have attributes such as type, protection, lifetime, and
  51. Xownership.  Variable type checking is performed at runtime startup, since
  52. Xprocesses are loosely connected.
  53. X.PP
  54. XSome of the more interesting attributes of these shared variables are:
  55. X.PP
  56. X.I
  57. Xlifetime and "shelf life".
  58. X.R
  59. XIn a real time environment, the system must
  60. Xsurvive a process dying or getting bogged down temporarily.  When the useful
  61. Xlifetime of a variable's value has expired, other processes are free to
  62. Xmanipulate the variable, for instance, by redeclaring or writing it.  This
  63. Xattribute allows a "god" process to notice unexpected process deaths and
  64. Xrestart processes or transfer control to other processes.   For less
  65. Xcritical variables (such as an infrequently updated sensor value), processes
  66. Xmight note a "stale" value, and make a projection that will carry them over
  67. Xuntil the variable writer catches up to its duties.
  68. X.PP
  69. X.I
  70. Xwrite count, timestamp, authorstamp.
  71. X.R
  72. XBy marking each variable with how many
  73. Xtimes or when it has been written, handshaking can be performed for the
  74. Xusers.  The archetypal example from the automation environment is the
  75. Xcommand "hit nail with hammer".  If the supervisor runs more quickly than
  76. Xthe subordinate, without handshaking, the subordinate may never see the
  77. Xcommand (i.e. nail is not hit).  If the subordinate runs more quickly than
  78. Xthe supervisor, without handshaking, the subordinate may execute the same
  79. Xcommand twice (i.e. nail is hit more than once)
  80. X.PP
  81. X.I
  82. Xwakeup.
  83. X.R
  84. XVariables can be marked with a list of processes to be notified upon
  85. Xvalue change.  This was originally added for efficiency, so that servers,
  86. Xfor example, would not have to loop just waiting for new values.  It has
  87. Xturned out to be extremely useful for debugging.  Rather than inserting
  88. Xprintf statements in existing code and recompiling, it is possible to create
  89. Xa debug module that simply prints out variables when they change.  We have
  90. Xalso used it for a graphics monitor that continuously displays the state of
  91. Xthe entire system.  This wakeup attribute forces a queuing discipline on a
  92. Xvariable.
  93. X.PP
  94. X.I
  95. Xnon-exclusive write.
  96. X.R
  97. XVariables can be declared read or write, exclusively or
  98. Xnonexclusively.  By default, writes are exclusive, meaning that only one
  99. Xprocess can write a variable during its lifetime.  Non-exclusive write has
  100. Xno such restriction, allowing multiple processes to write the same variable.
  101. XOne use of this might be a server listening on a socket.  Any client can
  102. Xrequest service by writing the variable associated with the socket.  Another
  103. Xuse is to allow a debug process to insert a new value without modifying the
  104. Xvariable's normal writer.
  105. X.PP
  106. X.SH
  107. XII   4.2BSD Implementation
  108. X.PP
  109. XThe Shared Variable System consists of three layers.  The lowest level
  110. Xsimulates a common memory facility such as is available in System V.  On top
  111. Xof this are the procedures that transform common memory into common
  112. Xvariables.  Above this is another level that provides handshaking, if
  113. Xnecessary.  All levels run as user-level code and require no kernel
  114. Xmodifications.
  115. X.PP
  116. X4.2BSD has no common memory facility.  Our system provides one via a
  117. Xuser-level server that stores variables in its own memory space which is
  118. Xprivate to it.  Access to variables is therefore strictly through the valid
  119. Xrequests to the CMM server.
  120. X.PP
  121. XClient processes keep their own local version of the common variables until
  122. Xit is convenient for them to synchronize with the CMM.  By calling
  123. X.I cm_sync() ,
  124. Xthe user and the common memory server become synchronized.  This
  125. Xcall is noninterruptible for the CMM since the server completely processes
  126. Xrequests in the order that they are received.
  127. X.PP
  128. XThe Shared Variables System is written in C and uses the 4.2 interprocess
  129. Xcommunication system.  Thus, the common memory as well as the clients can be
  130. Xdistributed.  An interface exists for Franz Lisp.
  131. X.PP
  132. X.SH
  133. XIII   An application - manufacturing automation
  134. X.PP
  135. XWhile the CMM is a general tool, it is currently being used at the National
  136. XBureau of Standards in the Automated Manufacturing Research Facility, a
  137. Xproject in manufacturing automation.  This project requires communication
  138. Xbetween stationary and mobile robots, machine tools, their controllers, and
  139. Xhigher-level cell and factory management computers.  The processes are
  140. Xorganized in a control hierarchy, much like the organization of a
  141. Xconventional factory.
  142. X.PP
  143. XFor the purposes of hierarchical control, one can imagine that processes in
  144. Xthe system communicate along hierarchical channels.  Each process runs
  145. Xasynchronously, communicating only with its superior and subordinate
  146. Xprocesses.
  147. X.PP
  148. XLogically however, communication is performed using the common memory model.
  149. XFor example, a process sending commands to a subordinate writes the
  150. Xinformation in a well-known common memory variable.  The subordinate reads
  151. Xthe information out of the common memory variable, noting whether or not it
  152. Xcontains a new value.
  153. X.PP
  154. XIn reality, there are small groups of processes and processors that directly
  155. Xcommunicate with each other, some using physical common memory and some
  156. Xsimulating common memory.  Each cluster representing a piece of common
  157. Xmemory can choose to replicate any other portion of another cluster's common
  158. Xmemory.  An underlying network invisibly supplies this service of keeping
  159. Xall the common memories synchronized.  The result is effectively one of a
  160. Xconsolidated common memory, with a very consistent and easy means of
  161. Xcommunication between processes.
  162. END_OF_FILE
  163. if test 6265 -ne `wc -c <'doc/usenix/abstract.trf'`; then
  164.     echo shar: \"'doc/usenix/abstract.trf'\" unpacked with wrong size!
  165. fi
  166. # end of 'doc/usenix/abstract.trf'
  167. fi
  168. if test -f 'src/cm_usr1.c' -a "${1}" != "-c" ; then 
  169.   echo shar: Will not clobber existing file \"'src/cm_usr1.c'\"
  170. else
  171. echo shar: Extracting \"'src/cm_usr1.c'\" \(8111 characters\)
  172. sed "s/^X//" >'src/cm_usr1.c' <<'END_OF_FILE'
  173. X/*
  174. X
  175. XThese are the user functions uses in manipulating common memory variables.
  176. XThe primary functions are:
  177. X
  178. Xcm_init(process_name,host,debug_level)
  179. Xcm_declare(name,type,role,period)
  180. Xcm_undeclare(variable)
  181. Xcm_sync(wait)
  182. Xcm_exit()
  183. X*/
  184. X
  185. X/* real code begins here */
  186. X
  187. X#include <stdio.h>
  188. X#include <sys/types.h>
  189. X#include <sys/time.h>
  190. X#include <sys/socket.h>
  191. X#include <netinet/in.h>
  192. X#include <strings.h>
  193. X#include <sys/file.h>    /* for open(/dev/null) hack */
  194. X#include "inet.h"
  195. X
  196. X#include "cm_constants.h"
  197. X#include "cm_sd.h"
  198. X#include "cm_var.h"
  199. X#include "cm_interface.h"
  200. X#include "cm_sync.h"
  201. X#include "cm_slot.h"
  202. X#include "cm_msg.h"
  203. X#include "cm_time.h"
  204. X
  205. Xextern int errno;
  206. X
  207. Xstatic struct msg *omsg, *imsg;
  208. X
  209. Xint server_socket;
  210. Xint maxfds;
  211. X
  212. Xint cm_init();
  213. Xcm_variable *cm_declare();
  214. Xcm_variable *firstuservar(), *nextuservar();
  215. Xcm_write();
  216. Xstruct user_variable *cm_read();
  217. Xcm_sync();
  218. Xstruct slot *nextslot();
  219. Xcm_variable *get_variable();
  220. X
  221. Xchar *malloc();
  222. Xstatic composemsg();
  223. X
  224. X/* real definitions begin here */
  225. X
  226. Xint
  227. Xcm_init(name,host,debug_level)
  228. Xchar *name;
  229. Xchar *host;    /* host running cmm.  0 or "" means local host */
  230. Xint debug_level;
  231. X{
  232. X    set_cm_debug_level(debug_level);
  233. X    set_cm_process_name(name);
  234. X    if (0 > (server_socket = initport(PORT_NUMBER(CM_PORT),CLIENT,
  235. X            SOCK_STREAM,host))) return(E_CM_INIT_FAILED);
  236. X
  237. X    maxfds = getdtablesize();
  238. X    cm_time_init();
  239. X
  240. X    if (!(imsg = (struct msg *)malloc(CM_MSGSIZE))) {
  241. X        fprintf(stderr,"init: failed malloc(imsg)\n");
  242. X        exit(-1);
  243. X    }
  244. X    if (!(omsg = (struct msg *)malloc(CM_MSGSIZE))) {
  245. X        fprintf(stderr,"init: failed malloc(omsg)\n");
  246. X        exit(-1);
  247. X    }
  248. X    return(0);
  249. X}
  250. X
  251. X/* the following call is important if you plan on restarting cm connections
  252. Xserveral times in one process.  It runs around deallocating memory that has
  253. Xbeen allocated by cm_sd_copy.
  254. X*/
  255. Xcm_exit()
  256. X{
  257. X    cm_variable *v;
  258. X
  259. X    close(server_socket);
  260. X
  261. X    for (v=next_user_variable((struct user_variable *)0);v;
  262. X                    v=next_user_variable(v)) {
  263. X        if (!v->count) continue;    /* never set */
  264. X        cm_sd_free(&v->data);
  265. X    }
  266. X}
  267. X
  268. Xcm_variable *
  269. Xcm_declare(name,role)
  270. Xchar *name;
  271. Xunsigned int role;        /* READER, WRITER, XWRITER, WAKEUP */
  272. X{
  273. X    cm_variable *v;
  274. X
  275. X    if (!(v = get_variable(name))) {
  276. X        fprintf(stderr,"cannot get_variable(%s)\n",name);
  277. X        return(NULL);
  278. X    }
  279. X    if (role) {
  280. X        /* you gave no way to "or out" these bits, you twit! */
  281. X        if (role & CM_ROLE_READER) v->role.reader = TRUE;
  282. X        if (role & CM_ROLE_XWRITER) v->role.xwriter = TRUE;
  283. X        if (role & CM_ROLE_NONXWRITER) v->role.nonxwriter = TRUE;
  284. X        if (role & CM_ROLE_WAKEUP) v->role.wakeup = TRUE;
  285. X    }
  286. X/*    if (cmd_assoc != 0) v->command_association = cmd_assoc;*/
  287. X
  288. X    v->status.declared = TRUE;
  289. X    return(v);
  290. X}
  291. X
  292. Xcm_undeclare(v)
  293. Xcm_variable *v;
  294. X{
  295. X    v->status.undeclared = TRUE;
  296. X}
  297. X
  298. X/* returns negative for failure or 0 for success */
  299. Xcm_sync(wait_opts)
  300. Xint wait_opts;
  301. X{
  302. X    int slots;    /* number of slots in incoming message */
  303. X    int query;    /* TRUE, if we are requesting an ack from the cmm */
  304. X    int rc = 0;
  305. X    int cc;
  306. X    int selector;
  307. X    struct slot *s;
  308. X    int processed_msg = FALSE;    /* true if we have received and
  309. X                       processed at least one msg in
  310. X                       this call to cm_sync */
  311. X
  312. X    if ((0 == message_waiting(server_socket))
  313. X        && (wait_opts & CM_WAIT_READ)) {
  314. X        /* no messages waiting, so provoke the cmm to give us some */
  315. X        query = TRUE;
  316. X    } else query = FALSE;
  317. X
  318. X    composemsg(omsg);
  319. X        if (query) omsg->read_wait = TRUE;
  320. X    if (omsg->slots || query) {
  321. X        print_msg(omsg);
  322. X        cc = sized_write(server_socket,omsg,omsg->size);
  323. X        if (cc != omsg->size) {
  324. X        fprintf(stderr,"%s%s\n","failed to send msg to cmm.  ",
  325. X            "cmm disappeared?");
  326. X        exit(0);
  327. X        }
  328. X        eprintf(2,"sent msg to server (%d)\n",cc);
  329. X    } /* no slots in msg, so no msg not sent to server */
  330. X    while (TRUE) {
  331. X        /* poll first */
  332. X        selector = 1<<server_socket;
  333. X        if (-1 == (cc = message_waiting(server_socket))) {
  334. X        rc = E_CMM_DIED;
  335. X        break;
  336. X        }
  337. X        /* wait rules are as follows:
  338. XWAIT:        WAIT_AT_MOST_ONCE        WAIT_FOR_ALL
  339. Xno msg waiting    select/return            select/return
  340. X   msg waiting    select/return            select/select
  341. X
  342. XNO_WAIT:    WAIT_AT_MOST_ONCE        WAIT_FOR_ALL
  343. Xno msg waiting    return/return            return/return
  344. X   msg waiting    select/return            select/select
  345. X
  346. XWhere x/y means:
  347. XDo x if no messages have been processed in this call to cm_sync, and 
  348. XDo y if at least one message has been processed in this call to cm_sync.
  349. X
  350. XFor example:
  351. XIf user specified NO_WAIT|WAIT_AT_MOST_ONCE, no message is waiting and
  352. Xat least one message has been processed, we return.
  353. X*/
  354. X        /* catagorize by the conditions that return, which are
  355. X               implemented by "break".
  356. X         */
  357. X        if (wait_opts & CM_NO_WAIT) {
  358. X        if (cc == 0) break;    /* no msg waiting */
  359. X        } else if (wait_opts & CM_WAIT_AT_MOST_ONCE) {
  360. X        if (processed_msg) break;
  361. X        } else if (processed_msg && (cc == 0)) break;
  362. X
  363. X        /* That was amazingly simpler to code then to say!!! */
  364. X        
  365. X        /* wait until someone responds */
  366. X        selector = 1<<server_socket;
  367. X        if (-1 == select(maxfds,&selector,(int *)0,(int *)0,
  368. X                        (struct timeval *)NULL)) {
  369. X        rc = E_CMM_DIED;
  370. X        break;
  371. X        } else {
  372. X        if (0 >= (cc = sized_read(server_socket,imsg,CM_MSGSIZE))) {
  373. X            rc = E_CMM_DIED;
  374. X            break;
  375. X        }
  376. X        processed_msg = TRUE;
  377. X        s = imsg->data;
  378. X        print_msg(imsg);
  379. X        if (imsg->version != CMM_VERSION) {
  380. X            if (imsg->version > CMM_VERSION) {
  381. X                fprintf(stderr,"cm library (v%d) is %s than cmm (v%d)",
  382. X                    CMM_VERSION,
  383. X                    ((imsg->version > CMM_VERSION)?"older":"newer"),
  384. X                    imsg->version);
  385. X            }
  386. X            return(E_CM_WRONG_VERSION);
  387. X        }
  388. X
  389. X        slots = imsg->slots;
  390. X        s = imsg->data;
  391. X        for (;;) {
  392. X            if (s == NULL || slots == 0) break;
  393. X            if (0 > user_decode_slot(s)) {
  394. X               printf("bad slot encountered...aborting msg \n");
  395. X               break;
  396. X            }
  397. X            eprintf(6,"slot = %x  ",s);
  398. X            eprintf(6,"slot->name %s  ",s->s_name);
  399. X            eprintf(6,"slot->size %x\n",s->s_size);
  400. X
  401. X            s = nextslot(imsg,s);
  402. X            slots--;
  403. X        }
  404. X        }
  405. X    }
  406. X    return(rc);
  407. X}
  408. X
  409. X/* returns -1 if cmm died, 0 if no message waiting, >0 if message waiting */
  410. Xstatic int
  411. Xmessage_waiting(fd)
  412. Xint fd;
  413. X{
  414. X    int selector = 1<<fd;
  415. X
  416. X    return(select(maxfds,&selector,(int *)0,(int *)0,&cm_period_zero));
  417. X}
  418. X
  419. X/*
  420. Xgo through our variables looking for ones that we have written or declared.
  421. XStuff them all into a buffer and send this message to the cmm.
  422. XBy looking at all variables only once, we get rid of duplicates.  I.e. the
  423. Xuser may have written a value more than once before syncing.
  424. X*/
  425. Xstatic composemsg(m)
  426. Xstruct msg *m;    /* outgoing msg */
  427. X{
  428. X    int size;
  429. X    cm_variable *v;
  430. X
  431. X    init_msg(m);
  432. X
  433. X    for (v=next_user_variable((struct user_variable *)0);v;
  434. X                    v=next_user_variable(v)) {
  435. X        if (v->status.declared) {
  436. X            eprintf(6,"adding declare slot for %s\n",v->name);
  437. X            size = put_slot_declare(m,v->name,
  438. X/*                &v->role,v->command_association); */
  439. X                &v->role,0);
  440. X            if (size > 0) v->status.declared = FALSE;
  441. X        }
  442. X        if (v->status.written) {
  443. X            eprintf(6,"adding write slot for %s\n",v->name);
  444. X            size = put_slot_write(m,v->name,&v->data,
  445. X                v->command_association);
  446. X            if (size > 0) v->status.written = FALSE;
  447. X        }
  448. X        if (v->status.undeclared) {
  449. X            eprintf(6,"adding undeclare slot for %s\n",v->name);
  450. X            size = put_slot_undeclare(m,v->name);
  451. X            if (size > 0) {
  452. X                cm_sd_free(&v->data);
  453. X                v->status.inuse = FALSE;
  454. X            }
  455. X        }
  456. X    }
  457. X#if 0
  458. X    /* this should be last, because when the manager receives it, */
  459. X    /* any current values going into the message queue are zapped. */
  460. X    /* This way, the user will not get any duplicate values. */
  461. X    if (query) put_slot_read(m);
  462. X#endif 
  463. X}
  464. X
  465. Xcm_print_variable(name)
  466. Xchar *name;
  467. X{
  468. X    cm_variable *v;
  469. X
  470. X        if (!(v = get_variable(name))) {
  471. X            fprintf(stderr,"cannot get_variable(%s)\n",name);
  472. X    }
  473. X
  474. X    printf("name = %s\n",v->name);
  475. X    printf("role.reader = %d\n",v->role.reader);
  476. X    printf("role.nonxwriter = %d\n",v->role.nonxwriter);
  477. X    printf("role.wakeup = %d\n",v->role.wakeup);
  478. X    printf("role.xwriter = %d\n",v->role.xwriter);
  479. X    printf("count = %d\n",v->count);
  480. X    printf("cmd assoc = %d\n",v->command_association);
  481. X    printf("status.inuse = %d\n",v->status.inuse);
  482. X    printf("status.written = %d\n",v->status.written);
  483. X    printf("status.declared = %d\n",v->status.declared);
  484. X    printf("status.undeclared = %d\n",v->status.undeclared);
  485. X}
  486. END_OF_FILE
  487. if test 8111 -ne `wc -c <'src/cm_usr1.c'`; then
  488.     echo shar: \"'src/cm_usr1.c'\" unpacked with wrong size!
  489. fi
  490. # end of 'src/cm_usr1.c'
  491. fi
  492. if test -f 'src/franz/config.h' -a "${1}" != "-c" ; then 
  493.   echo shar: Will not clobber existing file \"'src/franz/config.h'\"
  494. else
  495. echo shar: Extracting \"'src/franz/config.h'\" \(16909 characters\)
  496. sed "s/^X//" >'src/franz/config.h' <<'END_OF_FILE'
  497. X/*                                      -[Wed Jun 12 08:00:31 1985 by jkf]-
  498. X *      config.h                        $Locker:  $
  499. X * configuration dependent info
  500. X *
  501. X * $Header: config.h,v 40.37 85/07/21 10:49:29 layer Exp $
  502. X *
  503. X * (c) copyright 1982, Regents of the University of California
  504. X * Enhancements (c) copyright 1984, Franz Inc., Oakland California
  505. X */
  506. X/* 
  507. X * this file contains three types of parameters
  508. X *  1) those parameters which each site may wish to modify to
  509. X *     personalize lisp.
  510. X *  2) those flags which are machine or operating system dependent
  511. X *     and thus which should not be modified.
  512. X *  3) those which should be of type (1) but by the time the customer
  513. X *     has received lisp, the setting of the flag has been hardwired
  514. X *     in.  We are trying to reduce flags of this type, but a few still
  515. X *     exist.
  516. X *
  517. X * In the description of each flag we will note its class from the
  518. X * list above (class 1,2 or 3).
  519. X *
  520. X */
  521. X
  522. X/*
  523. X** The type of machine and os this is to run on will come from
  524. X** the file lconf.h.  
  525. X*/
  526. X# ifndef NoLconf
  527. X#  include "lconf.h"
  528. X# endif
  529. X
  530. X
  531. X/* GCSTRINGS - (class 3)
  532. X *  define this if you want the garbage collector to reclaim
  533. X *  strings.  It is not normally set because in typical applications the
  534. X *  expense of collecting strings is not worth the amount of space
  535. X *  retrieved
  536. X */
  537. X/* #define GCSTRINGS */
  538. X
  539. X/*
  540. X * NAMESIZE (class 1) - size of the internal stack for holding
  541. X * local (non-special) variables.  The size allocated is
  542. X * NAMESIZE + 4*NAMEINC, the stack growing by NAMINC each
  543. X * time it overflows (so that overflows can be handled in lisp).
  544. X * NAMINC is a class 1 constant.
  545. X */
  546. X#define NAMESIZE 3072
  547. X#define NAMINC 50
  548. X
  549. X/*
  550. X * MVR (class 3)  handle multiple value returns
  551. X */
  552. X#define MVR
  553. X#define MMVR 20
  554. X
  555. X/*
  556. X** HASHT (class 3) include the hash table package
  557. X*/
  558. X#define HASHT
  559. X
  560. X/* DOMAIN - (class 3) this is put on the (status features) list and
  561. X *      is the value of (status domain)
  562. X */
  563. X#define DOMAIN  "franz-inc"
  564. X
  565. X/*
  566. X * Machine/os dependent flags:          (class 2)
  567. X * All flags are of the ifdef/ifndef variety.
  568. X * Flags whose names are followed by * must be specified with a value.
  569. X * Some flags have default values, when noted.
  570. X * Only those flags so documented may be changed by the customer
  571. X * The meaning of the flags are as follows
  572. X * machine (choose one):
  573. X *   m_vax      a vax of any type (780,750, etc)
  574. X *   m_68k      a 68000 or 68010
  575. X * os (choose one if in the list, or else omit)
  576. X *   os_vms     dec's vms os
  577. X *   os_masscomp  masscomp's version of 4.2
  578. X *   os_sun4    sun 4bsd or newer
  579. X *   os_unisoft unisoft variant
  580. X * OFFSET*      lowest address (where nil will be stored)
  581. X * TTSIZE*      max number of 512 bytes pages for text and data
  582. X *              !This may be altered!
  583. X * XstackSize   size of alternate stack if SPISFP is defined
  584. X * unisys3botch something is wrong with initialization of data space
  585. X * SPISFP       the stack pointer is also the frame pointer, so we can't
  586. X *              push tempories on the C stack (we have to use an alternate
  587. X *              stack)
  588. X * NPINREG      np and lbot are stored in registers rather than global
  589. X *              variables
  590. X * DefDmpmode*  default dump mode (expressed in octal-like decimal)
  591. X * NILIS0       for any UNIX implementation in which the users
  592. X *              address space starts at 0 (and liszt takes advantage
  593. X *              of the fact)
  594. X * StringTable  when the a.out format uses a string table for symbol
  595. X *              names
  596. X * Vadvise      if system has vadvise system call, this is the location
  597. X *              of the vadvise include file.
  598. X * OS*          name of the operating system for the (status features)
  599. X *              list
  600. X * Pagesize*    the size in bytes of a page of memory. Can be specified
  601. X *              as a function to return the value.
  602. X *
  603. X * Machine*     name of the processor
  604. X * LongFilenames  if this machine has very long filenames
  605. X * Feature      something to be put on the status features list
  606. X * vms_cfasl    for vms, do a cfasl of a native vms object file (i believe)
  607. X * NewLineBuf   if it uses the setlinebuf call to set buffering for stdio
  608. X * RIndexFcn*   function to call to get the location of a given char
  609. X *          from the end of the string.
  610. X * IndexFcn*    function to call to get the location of a given char
  611. X * machine name (choose one):
  612. X *   GetHostname  has the 4.2 gethostname function
  613. X *   os_masscomp  [this was mentioned above] use the masscomp version
  614. X *               of gethostname
  615. X *   SiteName    a string which is the site name, if it must be hardwired
  616. X *               !this may be altered!
  617. X * CallBrkdirect if must do a brk with a system call rather than the
  618. X *               C function.
  619. X * UseSetmask    signals are reenabled with sigsetmask rather than
  620. X *               calling 'signal' again (a 4.2 feature)
  621. X * unisys3botch  has a problem in clearing low memory (mysterious flag
  622. X *               which should be better named)
  623. X * SunCore       has suncore
  624. X * Subxlbotch    operands of subxl exchanged [I'm guessing at this, it
  625. X *               was underdocumented in the code]
  626. X * NoSysTime    <sys/time.h> is <time.h>
  627. X * NoSyscall    doesn't have a syscall function
  628. X * NoAsm    doesn't have the function "asm" to insert assembler into the
  629. X *        output of the C compiler (like the cadmus).
  630. X * AsmOnly    This macro is defined in files which are really
  631. X        assembler files and the C pre-processor is being used.
  632. X        (The purpose is to keep typedef's from being passed
  633. X        to the assembler.)
  634. X * NoGarbColl    Turns off garbage collection permanently.
  635. X        (This is done by making sure that Initflag does not
  636. X        get changed in sysat.c
  637. X *
  638. X * unchar  [default 'unsigned char'] the data type to use for unsigned
  639. X *              character.  This is necessary since some C compilers can't
  640. X *              handle 'unsigned char'.
  641. X * word        An integer type (long, int, or short) whose size is the
  642. X        same as that of a pointer so that casts back and forth
  643. X        to (int *) or (char *) will not lose information.
  644. X * int32    An integer type (long, int, or short) whose size is 
  645. X        32 bits.
  646. X *
  647. X * xor          [ default uses ^] a macro to xor two quantities.  This is
  648. X *              necessary on ibm systems which use the caret for something
  649. X *              else
  650. X * Incl_ctype   [default: defined] if defined then explicitly include
  651. X *              <ctype.h>
  652. X *              
  653. X * IobName      Indicates that a special machine and/or O.S. routine must be
  654. X *              called to determine the locained] has floating point
  655. X * HasTermcap   [default: defined] has interface to termcap
  656. X *   ...        stdio flag conversions:  this should not be here when
  657. X *              we are done moving stdio
  658. X * DefLibDir    default lisp library directory
  659. X * NoLowInput    Indicates that no attempt should be made to interfere with
  660. X *        low level input routine (read). Otherwise, read is
  661. X *        rewritten in 68k.c
  662. X * NoLowOutput  Indicates that no attempt should be made to interfere with
  663. X *        low level output routine (write). Otherwise, write is
  664. X *        rewritten in 68k.c
  665. X * Savelisp    needs the save/restorelisp feature [apollo]
  666. X * UseOnlySdotsForBignums
  667. X *        if defined, use only sdots for constructing bignums.
  668. X *        This is for the apollo, and if Savelisp is defined, then
  669. X *        this also MUST be defined. [apollo]
  670. X * NoDumpLisp    this machine cannot support (dumplisp) [apollo]
  671. X * NoNlist    this machine does not have the UNIX function nlist() [apollo]
  672. X * ReadDir    If defined, uses unix system call to read a directory
  673. X *        listing.
  674. X */
  675. X
  676. X/* defaults */
  677. X
  678. X#define unchar unsigned char
  679. X#define xor(a,b)   (a) ^ (b)
  680. X#define Incl_ctype 
  681. X#define GcTime
  682. X#define HasFloat
  683. X#define HasTermcap
  684. X#define XstackSize 16384
  685. X#define DefLibDir "/usr/lib/lisp"
  686. X
  687. X/*
  688. X** If more machines have weird integer sizes,
  689. X** these typedefs will have to be moved.
  690. X*/
  691. X#ifndef AsmOnly
  692. X#ifdef Elxsi
  693. X    typedef int int32;
  694. X    typedef int word;
  695. X#else
  696. X#ifdef lint
  697. X    typedef int int32;
  698. X    typedef int word;
  699. X#else
  700. X    typedef long int32;
  701. X    typedef long word;
  702. X#endif lint
  703. X#endif Elxsi
  704. X#endif AsmOnly
  705. X
  706. X#ifdef vax_4_1
  707. X# define m_vax
  708. X# define OFFSET 0x0
  709. X# define TTSIZE 6120
  710. X# define NPINREG
  711. X# define DefDmpmode 413
  712. X# define NILIS0
  713. X# define StringTable
  714. X# define Vadvise <vadvise.h>
  715. X# define OS "unix"
  716. X# define Pagesize 1024
  717. X# define Machine "vax"
  718. X# define IndexFcn index
  719. X# define RIndexFcn rindex
  720. X# define SiteName "unknown-site"
  721. X#define nargsdefined
  722. X#define ReadDir
  723. X#endif
  724. X
  725. X#ifdef vax_4_1a
  726. X# define m_vax
  727. X# define OFFSET 0x0
  728. X# define TTSIZE 6120
  729. X# define NPINREG
  730. X# define DefDmpmode 413
  731. X# define NILIS0
  732. X# define StringTable
  733. X# define Vadvise <vadvise.h>
  734. X# define OS "unix"
  735. X# define Pagesize 1024
  736. X# define Machine "vax"
  737. X# define IndexFcn index
  738. X# define RIndexFcn rindex
  739. X# define GetHostname
  740. X#define nargsdefined
  741. X#define ReadDir
  742. X#endif
  743. X
  744. X#ifdef vax_4_1c
  745. X# define m_vax
  746. X# define OFFSET 0x0
  747. X# define TTSIZE 6120
  748. X# define NPINREG
  749. X# define DefDmpmode 413
  750. X# define NILIS0
  751. X# define StringTable
  752. X# define Vadvise <vadvise.h>
  753. X# define OS "unix"
  754. X# define Pagesize getpagesize()
  755. X# define Machine "vax"
  756. X# define LongFilenames
  757. X# define IndexFcn index
  758. X# define RIndexFcn rindex
  759. X# define GetHostname
  760. X#define nargsdefined
  761. X#define ReadDir
  762. X#endif
  763. X
  764. X#ifdef vax_4_2
  765. X# define m_vax
  766. X# define OFFSET 0x0
  767. X# ifdef HOLE
  768. X#   define TTSIZE 10216
  769. X# else
  770. X#   define TTSIZE 6120
  771. X# endif
  772. X# define NPINREG
  773. X# define DefDmpmode 413
  774. X# define NILIS0
  775. X# define StringTable
  776. X# define Vadvise <sys/vadvise.h>
  777. X# define OS "unix"
  778. X# define Pagesize getpagesize()
  779. X# define Machine "vax"
  780. X# define LongFilenames
  781. X# define IndexFcn index
  782. X# define RIndexFcn rindex
  783. X# define GetHostname
  784. X# define CallBrkdirect
  785. X# define UseSetmask
  786. X#define nargsdefined
  787. X#define ReadDir
  788. X#endif
  789. X
  790. X#ifdef vax_unix_ts
  791. X# define m_vax
  792. X# define OFFSET 0x0
  793. X# define TTSIZE 6120
  794. X# define NPINREG
  795. X# define DefDmpmode 410
  796. X# define NILIS0
  797. X# define OS "unix"
  798. X# define Pagesize 1024
  799. X# define Machine "vax"
  800. X# define IndexFcn strchr
  801. X# define RIndexFcn strrchr
  802. X# define SiteName "unknown-site"
  803. X#define nargsdefined
  804. X#define ReadDir
  805. X#endif
  806. X
  807. X#ifdef vax_eunice_vms
  808. X# define m_vax
  809. X# define os_vms
  810. X# define OFFSET 0x0
  811. X# define TTSIZE 10216
  812. X# define NPINREG
  813. X# define DefDmpmode 413
  814. X# define NILIS0
  815. X# define StringTable
  816. X# define OS "vms"
  817. X# define Pagesize 512
  818. X# define Machine "vax"
  819. X# ifndef EUNICE_UNIX_OBJECT_FILE_CFASL
  820. X#   define vms_cfasl
  821. X# endif
  822. X# define IndexFcn index
  823. X# define RIndexFcn rindex
  824. X# define SiteName "unknown-site"
  825. X#define nargsdefined
  826. X#define ReadDir
  827. X#endif
  828. X
  829. X#ifdef sun_unisoft
  830. X# define m_68k
  831. X# define os_unisoft
  832. X# define OFFSET 0x40000
  833. X# define TTSIZE 6120
  834. X# define DefDmpmode 410
  835. X# define OS "unix"
  836. X# define Pagesize 512
  837. X# define Machine "68k"
  838. X# define Feature "unisoft"
  839. X# define IndexFcn index
  840. X# define RIndexFcn rindex
  841. X# define SiteName "unknown-site"
  842. X# define NoSyscall
  843. X#define nargsdefined
  844. X#endif
  845. X
  846. X#ifdef dual_unisoft
  847. X# define m_68k
  848. X# define os_unisoft
  849. X# define OFFSET 0x800000
  850. X# define TTSIZE 6120
  851. X# define DefDmpmode 410
  852. X# define OS "unix"
  853. X# define Pagesize 512
  854. X# define Machine "68k"
  855. X# define Feature "unisoft"
  856. X# define IndexFcn index
  857. X# define RIndexFcn rindex
  858. X# define SiteName "unknown-site"
  859. X# define NoSyscall
  860. X#define nargsdefined
  861. X#endif
  862. X
  863. X#ifdef pixel_unisoft
  864. X# define m_68k
  865. X# define os_unisoft
  866. X# define OFFSET 0x20000
  867. X# define TTSIZE 6120
  868. X# define DefDmpmode 410
  869. X# define OS "unix"
  870. X# define Pagesize 512
  871. X# define Machine "68k"
  872. X# define Feature "unisoft"
  873. X# define IndexFcn index
  874. X# define RIndexFcn rindex
  875. X# define SiteName "unknown-site"
  876. X# define NoSyscall
  877. X#endif
  878. X
  879. X#ifdef lisa_unisys3
  880. X# define m_68k
  881. X# define os_unisoft
  882. X# define OFFSET 0x20000
  883. X# define TTSIZE 6120
  884. X# define unisys3botch   1
  885. X# define DefDmpmode 410
  886. X# define OS "unix"
  887. X# define Pagesize 1024
  888. X# define Machine "68k"
  889. X# define IndexFcn strchr
  890. X# define RIndexFcn strrchr
  891. X# define SiteName "unknown-site"
  892. X# define NoSyscall
  893. X#endif
  894. X
  895. X#ifdef sun_4_1c
  896. X# define m_68k
  897. X# define os_sun4
  898. X# define OFFSET 0x8000
  899. X# define TTSIZE 6120
  900. X# define DefDmpmode 413
  901. X# define StringTable
  902. X# define Vadvise <vadvise.h>
  903. X# define OS "unix"
  904. X# define Pagesize getpagesize()
  905. X# define Machine "68k"
  906. X# define LongFilenames
  907. X# define Feature "sun"
  908. X# define IndexFcn index
  909. X# define RIndexFcn rindex
  910. X# define GetHostname
  911. X# define SunCore
  912. X# define Subxlbotch
  913. X#define nargsdefined
  914. X#define ReadDir
  915. X#endif
  916. X
  917. X#ifdef sun_4_2beta      /* sun release 1.0 */
  918. X# define m_68k
  919. X# define os_sun4
  920. X# define OFFSET 0x8000
  921. X# define TTSIZE 10216
  922. X# define SPISFP
  923. X# define DefDmpmode 413
  924. X# define StringTable
  925. X# define Vadvise <sys/vadvise.h>
  926. X# define OS "unix"
  927. X# define Pagesize getpagesize()
  928. X# define Machine "68k"
  929. X# define LongFilenames
  930. X# define Feature "sun"
  931. X# define NewLineBuf
  932. X# define IndexFcn index
  933. X# define RIndexFcn rindex
  934. X# define GetHostname
  935. X# define UseSetmask
  936. X# define SunCore
  937. X# define Subxlbotch
  938. X#define nargsdefined
  939. X#define ReadDir
  940. X#endif
  941. X
  942. X#ifdef sun_4_2          /* sun release 1.1 */
  943. X# define m_68k
  944. X# define os_sun4
  945. X# define OFFSET 0x8000
  946. X# ifdef BIG
  947. X#  define TTSIZE 10216
  948. X# else
  949. X#  define TTSIZE 6120
  950. X# endif BIG
  951. X# define DefDmpmode 413
  952. X# define StringTable
  953. X# define Vadvise <sys/vadvise.h>
  954. X# define OS "unix"
  955. X# define Pagesize getpagesize()
  956. X# define Machine "68k"
  957. X# define LongFilenames
  958. X# define Feature "sun"
  959. X# define NewLineBuf
  960. X# define IndexFcn index
  961. X# define RIndexFcn rindex
  962. X# define GetHostname
  963. X# define UseSetmask
  964. X# define SunCore
  965. X# define nargsdefined
  966. X# define ReadDir
  967. X#endif
  968. X
  969. X#ifdef mc500_2_2
  970. X# define m_68k
  971. X# define os_masscomp
  972. X# define growstackbotch
  973. X# define OFFSET 0x0
  974. X# define TTSIZE 6120
  975. X# define DefDmpmode 413
  976. X# define StringTable
  977. X/* seems to have disappeared # define Vadvise <sys/vadvise.h> */
  978. X# define OS "unix"
  979. X# define Machine "68k"
  980. X/* # define LongFilenames */
  981. X# define Feature "masscomp"
  982. X# define IndexFcn strchr
  983. X# define RIndexFcn strrchr
  984. X# define Pagesize 4096
  985. X# define NoSysTime
  986. X# define ReadDir
  987. X#endif
  988. X
  989. X#ifdef pegasus
  990. X# define m_68k
  991. X# define OFFSET 0
  992. X# define TTSIZE 6120
  993. X/* SPISFP isn't quite true, but due to the way in which there is a phantom
  994. X * spot on the stack, it is probably better that we use it
  995. X */
  996. X# define growstackbotch
  997. X# define SPISFP
  998. X# undef  XstackSize
  999. X# define XstackSize 22000
  1000. X# define DefDmpmode 413
  1001. X# define OS "uniflex"
  1002. X# define Machine "68k"
  1003. X# define Feature "tek4404"
  1004. X# define IndexFcn index
  1005. X# define RIndexFcn rindex
  1006. X# define SiteName "fi test machine"
  1007. X# define NoSysTime
  1008. X# define NoSyscall
  1009. X# define NoAsm
  1010. X# undef HasTermcap
  1011. X# undef DefLibDir
  1012. X# define DefLibDir "/lisp/lib"
  1013. X/* stdio conversions */
  1014. X# define _IOREAD _READ
  1015. X# define _IOWRT  _WRITE
  1016. X# define _IONBF  _UNBUF
  1017. X# define _IOSTRG 0
  1018. X# define _file _fd
  1019. X/* end stdio conversions */
  1020. X# define ReadDir
  1021. X# define NoLowInput
  1022. X#endif
  1023. X
  1024. X#ifdef ibm_cms
  1025. X# define m_ibm
  1026. X# define os_cms
  1027. X# define OFFSET ((int)&nilatom)
  1028. X# define TTSIZE 6120
  1029. X# define SPISFP
  1030. X# define DefDmpmode 0407
  1031. X# define OS "cms"
  1032. X# define Pagesize 512
  1033. X# define Machine "ibm"
  1034. X# define IndexFcn "index"
  1035. X# define RIndexFcn "rindex"
  1036. X# define SiteName "ucb cms"
  1037. X# define NoSyscall
  1038. X/* it is a bug that unsigned char doesn't exist */
  1039. X# undef unchar
  1040. X# define unchar char
  1041. X/* must define xor on ibm system to be the cent sign */
  1042. X# include "ibmxor.h"
  1043. X/* defined in stdio.h on ibm */
  1044. X# undef Incl_ctype
  1045. X# define IobName
  1046. X# undef HasTermcap
  1047. X#endif
  1048. X
  1049. X#ifdef cadmus
  1050. X# define m_68k
  1051. X# define OFFSET 0x600000
  1052. X# define CadmusOsBugs
  1053. X# ifdef CadmusOsBugs
  1054. X# define TTSIZE 8196
  1055. X# else
  1056. X# define TTSIZE 6120
  1057. X# endif CadmusOsBugs
  1058. X# define DefDmpmode 411
  1059. X# define OS "unix"
  1060. X# define Pagesize 1024
  1061. X# define Machine "68k"
  1062. X# define IndexFcn index
  1063. X# define RIndexFcn rindex
  1064. X# define SiteName "unknown-site"
  1065. X# define NoSyscall
  1066. X# define NoSysTime
  1067. X# define NoAsm
  1068. X# define Subxlbotch
  1069. X# define Feature "cadmus"
  1070. X#endif
  1071. X
  1072. X#ifdef apollo
  1073. X# define m_68k
  1074. X# define Savelisp
  1075. X# define NoDumpLisp
  1076. X# define NoNlist
  1077. X# define UseOnlySdotsForBignums
  1078. X# define SPISFP
  1079. X# define OFFSET ((int) &nilatom)
  1080. X# define TTSIZE 6120
  1081. X# define OS "aegis"
  1082. X# define Pagesize 1024
  1083. X# define Machine "68k"
  1084. X# define IndexFcn index
  1085. X# define RIndexFcn rindex
  1086. X# define SiteName "unknown-site"
  1087. X# define Feature "apollo"
  1088. X# define NoSyscall
  1089. X# define NoSysTime
  1090. X# define NoAsm
  1091. X# define NoLowInput    /* to avoid _read, _write */
  1092. X# define NoLowOuput    /* to avoid _read, _write */
  1093. X# define NewLineBuf
  1094. X/* stdio conversions */
  1095. X# define _IOREAD _SIRD
  1096. X# define _IOWRT  _SIWR
  1097. X# define _IONBF  _SIUNB
  1098. X# define _IOSTRG 0
  1099. X# define _file _fd
  1100. X/* things written in asm can't have upper case in routine names */
  1101. X# define Fixzero fixzero
  1102. X# define Ifuncal ifuncal
  1103. X# define Ipushf ipushf
  1104. X# define Lastfix lastfix
  1105. X# define Undeff undeff
  1106. X#endif
  1107. X
  1108. X#ifdef Elxsi
  1109. X/* do not replace "Elxsi" with "elxsi" because elxsi is defined
  1110. X   in the C preprosessor */
  1111. X# define SPISFP
  1112. X# define OFFSET 0x800
  1113. X# define Machine "elxsi"
  1114. X# define OS "enix"
  1115. X# define _IOSTRG _IOMYBUF
  1116. X# define NoLowInput    /* to avoid _read, _write */
  1117. X# define NoLowOutput
  1118. X# define NoSysTime
  1119. X# define NoGarbColl
  1120. X# define gstart() OFFSET  /* ??? */
  1121. X# define Pagesize 1024
  1122. X# define PAGSIZ 1024
  1123. X# define TTSIZE 6120
  1124. X# define DefDmpmode 410
  1125. X# define IndexFcn strchr
  1126. X# define RIndexFcn strrchr
  1127. X# define SiteName "unknown-site"
  1128. X#endif
  1129. X
  1130. X#ifdef m_68k
  1131. X#define SortSymbols
  1132. X#endif
  1133. X
  1134. END_OF_FILE
  1135. if test 16909 -ne `wc -c <'src/franz/config.h'`; then
  1136.     echo shar: \"'src/franz/config.h'\" unpacked with wrong size!
  1137. fi
  1138. # end of 'src/franz/config.h'
  1139. fi
  1140. if test -f 'src/man.c' -a "${1}" != "-c" ; then 
  1141.   echo shar: Will not clobber existing file \"'src/man.c'\"
  1142. else
  1143. echo shar: Extracting \"'src/man.c'\" \(11451 characters\)
  1144. sed "s/^X//" >'src/man.c' <<'END_OF_FILE'
  1145. X/* top level common memory manager */
  1146. X
  1147. X/*
  1148. X
  1149. Xthis is a server process that manages common memory - or at least what
  1150. Xbehaves like common memory.  It is actually quite simple.  For each object
  1151. Xthat we are keeping track of we allocate a piece of memory via declare().
  1152. XWe write the object with writevalue() and read it with readvalue()
  1153. X
  1154. XInitially, we sit idle waiting for messages.  Each message is processed
  1155. Xas follows:
  1156. X
  1157. Xforever {
  1158. X    for each message in queue
  1159. X        for each component in message
  1160. X            declares are created or confirmed
  1161. X            reads cause a new message to be built
  1162. X            writes cause processes to be tagged for wakeup.
  1163. X    acknowledge every message, by sending back a list of variable
  1164. X    values that the process is listed as a reader which have been written
  1165. X    
  1166. X    for each process scheduled for wakeup {
  1167. X        and not having an outstanding read in the queue {
  1168. X        create a message with all its "read" variables
  1169. X        if (message built) send it, delete it
  1170. X        }
  1171. X    }
  1172. X}
  1173. X
  1174. X*/
  1175. X
  1176. X#include <stdio.h>
  1177. X#include <sys/types.h>
  1178. X
  1179. X#include <sys/time.h>
  1180. X#include <sys/socket.h>
  1181. X#include <netinet/in.h>
  1182. X#include "inet.h"
  1183. X
  1184. X#include "cm_constants.h"
  1185. X#include "cm_var.h"
  1186. X#include "cm_sd.h"
  1187. X#include "cm_slot.h"
  1188. X#include "cm_msg.h"
  1189. X#include "cm_man.h"
  1190. X#include "cm_time.h"
  1191. X
  1192. X#include <setjmp.h>
  1193. X#include <signal.h>
  1194. X
  1195. Xstruct process processes[CM_MAXPROCESSES];
  1196. Xstruct variable variables[CM_MAXVARIABLES];
  1197. Xcm_value cm_variable_names = {0,0,0,1};
  1198. X
  1199. Xint connection_socket;
  1200. X
  1201. Xstatic struct msg *cm_imsg;
  1202. Xstruct msg *cm_omsg;    /* shared with man_get_slot.c .. ugh! */
  1203. X
  1204. Xstruct slot *nextslot();
  1205. X
  1206. X#define CM_WRITE_TIMEOUT    5    /* after this many seconds, we give */
  1207. X                    /* up writing to a process, and go */
  1208. X                    /* on.  We will eventually retry. */
  1209. Xstatic int timeout = CM_WRITE_TIMEOUT;
  1210. Xjmp_buf write_context;    /* context when we are about to call write() */
  1211. Xvoid sigpipe_handler();
  1212. Xvoid sigalrm_handler();
  1213. X
  1214. Xchar *malloc();
  1215. X
  1216. Xmain(argc,argv)
  1217. Xint argc;
  1218. Xchar **argv;
  1219. X{
  1220. X    init(argc,argv);
  1221. X    while (TRUE) {
  1222. X        process_msg();
  1223. X    }
  1224. X}
  1225. X
  1226. Xprocess_msg()
  1227. X{
  1228. X    struct slot *s;
  1229. X    int clientfd;
  1230. X    int slots;    /* number of slots in message */
  1231. X
  1232. X    int rc;
  1233. X
  1234. X    clientfd = man_get_msg(cm_imsg);
  1235. X    init_msg(cm_omsg);
  1236. X    if (cm_imsg->version == CMM_VERSION) {
  1237. X        slots = cm_imsg->slots;
  1238. X        s = cm_imsg->data;
  1239. X        while (TRUE) {
  1240. X            if (s == NULL || slots == 0) break;
  1241. X            if (0 > (rc = man_decode_slot(s,clientfd))) {
  1242. X                printf("process_msg: error trying to decode slot <%d>...aborting msg\n",rc);
  1243. X                break;
  1244. X            }
  1245. X            s = nextslot(cm_imsg,s);
  1246. X            slots--;
  1247. X        }
  1248. X    } else {
  1249. X        char error_message[80];
  1250. X
  1251. X        if (cm_imsg->version > CMM_VERSION)
  1252. X        sprintf(error_message,"cm library (v%d) is %s than cmm (v%d)",
  1253. X            cm_imsg->version,
  1254. X            ((cm_imsg->version > CMM_VERSION)?"newer":"older"),
  1255. X            CMM_VERSION);
  1256. X        put_slot_error(cm_omsg,"version",0,error_message);
  1257. X    }
  1258. X
  1259. X
  1260. X    /* if a slot produced an explicit message (like an error), send it. */
  1261. X    /* otherwise assume he just wants normal variable updates */
  1262. X    /* Also, respond immediately to anyone waiting on an immediate
  1263. X    /* response. */
  1264. X    if ((cm_omsg->slots > 0) || cm_imsg->read_wait) {
  1265. X        add_read_vars_to_msg(cm_omsg,clientfd);
  1266. X        send_msg_to(cm_omsg,clientfd);
  1267. X        processes[clientfd].wakeup = FALSE;
  1268. X    }
  1269. X/* why is this necessary, if you figure it out, comment this! */
  1270. X/*    else processes[clientfd].wakeup = TRUE;*/
  1271. X    wakeup();    /* any processes necessary */
  1272. X}
  1273. X
  1274. Xwakeup()
  1275. X{
  1276. X    int i=0;
  1277. X
  1278. X    eprintf(3,"processes to wake:\n");
  1279. X    for (i=0;i<CM_MAXPROCESSES;i++) {    /* step through all processes */
  1280. X    if (processes[i].wakeup) {
  1281. X        eprintf(3," %s",processes[i].name);
  1282. X        init_msg(cm_omsg);
  1283. X        add_read_vars_to_msg(cm_omsg,i);
  1284. X        if (cm_omsg->slots > 0) send_msg_to(cm_omsg,i);
  1285. X        processes[i].wakeup = FALSE;
  1286. X    }
  1287. X    }
  1288. X    eprintf(3,"\n");
  1289. X}
  1290. X
  1291. Xextern char *optarg;    /* pointer to start of option argument */
  1292. Xextern int optind;    /* index of argv of next argument to be processed */
  1293. X
  1294. X/* initialize the process and variable structures */
  1295. Xinit(argc,argv)
  1296. Xint argc;
  1297. Xchar **argv;
  1298. X{
  1299. X    int i;
  1300. X    int debug_level = 0;
  1301. X    int c;
  1302. X    int port = CM_PORT;
  1303. X    extern int optind;
  1304. X
  1305. X    while (EOF != (c = getopt(argc,argv,"d:p:t:"))) {
  1306. X        switch (c) {
  1307. X        case 'd':
  1308. X            debug_level = atoi(optarg);
  1309. X            break;
  1310. X        case 'p':
  1311. X            port = atoi(optarg);
  1312. X            break;
  1313. X        case 't':    /* timeout */
  1314. X            timeout = atoi(optarg);
  1315. X            break;
  1316. X        }
  1317. X    }
  1318. X
  1319. X    set_cm_debug_level(debug_level);
  1320. X    set_cm_process_name(CM_MANAGER_NAME);
  1321. X
  1322. X    eprintf(1,"cmm version %d\n",CMM_VERSION);
  1323. X    eprintf(1,"timeout on writes = %d\n",timeout);
  1324. X
  1325. X    if (-1 == (connection_socket = initport(PORT_NUMBER(port),SERVER,SOCK_STREAM,
  1326. X        (char *)0))) {
  1327. X        fprintf(stderr,"failed to initialize connection socket\n");
  1328. X        exit(-1);
  1329. X    }
  1330. X    cm_time_init();
  1331. X
  1332. X    if (!(cm_imsg = (struct msg *)malloc(CM_MSGSIZE))) {
  1333. X        fprintf(stderr,"init: failed malloc(imsg)\n");
  1334. X        exit(-1);
  1335. X    }
  1336. X    if (!(cm_omsg = (struct msg *)malloc(CM_MSGSIZE))) {
  1337. X        fprintf(stderr,"init: failed malloc(omsg)\n");
  1338. X        exit(-1);
  1339. X    }
  1340. X
  1341. X    for (i=0;i<CM_MAXPROCESSES;i++) processes[i].inuse = FALSE;
  1342. X
  1343. X    for (i=0;i<CM_MAXVARIABLES;i++) {
  1344. X        cm_sd_clear(&variables[i].data);
  1345. X        variables[i].readers = 0;
  1346. X        variables[i].writers = 0;
  1347. X        variables[i].xwriter = 0;
  1348. X        variables[i].count = 0;
  1349. X    }
  1350. X
  1351. X#if 0
  1352. X    /* grab a variable for maintaining the names of all other variables */
  1353. X    variables[0].writers = 1;
  1354. X    variables[0].xwriter = connection_socket;    /* reserved to us */
  1355. X
  1356. X    /* stick in the first value */
  1357. X    variables[0].count = 1;
  1358. X    cm_variable_names.size = cm_variable_name.msize =
  1359. X        strlen("cm_variable_names"+1);
  1360. X    cm_variable_names.data = new_string("cm_variable_names");
  1361. X#endif
  1362. X
  1363. X    signal(SIGPIPE,sigpipe_handler);
  1364. X    signal(SIGALRM,sigalrm_handler);
  1365. X}
  1366. X
  1367. X/* if process died while we were writing to it, abort the write() */
  1368. Xvoid sigpipe_handler()
  1369. X{
  1370. X    longjmp(write_context,SIGPIPE);    /* abort the write() */
  1371. X}
  1372. X
  1373. X/* if process hangs and we write to it enough, eventually we will block */
  1374. X/* abort the write(), when the timer goes off */
  1375. Xvoid sigalrm_handler()
  1376. X{
  1377. X    longjmp(write_context,SIGALRM);
  1378. X}
  1379. X
  1380. Xstruct variable *
  1381. Xget_variable(name)
  1382. Xchar *name;
  1383. X{
  1384. X    int i;
  1385. X    int j;
  1386. X    int free_var = -1;
  1387. X
  1388. X    for (i=0;i<CM_MAXVARIABLES;i++) {
  1389. X        if (!var_inuse(&variables[i])) {
  1390. X            free_var = i;
  1391. X        } else if (!strcmp(variables[i].name,name)) {
  1392. X            return(&variables[i]);
  1393. X        }
  1394. X    }
  1395. X
  1396. X    if (free_var == -1) {
  1397. X        /* no old definition and no space for a new one! */
  1398. X        /* this is really an exceptional condition, so let's */
  1399. X        /* print out some helpful info */
  1400. X
  1401. X        fprintf(stderr,"get_variable(%s) failed\n",name);
  1402. X        for (i=0;i<CM_MAXVARIABLES;i++) {
  1403. X            printf("%d: ",i);
  1404. X            if (var_inuse(&variables[i])) {
  1405. X                printf("<%s>",variables[i].name);
  1406. X                printf(" r=%d  w=%d\n  inuse=%d",
  1407. X                    variables[i].readers,
  1408. X                    variables[i].writers,
  1409. X                    var_inuse(&variables[i]));
  1410. X            } else printf("<not in use>\n");
  1411. X        }
  1412. X        return(NULL);
  1413. X    }
  1414. X
  1415. X
  1416. X    strcpy(variables[free_var].name,name);
  1417. X    variables[free_var].count = 0;
  1418. X    time_now(&variables[free_var].timestamp);
  1419. X    variables[free_var].command_association = 0;
  1420. X    variables[free_var].xwriter = CM_NULL_PROCESS;
  1421. X    for (j=0;j<CM_MAXPROCESSES;j++) {
  1422. X        variables[free_var].role[j].reader = FALSE;
  1423. X        variables[free_var].role[j].writer = FALSE;
  1424. X        variables[free_var].role[j].wakeup = FALSE;
  1425. X        variables[free_var].role[j].new = FALSE;
  1426. X    }
  1427. X    return(&variables[free_var]);
  1428. X}
  1429. X
  1430. Xsend_msg_to(m,to)
  1431. Xstruct msg *m;
  1432. Xint to;
  1433. X{
  1434. X    int rc;
  1435. X
  1436. X    switch (rc = setjmp(write_context)) {
  1437. X    case 0:
  1438. X        /* assume write() succeeds */
  1439. X        alarm(timeout);
  1440. X        sized_write(to,(char *)m,m->size);
  1441. X        alarm(0);
  1442. X        print_msg(m);
  1443. X        break;
  1444. X    case SIGPIPE:
  1445. X        alarm(0);
  1446. X        /* if write() interrupted due to SIGPIPE */
  1447. X        eprintf(3,"broken pipe\n");
  1448. X        eprintf(3,"detected death of %s on fd %d\n",
  1449. X            (processes[to].inuse?
  1450. X                processes[to].name:"unknown"),
  1451. X                to);
  1452. X        kill_client(to);
  1453. X        break;
  1454. X    case SIGALRM:
  1455. X        fprintf(stderr,
  1456. X            "process %s is being antisocial on fd %d\n",
  1457. X            (processes[to].inuse?
  1458. X                processes[to].name:"unknown"),
  1459. X                to);
  1460. X        break;
  1461. X    default:
  1462. X        alarm(0);
  1463. X        printf("setjmp(write_context) = %d?!\n",rc);
  1464. X        abort();    /* should never happen */
  1465. X    }
  1466. X}
  1467. X
  1468. X/* The philosophy coded here is that the cmm always responds to a msg
  1469. Xwith the data values that are marked for read and have changed since the
  1470. Xlast time it was read */
  1471. Xadd_read_vars_to_msg(m,pin)
  1472. Xstruct msg *m;
  1473. Xint pin;
  1474. X{
  1475. X    struct variable *v;
  1476. X
  1477. X    for (v=variables;v<&variables[CM_MAXVARIABLES];v++) {
  1478. X        if (!var_inuse(v)) continue;
  1479. X        eprintf(5,"is_reader(%s,%s)=%d  is_new(%s,%s)=%d\n",
  1480. X            processes[pin].name,v->name,is_reader(pin,v),
  1481. X            processes[pin].name,v->name,is_new(pin,v));
  1482. X        if (is_reader(pin,v) && is_new(pin,v)) {
  1483. X                    put_slot_read_response(m,v->name,
  1484. X            v->count,&v->timestamp,v->command_association,&v->data);
  1485. X            unset_new(pin,v);
  1486. X        }
  1487. X    }
  1488. X}
  1489. X
  1490. Xstatic int clientfds = 0;    /* bitmap of sockets to clients */
  1491. X
  1492. Xint    /* returns file descriptor of client */
  1493. Xman_get_msg(msg)
  1494. Xstruct msg *msg;
  1495. X{
  1496. X    int clientfd;
  1497. X    int msg_length = 0;
  1498. X
  1499. X
  1500. X    while (msg_length <= 0) {
  1501. X    eprintf(3,"known fds = %x\n",clientfds);
  1502. X    clientfd = select_server_stream(connection_socket,&clientfds);
  1503. X    msg_length = sized_read(clientfd,(char *)msg,CM_MSGSIZE);
  1504. X    eprintf(3,"received message from %s.  fd = %d length = %d\n",
  1505. X                (processes[clientfd].inuse?
  1506. X                    processes[clientfd].name:"new user"),
  1507. X            clientfd,
  1508. X            msg_length);
  1509. X    print_msg(msg);
  1510. X    if (msg_length < 0) {
  1511. X        eprintf(3,"detected death of %s on fd %d\n",
  1512. X                (processes[clientfd].inuse?
  1513. X                    processes[clientfd].name:"unknown"),
  1514. X                    clientfd);
  1515. X        kill_client(clientfd);
  1516. X    }
  1517. X    }
  1518. X
  1519. X    if (!processes[clientfd].inuse) {
  1520. X    processes[clientfd].inuse = TRUE;
  1521. X    processes[clientfd].wakeup = FALSE;
  1522. X    strcpy(processes[clientfd].name,msg->name);
  1523. X    }
  1524. X    eprintf(2,"received msg from %s on fd %d\n",msg->name,clientfd);
  1525. X
  1526. X    return(clientfd);
  1527. X}
  1528. X
  1529. X/* delete any info we had about this client */
  1530. Xkill_client(fd)
  1531. Xint fd;
  1532. X{
  1533. X    struct variable *v;
  1534. X
  1535. X    processes[fd].inuse = FALSE;
  1536. X    close(fd);
  1537. X    eprintf(3,"known fds = %x (before kill_client)\n",clientfds);
  1538. X/*new*/    clientfds &= ~(1<<fd);
  1539. X    eprintf(3,"known fds = %x (after kill_client)\n",clientfds);
  1540. X
  1541. X    for (v=variables;v<&variables[CM_MAXVARIABLES];v++) {
  1542. X        if (!var_inuse(v)) continue;
  1543. X        unset_reader(fd,v);
  1544. X        unset_writer(fd,v);
  1545. X        unset_wakeup(fd,v);
  1546. X        /* note that the above calls change the value of var_inuse */
  1547. X        if (var_inuse(v)) continue;
  1548. X        /* var had been set, free up any space taken by it */
  1549. X        if (v->count) {
  1550. X            cm_sd_free(&v->data);
  1551. X            v->count = 0;
  1552. X        }
  1553. X    }
  1554. X}
  1555. X
  1556. X/* flag this variable as having a new value with respect to this process */
  1557. Xset_new(proc,var)
  1558. Xint proc;
  1559. Xstruct variable *var;
  1560. X{
  1561. X    var->role[proc].new = TRUE;
  1562. X}
  1563. X
  1564. Xset_reader(proc,var)
  1565. Xint proc;
  1566. Xstruct variable *var;
  1567. X{
  1568. X    if (!var->role[proc].reader) {
  1569. X        var->role[proc].reader = TRUE;
  1570. X        var->readers++;
  1571. X    }
  1572. X}
  1573. X
  1574. Xset_nonxwriter(proc,var)
  1575. Xint proc;
  1576. Xstruct variable *var;
  1577. X{
  1578. X    if (!var->role[proc].writer) {
  1579. X        var->role[proc].writer = TRUE;
  1580. X        var->writers++;
  1581. X    }
  1582. X}
  1583. X
  1584. Xset_xwriter(proc,var)
  1585. Xint proc;
  1586. Xstruct variable *var;
  1587. X{
  1588. X    var->xwriter = proc;
  1589. X    set_nonxwriter(proc,var);
  1590. X}
  1591. X
  1592. Xset_wakeup(proc,var)
  1593. Xint proc;
  1594. Xstruct variable *var;
  1595. X{
  1596. X    var->role[proc].wakeup = TRUE;
  1597. X}
  1598. X
  1599. Xunset_wakeup(proc,var)
  1600. Xint proc;
  1601. Xstruct variable *var;
  1602. X{
  1603. X    var->role[proc].wakeup = FALSE;
  1604. X}
  1605. X
  1606. Xunset_new(proc,var)
  1607. Xint proc;
  1608. Xstruct variable *var;
  1609. X{
  1610. X    var->role[proc].new = FALSE;
  1611. X}
  1612. X
  1613. Xunset_reader(proc,var)
  1614. Xint proc;
  1615. Xstruct variable *var;
  1616. X{
  1617. X    if (var->role[proc].reader) {
  1618. X        var->role[proc].reader = FALSE;
  1619. X        var->readers--;
  1620. X    }
  1621. X}
  1622. X
  1623. Xunset_writer(proc,var)
  1624. Xint proc;
  1625. Xstruct variable *var;
  1626. X{
  1627. X    if (var->role[proc].writer) {
  1628. X        if (var->xwriter == proc) var->xwriter = CM_NULL_PROCESS;
  1629. X        var->role[proc].writer = FALSE;
  1630. X        var->writers--;
  1631. X    }
  1632. X}
  1633. X
  1634. Xvar_inuse(var)
  1635. Xstruct variable *var;
  1636. X{
  1637. X    return(var->readers || var->writers);
  1638. X}
  1639. END_OF_FILE
  1640. if test 11451 -ne `wc -c <'src/man.c'`; then
  1641.     echo shar: \"'src/man.c'\" unpacked with wrong size!
  1642. fi
  1643. # end of 'src/man.c'
  1644. fi
  1645. echo shar: End of archive 3 \(of 4\).
  1646. cp /dev/null ark3isdone
  1647. MISSING=""
  1648. for I in 1 2 3 4 ; do
  1649.     if test ! -f ark${I}isdone ; then
  1650.     MISSING="${MISSING} ${I}"
  1651.     fi
  1652. done
  1653. if test "${MISSING}" = "" ; then
  1654.     echo You have unpacked all 4 archives.
  1655.     rm -f ark[1-9]isdone
  1656. else
  1657.     echo You still need to unpack the following archives:
  1658.     echo "        " ${MISSING}
  1659. fi
  1660. ##  End of shell archive.
  1661. exit 0
  1662.  
  1663.