source: trunk/athena/bin/discuss/server/coreutil.c @ 17452

Revision 17452, 19.0 KB checked in by zacheiss, 22 years ago (diff)
Include unistd.h for lseek prototype and SEEK_* macros
RevLine 
[147]1/*
2 *
[1939]3 *      Copyright (C) 1988, 1989 by the Massachusetts Institute of Technology
4 *      Developed by the MIT Student Information Processing Board (SIPB).
5 *      For copying information, see the file mit-copyright.h in this release.
[150]6 *
[1939]7 */
8/*
[17452]9 *      $Id: coreutil.c,v 1.32 2002-04-06 15:18:55 zacheiss Exp $
[150]10 *
11 *
[147]12 * coreutil.c  -- These contain lower-layer, utility type routines to
13 *                be used by core.  These include things to handle the
14 *                in-memory superblock, and to open & close meetings.
15 *
16 */
17
[150]18#ifndef lint
[1478]19#ifdef __STDC__
20const
21#endif
22static char rcsid_coreutil_c[] =
[17452]23    "$Id: coreutil.c,v 1.32 2002-04-06 15:18:55 zacheiss Exp $";
[1478]24#endif /* lint */
[150]25
[1938]26#include <discuss/types.h>
27#include <discuss/dsc_et.h>
28#include "atom.h"
[147]29#include "mtg.h"
[1938]30#include <discuss/tfile.h>
31#include <discuss/acl.h>
32#include "internal.h"
33#include "ansi.h"
[12439]34#if HAVE_ZEPHYR
[752]35#include <zephyr/zephyr.h>
[12439]36#endif
37#include <stdio.h>
[12267]38#include <stdlib.h>
[147]39#include <errno.h>
[972]40#include <sys/types.h>
[17452]41#include <unistd.h>
[752]42#include <netdb.h>
[147]43#include <sys/file.h>
44#include <sys/stat.h>
[6571]45#include <string.h>
[12439]46#if HAVE_FCNTL_H
[6571]47#include <fcntl.h>
48#endif
[17452]49#include <unistd.h>
[147]50
51/* global variables */
[1938]52char current_mtg [256] = "";    /* meeting that's opened */
53int u_trn_f,u_control_f,u_acl_f; /* UNIX file descriptors */
54bool nuclear = FALSE;           /* Using atomic reads/writes */
55afile a_control_f = NULL;       /* radioactive file descriptor */
56tfile abort_file = NULL;        /* close this on abort */
57bool  read_lock = FALSE;        /* have lock on u_control_f */
[11464]58bool  mtg_swapped = FALSE;      /* current meeting is swapped */
[1938]59dsc_acl   *mtg_acl = NULL;      /* current mtg acl */
60int     last_acl_mod;           /* last mod to ACL */
[147]61mtg_super super;
62char *super_chairman;
63char *super_long_name;
[1938]64int has_privs = 0;              /* Has privileges (linked) */
65int no_nuke = 0;                /* Don't be atomic (linked) */
[12439]66#if HAVE_ZEPHYR
[1938]67int use_zephyr = 1;             /* Actually do use Zephyr. */
[2080]68#else
69int use_zephyr = 0;
[1938]70#endif
[147]71
72
73/* EXTERNAL */
74extern int errno;
75extern char rpc_caller [];
76
77/*
78 *
79 * new_string (s)  --   Routine to create a copy of the given string, using
80 *                      malloc.
81 *
82 */
83char *new_string (s)
84char *s;
85{
86     int len;
87     char *newstr;
88
89     len = strlen (s) + 1;
[170]90     newstr = malloc ((unsigned)len);
91     (void) strcpy (newstr, s);
[147]92     return (newstr);
93}
94
95/*
96 *
97 * open_mtg (mtg_name) -- Routine to open a meeting, if necessary.
98 *
99 */
100int open_mtg (mtg_name)
101char *mtg_name;
102{
103     char str[256];
104     int result;
105     int mtg_name_len;
106     trn_base tb;
[170]107     int uid = (int)geteuid();
[150]108     struct stat sb;
[147]109
110     mtg_name_len = strlen (mtg_name);
[1938]111     if (mtg_name[0] != '/' || mtg_name_len == 0 || mtg_name_len > 168
112         || mtg_name [mtg_name_len-1] == '/') {
[147]113          return (BAD_PATH);
114     }
115
[2033]116     /* Check for moved meeting */
[170]117     (void) strcpy (str, mtg_name);
[2033]118     (void) strcat (str, "/forward");
119     if (!stat(str, &sb)) {
120          return(MTG_MOVED);
121     }
122
123     (void) strcpy (str, mtg_name);
[170]124     (void) strcat (str, "/acl");
[147]125
[150]126     if (!strcmp (mtg_name, current_mtg)) {
127          /*
128           * is acl stale?
129           */
[257]130          if (stat(str, &sb) >= 0)
131               if (sb.st_mtime <= last_acl_mod)
132                    return (0);                         /* that was easy */
[150]133     }
134
[147]135     if (current_mtg [0] != '\0') {             /* close previous meeting */
136          if (nuclear)
137               panic ("Nuclear flag error");    /* should never happen */
[170]138          (void) close (u_trn_f);
139          (void) close (u_control_f);
[147]140          current_mtg [0] = '\0';
141          acl_destroy(mtg_acl);
142     }
143
144     u_trn_f = u_control_f = u_acl_f = 0;
145
146     if ((u_acl_f = open(str, O_RDONLY, 0700)) < 0) {
147          if (errno == ENOENT)
148               result = NO_SUCH_MTG;
149          else if (errno == EACCES)
150               result = NO_ACCESS;
151          else
152               result = BAD_PATH;
153          goto punt;
154     }
155     if (!fis_owner (u_acl_f, uid)) {
156          result = NO_ACCESS;
157          goto punt;
158     }
159
160     mtg_acl = acl_read (u_acl_f);
[170]161     (void) fstat(u_acl_f, &sb);
[150]162     last_acl_mod = sb.st_mtime;
[170]163     (void) close(u_acl_f);
[147]164     u_acl_f = 0;
165
[170]166     (void) strcpy (str, mtg_name);
167     (void) strcat (str, "/control");
[147]168
169     if ((u_control_f = open(str, O_RDWR, 0700)) < 0) {
170          if (errno == ENOENT)
171               result = NO_SUCH_MTG;
172          else if (errno == EACCES)
173               result = NO_ACCESS;
174          else
175               result = BAD_PATH;
176          goto punt;
177     }
178
179     if (!fis_owner (u_control_f, uid)) {
180          result = NO_ACCESS;
181          goto punt;
182     }
183
[170]184     (void) strcpy (str, mtg_name);
185     (void) strcat (str, "/transactions");
[147]186     
187     if ((u_trn_f = open(str, O_RDWR, 0700)) < 0) {
188          if (errno == ENOENT)
189               result = NO_SUCH_MTG;
190          else if (errno == EACCES)
191               result = NO_ACCESS;
192          else
193               result = BAD_PATH;
194          goto punt;
195     }
196
197     if (!fis_owner (u_trn_f, uid)) {
198          result = NO_ACCESS;
199          goto punt;
200     }
201
202     read (u_trn_f, (char *) &tb, sizeof (trn_base));
[11464]203     if (tb.unique == TRN_BASE_UNIQUE_SWAP) {
204          swap_trn_base(&tb);
205          mtg_swapped = TRUE;
206     } else {
207          mtg_swapped = FALSE;
208     }
209
[147]210     if (tb.unique != TRN_BASE_UNIQUE) {
211          result = INCONSISTENT;
212          goto punt;
213     }
214
[170]215     (void) strcpy (current_mtg, mtg_name);
[147]216
217     return (0);
218
219 punt:
220     if (u_trn_f)
[170]221             (void) close(u_trn_f);
[147]222     if (u_control_f)
[170]223             (void) close(u_control_f);
[147]224     if (u_acl_f)
[170]225             (void) close(u_acl_f);
[147]226     acl_destroy(mtg_acl);
227     mtg_acl = NULL;
228     return (result);
229}
230
231
232int read_super()
233{
234     if (nuclear) {
235          aread (a_control_f, (char *) &super, sizeof(super), 0);
236     } else {
[17452]237             lseek (u_control_f, (long)0, SEEK_SET);
[170]238             read (u_control_f, (char *) &super, sizeof (super));
[147]239     }
240
[11464]241     if (!mtg_swapped) {
242          if (super.unique != MTG_SUPER_UNIQUE)
243               return (INCONSISTENT);
244     } else {
245          if (super.unique != MTG_SUPER_UNIQUE_SWAP)
246               return (INCONSISTENT);
247          swap_super(&super);
248     }
[1072]249
[147]250     if (super.version != MTG_SUPER_1)
251          return (NEW_VERSION);
252
[170]253     super_long_name = malloc ((unsigned)super.long_name_len);
254     super_chairman = malloc ((unsigned)super.chairman_len);
[147]255
256     if (nuclear) {
257          aread (a_control_f, super_long_name, super.long_name_len, super.long_name_addr);
258          aread (a_control_f, super_chairman, super.chairman_len, super.chairman_addr);
259     } else {
[17452]260          lseek (u_control_f, (long)super.long_name_addr, SEEK_SET);
[147]261          read (u_control_f, super_long_name, super.long_name_len);
[17452]262          lseek (u_control_f, (long)super.chairman_addr, SEEK_SET);
[147]263          read (u_control_f, super_chairman, super.chairman_len);
264     }
265
266     return(0);
267}
268
269write_super ()
270{
271     int sc_len, sl_len;
[11464]272     int slong_name_len, slong_name_addr;
273     int schairman_len, schairman_addr;
[147]274
275     sc_len = strlen (super_chairman)+1;
276     sl_len = strlen (super_long_name)+1;
277
278     if (sc_len != super.chairman_len || sl_len != super.long_name_len) {               /* reallocate things */
279          super.long_name_addr = sizeof (super);
280          super.long_name_len = sl_len;
281          super.chairman_addr = super.long_name_addr + super.long_name_len;
282          super.chairman_len = sc_len;
283     }
284
[11464]285     /* Copy into locals to avoid swapping */
286     slong_name_len = super.long_name_len;
287     slong_name_addr = super.long_name_addr;
288     schairman_len = super.chairman_len;
289     schairman_addr = super.chairman_addr;
290
291     if (mtg_swapped)
292          swap_super(&super);
293
[147]294     if (nuclear) {
295          awrite (a_control_f, (char *) &super, sizeof (super), 0);
[11464]296          awrite (a_control_f, super_long_name, slong_name_len, slong_name_addr);
297          awrite (a_control_f, super_chairman, schairman_len, schairman_addr);
[147]298     } else {
[17452]299          lseek (u_control_f, (long)0, SEEK_SET);
[147]300          write (u_control_f, (char *)  &super, sizeof (super));
[17452]301          lseek (u_control_f, (long)slong_name_addr, SEEK_SET);
[11464]302          write (u_control_f, super_long_name, slong_name_len);
[17452]303          lseek (u_control_f, (long)schairman_addr, SEEK_SET);
[11464]304          write (u_control_f, super_chairman, schairman_len);
[147]305     }
306
307     free (super_chairman);
[2079]308     super_chairman = NULL;
[147]309     free (super_long_name);
[2079]310     super_long_name = NULL;
[147]311     super.unique = 0;                                  /* prevent accidents */
312
313     return;
314}
315
316/*
317 *
318 * forget_super () -- Routine to dump superblock, like when we just read
319 *                    it.  This frees any alloc'd storage.
320 *
321 */
322forget_super()
323{
[2079]324     if (super_long_name != NULL)
325          free(super_long_name);
326     super_long_name = NULL;
[147]327
[2079]328     if (super_chairman != NULL)
329          free(super_chairman);
330     super_chairman = NULL;
[147]331     super.unique = 0;
332}
333
334/*
335 *
336 * start_read () --     This reserves the meeting for non-destructive reading.
337 *                      Simply does an flock.
338 *
339 */
340start_read()
341{
[7185]342     struct flock lock;
343
[1503]344     if (!no_nuke) {
[9551]345          lock.l_type = F_RDLCK;
[7185]346          lock.l_start = 0;
347          lock.l_whence = 0;
348          lock.l_len = 0;
[9551]349          if (fcntl(u_control_f, F_SETLKW, &lock) < 0)
[1503]350               panic ("Cannot share lock");
351          read_lock = TRUE;
352     }
[147]353}
354
355/*
356 *
357 * finish_read () --    This frees up our reservation on the meeting.  This
358 *                      does the opposite of start_read.
359 *
360 */
361finish_read()
362{
[7185]363    struct flock lock;
364
[1503]365     if (!no_nuke) {
[7185]366           lock.l_type = F_UNLCK;
367          lock.l_start = 0;
368          lock.l_whence = 0;
369          lock.l_len = 0;
370          fcntl(u_control_f, F_SETLK, &lock);
[1503]371          read_lock = 0;
372     }
[147]373}
374
375/*
376 *
377 * chain_addr -- Returns address of given chain block.
378 *
379 */
380faddr chain_addr(trn)
381trn_nums trn;
382{
383     if (trn < super.lowest || trn > super.highest)
384          return (0);
385
386     return (super.chain_start + (trn-1) * sizeof (chain_blk));
387}
388
389int read_chain (trn, cb)
390trn_nums trn;
391chain_blk *cb;
392{
393     faddr cbaddr;
394
395     cbaddr = chain_addr (trn);
396     if (cbaddr == 0)
397          return (NO_SUCH_TRN);
398
399     if (nuclear)
400          aread (a_control_f, (char *) cb, sizeof (chain_blk), cbaddr);
401     else {
[17452]402          lseek (u_control_f, (long)cbaddr, SEEK_SET);
[147]403          read (u_control_f, (char *) cb, sizeof (chain_blk));
404     }
405
[11464]406     if (mtg_swapped)
407          swap_chain(cb);
408
[1072]409     if (cb -> unique != CHAIN_BLK_UNIQUE || cb -> current != trn)
410          return (INCONSISTENT);
411
[147]412     if (cb -> version != CHAIN_BLK_1)
413          return (NEW_VERSION);
414
415     return (0);
416}
417
418int write_chain (cb)
419chain_blk *cb;
420{
421     faddr cbaddr;
422
423     cbaddr = chain_addr (cb -> current);
424     if (cbaddr == 0)
425          return (NO_SUCH_TRN);
426
[11464]427     if (mtg_swapped)
428          swap_chain(cb);
429
[247]430     if (nuclear) {
[11464]431          if (awrite (a_control_f, (char *) cb, sizeof (chain_blk), cbaddr) != sizeof (chain_blk)) {
432               if (mtg_swapped)
433                    swap_chain(cb);
[247]434               return (NO_WRITE);
[11464]435          }
[247]436     }
[147]437     else {
[17452]438          lseek (u_control_f, (long)cbaddr, SEEK_SET);
[11464]439          if (write (u_control_f, (char *) cb, sizeof (chain_blk)) != sizeof (chain_blk)) {
440               if (mtg_swapped)
441                    swap_chain(cb);
[247]442               return (NO_WRITE);
[11464]443          }
[147]444     }
445
[11464]446     if (mtg_swapped)
447          swap_chain(cb);
[147]448     return (0);
449}
450
451/*
452 *
453 * read_trn -- routine to read a transaction from the transaction file.
454 *
455 */
[2743]456int read_trn (trn_addr, th, th_subject, th_author, th_signature)
[147]457faddr trn_addr;
458trn_hdr *th;
[2743]459char **th_subject, **th_author, **th_signature;
[147]460{
[2743]461     char *author;
462
[17452]463     lseek (u_trn_f, (long)trn_addr, SEEK_SET);
[147]464     read (u_trn_f, (char *) th, sizeof (trn_hdr));
465
[11464]466     if (mtg_swapped)
467          swap_trn(th);
468
[1072]469     if (th -> unique != TRN_HDR_UNIQUE)
470          return (INCONSISTENT);
471
[147]472     if (th -> version != TRN_HDR_1)
473          return(NEW_VERSION);
474
[2743]475     if (th_subject != NULL) {
[170]476          *th_subject = malloc ((unsigned)(th -> subject_len));
[17452]477          lseek (u_trn_f, (long)(th -> subject_addr), SEEK_SET);
[147]478          read (u_trn_f, *th_subject, th -> subject_len);
479     }
480         
[2743]481     if (th_author != NULL || th_signature != NULL) {
482          author = malloc ((unsigned)(th -> author_len));
[17452]483          lseek (u_trn_f, (long)(th -> author_addr), SEEK_SET);
[2743]484          read (u_trn_f, author, th -> author_len);
[147]485     }
486
[2743]487     if (th_author != NULL)
488          *th_author = author;
489
490     if (th_signature != NULL) {
491          if (strlen(author)+1 == th -> author_len) {
492               *th_signature = new_string(author);      /* No signature, return author */
493          } else {
494               *th_signature = new_string(&author[strlen(author)+1]);
495          }
496          if (th_author == NULL)
497               free(author);
498     }
499               
[147]500     return(0);
501}
502         
503
504/*
505 *
506 * core_abort () -- Routine for use by core routines to clean things up.
507 *
508 */
509core_abort ()
510{
511     int dummy;
512
513     if (nuclear) {
514          aabort(a_control_f);
515          nuclear = FALSE;
516     }
517
518     if (abort_file != NULL) {
519          tclose (abort_file,&dummy);
520          abort_file = NULL;
521     }
522
523     if (read_lock)
524          finish_read();
525
[2079]526     forget_super();
527
[147]528     return;
529}
530
531/*
532 *
533 * fsize () -- Routine to find out the size of a file.
534 *
535 */
536fsize (d)
537int d;
538{
539     struct stat buf;
540
541     if (fstat (d, &buf) < 0)
542          return (0);
543
544     return (buf.st_size);
545}
546/*
547 *
548 * fis_owner () -- Routine to find out if uid is owner of file.
549 *
550 */
551fis_owner (d, uid)
552int d,uid;
553{
554     struct stat buf;
555
556     if (fstat (d, &buf) < 0)
557          return (0);
558
559     return (uid == buf.st_uid);
560}
561
562/*
563 *
564 * has_trn_access -- Routine to return true if current user can access
565 *                   transaction.
566 *
567 */
568bool has_trn_access(author,mode)
569char *author;
570char mode;
571{
572     char *test_modes;
573
[257]574     if (has_privs)
575          return(TRUE);                         /* linked in */
576
[147]577     switch (mode) {
578     case 'd':
579          if (!strcmp(author,rpc_caller)) {
580               test_modes = "o";
581          } else {
582               test_modes = "d";
583          }
584          return (acl_check(mtg_acl,rpc_caller,test_modes));
585
586     case 'r':
587          return (acl_check(mtg_acl,rpc_caller,"r") ||
588                  ((!strcmp (author, rpc_caller)) && acl_check(mtg_acl,rpc_caller,"o")));
589     default:
590          panic ("Invalid mode");
[170]591          /*NOTREACHED*/
[147]592     }
593}         
594/*
595 *
596 * has_mtg_access -- Routine to return true if current user can access
597 *                   mtg, with given mode.
598 *
599 */
600bool has_mtg_access(mode)
601char mode;
602{
603     char *test_modes;
[296]604     char mode_str[3];
[147]605
[257]606     if (has_privs)                             /* linked in stuff */
607          return (TRUE);               
608
[147]609     switch (mode) {
610     case 'w':
611     case 'a':
[296]612     case 'r':
[147]613     case 's':
[296]614     case 'o':
615          mode_str[0] = mode;
616          mode_str[1] = '\0';
617          test_modes = mode_str;
[147]618          break;
619
620     case 'c':
621          test_modes = "c";
622          break;
623
624     default:
625          panic("Invalid mode");
626     }
627
628     return(acl_check(mtg_acl,rpc_caller,test_modes));
629}         
630/*
631 *
632 * panic -- just a printf
633 *
634 */
635panic(str)
636char *str;
637{
638     printf("panic: %s\n",str);
639     perror("discuss");
640     exit(1);
641}
[1938]642
[12439]643#if HAVE_ZEPHYR
[752]644/*
645 *
646 * mtg_znotify -- send off a Zephyr notification as appropriate
647 *
648 */
[1938]649
650static const char * this_host = (const char *) NULL;
651
[2743]652void mtg_znotify(mtg_name, subject, author, signature)
653        char *mtg_name, *subject, *author, *signature;
[752]654{
[1478]655        register dsc_acl_entry *ae;
[752]656        register int n;
657        ZNotice_t notice;
[2750]658        char *msglst[5],bfr[30],fullpath[256];
[2743]659        int code, list_size;
[1938]660
661        if (!use_zephyr)
662            return;
663
664        if (!this_host) {
665            /* perform initializations */
666            char *h;
667            char host[100];
668            struct hostent *hent;
669            if (gethostname(host,100) != 0)
670                return;
671            hent = (struct hostent *) gethostbyname(host);
672            if (hent == 0)
673                return;
674            h = (char *) malloc (strlen (hent->h_name) + 1);
675            if (!h)
676                return;
677            strcpy (h, hent->h_name);
678            this_host = h;
679            ZInitialize();
680        }
681
[752]682        /* Set up the notice structure */
[7185]683        memset(&notice, 0, sizeof(notice));
[752]684
[1938]685        sprintf(fullpath,"%s:%s", this_host, mtg_name);
[1510]686        ZOpenPort(NULL);
[752]687        notice.z_kind = UNSAFE;
688        notice.z_port = 0;
689        notice.z_class = "DISCUSS";
690        notice.z_class_inst = fullpath;
691        notice.z_opcode = "NEW_TRN";
692        notice.z_sender = 0;
[2743]693        if (signature == NULL)
694             notice.z_default_format = "New transaction [$1] entered in $2\nFrom: $3\nSubject: $4";
695        else
696             notice.z_default_format = "New transaction [$1] entered in $2\nFrom: $3 ($5)\nSubject: $4";
[752]697        msglst[0] = bfr;
698        sprintf(msglst[0],"%04d",super.highest);
699        msglst[1] = super_long_name;
700        msglst[2] = author;
701        msglst[3] = subject;
[2743]702        list_size = 4;
703        if (signature != NULL) {
704             msglst[4] = signature;
705             list_size = 5;
706        }
[752]707
708        /* Does "*" have read access? If so, just send out a global
709         * notice.
710         */
711
712        /* XXX
713         * Check at some point for people who don't have access, etc.
714         */
[1938]715
[752]716        for (ae = mtg_acl->acl_entries, n=mtg_acl->acl_length;
717             n;
718             ae++, n--) {
719                if ((strcmp("*", ae->principal) == 0) &&
720                    acl_is_subset("r", ae->modes))
721                        break;
722        }
723        if (n) {
[1517]724                notice.z_recipient = "";
[752]725                /* We really don't care if it gets through... */
[2743]726                code = ZSendList(&notice,msglst,list_size,ZNOAUTH);
[752]727                return;
728        }
729        for (ae = mtg_acl->acl_entries, n=mtg_acl->acl_length;
730             n;
731             ae++, n--) {
732                if (acl_is_subset("r", ae->modes)) {
733                        notice.z_recipient = ae->principal;
[2743]734                        ZSendList(&notice,msglst,list_size,ZNOAUTH);
[752]735                }
736        }
737}
[12439]738#endif
[11464]739
740static unsigned long swap_32(val)
741unsigned long val;
742{
743     unsigned char b1 = (val >> 24) & 0xff;
744     unsigned char b2 = (val >> 16) & 0xff;
745     unsigned char b3 = (val >> 8) & 0xff;
746     unsigned char b4 = val & 0xff;
747
748     return ((b4 << 24) | (b3 << 16) | (b2 << 8) | b1);
749}
750
751static unsigned int swap_16(val)
752unsigned int val;
753{
754     unsigned char b1 = (val >> 8) & 0xff;
755     unsigned char b2 = val & 0xff;
756
757     return ((b2 << 8) | b1);
758}
759
760swap_super(superp)
761mtg_super *superp;
762{
763     superp->version = swap_32(superp->version);
764     superp->unique = swap_32(superp->unique);
765     superp->first = swap_32(superp->first);
766     superp->last = swap_32(superp->last);
767     superp->lowest = swap_32(superp->lowest);
768     superp->highest = swap_32(superp->highest);
769     superp->highest_chain = swap_32(superp->highest_chain);
770     superp->date_created = swap_32(superp->date_created);
771     superp->date_modified = swap_32(superp->date_modified);
772     superp->long_name_addr = swap_32(superp->long_name_addr);
773     superp->chairman_addr = swap_32(superp->chairman_addr);
774     superp->long_name_len = swap_16(superp->long_name_len);
775     superp->chairman_len = swap_16(superp->chairman_len);
776     superp->flags = swap_16(superp->flags);
777     superp->chain_start = swap_32(superp->chain_start);
778     superp->high_water = swap_32(superp->high_water);
779     superp->trn_fsize = swap_32(superp->trn_fsize);
780     superp->highest_trn_addr = swap_32(superp->highest_trn_addr);
781}
782
783swap_chain(cbp)
784chain_blk *cbp;
785{
786     cbp->version = swap_32(cbp->version);
787     cbp->unique = swap_32(cbp->unique);
788     cbp->current = swap_32(cbp->current);
789     cbp->prev = swap_32(cbp->prev);
790     cbp->next = swap_32(cbp->next);
791     cbp->pref = swap_32(cbp->pref);
792     cbp->nref = swap_32(cbp->nref);
793     cbp->trn_chain = swap_32(cbp->trn_chain);
794     cbp->trn_addr = swap_32(cbp->trn_addr);
795     cbp->flags = swap_16(cbp->flags);
796     cbp->filler = swap_16(cbp->filler);
797     cbp->chain_fref = swap_32(cbp->chain_fref);
798     cbp->chain_lref = swap_32(cbp->chain_lref);
799}
800
801swap_trn_base(tbp)
802trn_base *tbp;
803{
804     tbp->version = swap_32(tbp->version);
805     tbp->unique = swap_32(tbp->unique);
806     tbp->date_created = swap_32(tbp->date_created);
807     tbp->long_name_addr = swap_32(tbp->long_name_addr);
808     tbp->chairman_addr = swap_32(tbp->chairman_addr);
809     tbp->long_name_len = swap_16(tbp->long_name_len);
810     tbp->chairman_len = swap_16(tbp->chairman_len);
811     tbp->public_flag = swap_16(tbp->public_flag);
812}
813
814swap_trn(thp)
815trn_hdr *thp;
816{
817     thp->version = swap_32(thp->version);
818     thp->unique = swap_32(thp->unique);
819     thp->current = swap_32(thp->current);
820     thp->orig_pref = swap_32(thp->orig_pref);
821     thp->date_entered = swap_32(thp->date_entered);
822     thp->num_lines = swap_32(thp->num_lines);
823     thp->num_chars = swap_32(thp->num_chars);
824     thp->prev_trn = swap_32(thp->prev_trn);
825     thp->subject_addr = swap_32(thp->subject_addr);
826     thp->author_addr = swap_32(thp->author_addr);
827     thp->text_addr = swap_32(thp->text_addr);
828     thp->subject_len = swap_16(thp->subject_len);
829     thp->author_len = swap_16(thp->author_len);
830}
Note: See TracBrowser for help on using the repository browser.