1 | /* |
---|
2 | * |
---|
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. |
---|
6 | * |
---|
7 | */ |
---|
8 | /* |
---|
9 | * $Id: coreutil.c,v 1.32 2002-04-06 15:18:55 zacheiss Exp $ |
---|
10 | * |
---|
11 | * |
---|
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 | |
---|
18 | #ifndef lint |
---|
19 | #ifdef __STDC__ |
---|
20 | const |
---|
21 | #endif |
---|
22 | static char rcsid_coreutil_c[] = |
---|
23 | "$Id: coreutil.c,v 1.32 2002-04-06 15:18:55 zacheiss Exp $"; |
---|
24 | #endif /* lint */ |
---|
25 | |
---|
26 | #include <discuss/types.h> |
---|
27 | #include <discuss/dsc_et.h> |
---|
28 | #include "atom.h" |
---|
29 | #include "mtg.h" |
---|
30 | #include <discuss/tfile.h> |
---|
31 | #include <discuss/acl.h> |
---|
32 | #include "internal.h" |
---|
33 | #include "ansi.h" |
---|
34 | #if HAVE_ZEPHYR |
---|
35 | #include <zephyr/zephyr.h> |
---|
36 | #endif |
---|
37 | #include <stdio.h> |
---|
38 | #include <stdlib.h> |
---|
39 | #include <errno.h> |
---|
40 | #include <sys/types.h> |
---|
41 | #include <unistd.h> |
---|
42 | #include <netdb.h> |
---|
43 | #include <sys/file.h> |
---|
44 | #include <sys/stat.h> |
---|
45 | #include <string.h> |
---|
46 | #if HAVE_FCNTL_H |
---|
47 | #include <fcntl.h> |
---|
48 | #endif |
---|
49 | #include <unistd.h> |
---|
50 | |
---|
51 | /* global variables */ |
---|
52 | char current_mtg [256] = ""; /* meeting that's opened */ |
---|
53 | int u_trn_f,u_control_f,u_acl_f; /* UNIX file descriptors */ |
---|
54 | bool nuclear = FALSE; /* Using atomic reads/writes */ |
---|
55 | afile a_control_f = NULL; /* radioactive file descriptor */ |
---|
56 | tfile abort_file = NULL; /* close this on abort */ |
---|
57 | bool read_lock = FALSE; /* have lock on u_control_f */ |
---|
58 | bool mtg_swapped = FALSE; /* current meeting is swapped */ |
---|
59 | dsc_acl *mtg_acl = NULL; /* current mtg acl */ |
---|
60 | int last_acl_mod; /* last mod to ACL */ |
---|
61 | mtg_super super; |
---|
62 | char *super_chairman; |
---|
63 | char *super_long_name; |
---|
64 | int has_privs = 0; /* Has privileges (linked) */ |
---|
65 | int no_nuke = 0; /* Don't be atomic (linked) */ |
---|
66 | #if HAVE_ZEPHYR |
---|
67 | int use_zephyr = 1; /* Actually do use Zephyr. */ |
---|
68 | #else |
---|
69 | int use_zephyr = 0; |
---|
70 | #endif |
---|
71 | |
---|
72 | |
---|
73 | /* EXTERNAL */ |
---|
74 | extern int errno; |
---|
75 | extern char rpc_caller []; |
---|
76 | |
---|
77 | /* |
---|
78 | * |
---|
79 | * new_string (s) -- Routine to create a copy of the given string, using |
---|
80 | * malloc. |
---|
81 | * |
---|
82 | */ |
---|
83 | char *new_string (s) |
---|
84 | char *s; |
---|
85 | { |
---|
86 | int len; |
---|
87 | char *newstr; |
---|
88 | |
---|
89 | len = strlen (s) + 1; |
---|
90 | newstr = malloc ((unsigned)len); |
---|
91 | (void) strcpy (newstr, s); |
---|
92 | return (newstr); |
---|
93 | } |
---|
94 | |
---|
95 | /* |
---|
96 | * |
---|
97 | * open_mtg (mtg_name) -- Routine to open a meeting, if necessary. |
---|
98 | * |
---|
99 | */ |
---|
100 | int open_mtg (mtg_name) |
---|
101 | char *mtg_name; |
---|
102 | { |
---|
103 | char str[256]; |
---|
104 | int result; |
---|
105 | int mtg_name_len; |
---|
106 | trn_base tb; |
---|
107 | int uid = (int)geteuid(); |
---|
108 | struct stat sb; |
---|
109 | |
---|
110 | mtg_name_len = strlen (mtg_name); |
---|
111 | if (mtg_name[0] != '/' || mtg_name_len == 0 || mtg_name_len > 168 |
---|
112 | || mtg_name [mtg_name_len-1] == '/') { |
---|
113 | return (BAD_PATH); |
---|
114 | } |
---|
115 | |
---|
116 | /* Check for moved meeting */ |
---|
117 | (void) strcpy (str, mtg_name); |
---|
118 | (void) strcat (str, "/forward"); |
---|
119 | if (!stat(str, &sb)) { |
---|
120 | return(MTG_MOVED); |
---|
121 | } |
---|
122 | |
---|
123 | (void) strcpy (str, mtg_name); |
---|
124 | (void) strcat (str, "/acl"); |
---|
125 | |
---|
126 | if (!strcmp (mtg_name, current_mtg)) { |
---|
127 | /* |
---|
128 | * is acl stale? |
---|
129 | */ |
---|
130 | if (stat(str, &sb) >= 0) |
---|
131 | if (sb.st_mtime <= last_acl_mod) |
---|
132 | return (0); /* that was easy */ |
---|
133 | } |
---|
134 | |
---|
135 | if (current_mtg [0] != '\0') { /* close previous meeting */ |
---|
136 | if (nuclear) |
---|
137 | panic ("Nuclear flag error"); /* should never happen */ |
---|
138 | (void) close (u_trn_f); |
---|
139 | (void) close (u_control_f); |
---|
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); |
---|
161 | (void) fstat(u_acl_f, &sb); |
---|
162 | last_acl_mod = sb.st_mtime; |
---|
163 | (void) close(u_acl_f); |
---|
164 | u_acl_f = 0; |
---|
165 | |
---|
166 | (void) strcpy (str, mtg_name); |
---|
167 | (void) strcat (str, "/control"); |
---|
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 | |
---|
184 | (void) strcpy (str, mtg_name); |
---|
185 | (void) strcat (str, "/transactions"); |
---|
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)); |
---|
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 | |
---|
210 | if (tb.unique != TRN_BASE_UNIQUE) { |
---|
211 | result = INCONSISTENT; |
---|
212 | goto punt; |
---|
213 | } |
---|
214 | |
---|
215 | (void) strcpy (current_mtg, mtg_name); |
---|
216 | |
---|
217 | return (0); |
---|
218 | |
---|
219 | punt: |
---|
220 | if (u_trn_f) |
---|
221 | (void) close(u_trn_f); |
---|
222 | if (u_control_f) |
---|
223 | (void) close(u_control_f); |
---|
224 | if (u_acl_f) |
---|
225 | (void) close(u_acl_f); |
---|
226 | acl_destroy(mtg_acl); |
---|
227 | mtg_acl = NULL; |
---|
228 | return (result); |
---|
229 | } |
---|
230 | |
---|
231 | |
---|
232 | int read_super() |
---|
233 | { |
---|
234 | if (nuclear) { |
---|
235 | aread (a_control_f, (char *) &super, sizeof(super), 0); |
---|
236 | } else { |
---|
237 | lseek (u_control_f, (long)0, SEEK_SET); |
---|
238 | read (u_control_f, (char *) &super, sizeof (super)); |
---|
239 | } |
---|
240 | |
---|
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 | } |
---|
249 | |
---|
250 | if (super.version != MTG_SUPER_1) |
---|
251 | return (NEW_VERSION); |
---|
252 | |
---|
253 | super_long_name = malloc ((unsigned)super.long_name_len); |
---|
254 | super_chairman = malloc ((unsigned)super.chairman_len); |
---|
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 { |
---|
260 | lseek (u_control_f, (long)super.long_name_addr, SEEK_SET); |
---|
261 | read (u_control_f, super_long_name, super.long_name_len); |
---|
262 | lseek (u_control_f, (long)super.chairman_addr, SEEK_SET); |
---|
263 | read (u_control_f, super_chairman, super.chairman_len); |
---|
264 | } |
---|
265 | |
---|
266 | return(0); |
---|
267 | } |
---|
268 | |
---|
269 | write_super () |
---|
270 | { |
---|
271 | int sc_len, sl_len; |
---|
272 | int slong_name_len, slong_name_addr; |
---|
273 | int schairman_len, schairman_addr; |
---|
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 | |
---|
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 | |
---|
294 | if (nuclear) { |
---|
295 | awrite (a_control_f, (char *) &super, sizeof (super), 0); |
---|
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); |
---|
298 | } else { |
---|
299 | lseek (u_control_f, (long)0, SEEK_SET); |
---|
300 | write (u_control_f, (char *) &super, sizeof (super)); |
---|
301 | lseek (u_control_f, (long)slong_name_addr, SEEK_SET); |
---|
302 | write (u_control_f, super_long_name, slong_name_len); |
---|
303 | lseek (u_control_f, (long)schairman_addr, SEEK_SET); |
---|
304 | write (u_control_f, super_chairman, schairman_len); |
---|
305 | } |
---|
306 | |
---|
307 | free (super_chairman); |
---|
308 | super_chairman = NULL; |
---|
309 | free (super_long_name); |
---|
310 | super_long_name = NULL; |
---|
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 | */ |
---|
322 | forget_super() |
---|
323 | { |
---|
324 | if (super_long_name != NULL) |
---|
325 | free(super_long_name); |
---|
326 | super_long_name = NULL; |
---|
327 | |
---|
328 | if (super_chairman != NULL) |
---|
329 | free(super_chairman); |
---|
330 | super_chairman = NULL; |
---|
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 | */ |
---|
340 | start_read() |
---|
341 | { |
---|
342 | struct flock lock; |
---|
343 | |
---|
344 | if (!no_nuke) { |
---|
345 | lock.l_type = F_RDLCK; |
---|
346 | lock.l_start = 0; |
---|
347 | lock.l_whence = 0; |
---|
348 | lock.l_len = 0; |
---|
349 | if (fcntl(u_control_f, F_SETLKW, &lock) < 0) |
---|
350 | panic ("Cannot share lock"); |
---|
351 | read_lock = TRUE; |
---|
352 | } |
---|
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 | */ |
---|
361 | finish_read() |
---|
362 | { |
---|
363 | struct flock lock; |
---|
364 | |
---|
365 | if (!no_nuke) { |
---|
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); |
---|
371 | read_lock = 0; |
---|
372 | } |
---|
373 | } |
---|
374 | |
---|
375 | /* |
---|
376 | * |
---|
377 | * chain_addr -- Returns address of given chain block. |
---|
378 | * |
---|
379 | */ |
---|
380 | faddr chain_addr(trn) |
---|
381 | trn_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 | |
---|
389 | int read_chain (trn, cb) |
---|
390 | trn_nums trn; |
---|
391 | chain_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 { |
---|
402 | lseek (u_control_f, (long)cbaddr, SEEK_SET); |
---|
403 | read (u_control_f, (char *) cb, sizeof (chain_blk)); |
---|
404 | } |
---|
405 | |
---|
406 | if (mtg_swapped) |
---|
407 | swap_chain(cb); |
---|
408 | |
---|
409 | if (cb -> unique != CHAIN_BLK_UNIQUE || cb -> current != trn) |
---|
410 | return (INCONSISTENT); |
---|
411 | |
---|
412 | if (cb -> version != CHAIN_BLK_1) |
---|
413 | return (NEW_VERSION); |
---|
414 | |
---|
415 | return (0); |
---|
416 | } |
---|
417 | |
---|
418 | int write_chain (cb) |
---|
419 | chain_blk *cb; |
---|
420 | { |
---|
421 | faddr cbaddr; |
---|
422 | |
---|
423 | cbaddr = chain_addr (cb -> current); |
---|
424 | if (cbaddr == 0) |
---|
425 | return (NO_SUCH_TRN); |
---|
426 | |
---|
427 | if (mtg_swapped) |
---|
428 | swap_chain(cb); |
---|
429 | |
---|
430 | if (nuclear) { |
---|
431 | if (awrite (a_control_f, (char *) cb, sizeof (chain_blk), cbaddr) != sizeof (chain_blk)) { |
---|
432 | if (mtg_swapped) |
---|
433 | swap_chain(cb); |
---|
434 | return (NO_WRITE); |
---|
435 | } |
---|
436 | } |
---|
437 | else { |
---|
438 | lseek (u_control_f, (long)cbaddr, SEEK_SET); |
---|
439 | if (write (u_control_f, (char *) cb, sizeof (chain_blk)) != sizeof (chain_blk)) { |
---|
440 | if (mtg_swapped) |
---|
441 | swap_chain(cb); |
---|
442 | return (NO_WRITE); |
---|
443 | } |
---|
444 | } |
---|
445 | |
---|
446 | if (mtg_swapped) |
---|
447 | swap_chain(cb); |
---|
448 | return (0); |
---|
449 | } |
---|
450 | |
---|
451 | /* |
---|
452 | * |
---|
453 | * read_trn -- routine to read a transaction from the transaction file. |
---|
454 | * |
---|
455 | */ |
---|
456 | int read_trn (trn_addr, th, th_subject, th_author, th_signature) |
---|
457 | faddr trn_addr; |
---|
458 | trn_hdr *th; |
---|
459 | char **th_subject, **th_author, **th_signature; |
---|
460 | { |
---|
461 | char *author; |
---|
462 | |
---|
463 | lseek (u_trn_f, (long)trn_addr, SEEK_SET); |
---|
464 | read (u_trn_f, (char *) th, sizeof (trn_hdr)); |
---|
465 | |
---|
466 | if (mtg_swapped) |
---|
467 | swap_trn(th); |
---|
468 | |
---|
469 | if (th -> unique != TRN_HDR_UNIQUE) |
---|
470 | return (INCONSISTENT); |
---|
471 | |
---|
472 | if (th -> version != TRN_HDR_1) |
---|
473 | return(NEW_VERSION); |
---|
474 | |
---|
475 | if (th_subject != NULL) { |
---|
476 | *th_subject = malloc ((unsigned)(th -> subject_len)); |
---|
477 | lseek (u_trn_f, (long)(th -> subject_addr), SEEK_SET); |
---|
478 | read (u_trn_f, *th_subject, th -> subject_len); |
---|
479 | } |
---|
480 | |
---|
481 | if (th_author != NULL || th_signature != NULL) { |
---|
482 | author = malloc ((unsigned)(th -> author_len)); |
---|
483 | lseek (u_trn_f, (long)(th -> author_addr), SEEK_SET); |
---|
484 | read (u_trn_f, author, th -> author_len); |
---|
485 | } |
---|
486 | |
---|
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 | |
---|
500 | return(0); |
---|
501 | } |
---|
502 | |
---|
503 | |
---|
504 | /* |
---|
505 | * |
---|
506 | * core_abort () -- Routine for use by core routines to clean things up. |
---|
507 | * |
---|
508 | */ |
---|
509 | core_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 | |
---|
526 | forget_super(); |
---|
527 | |
---|
528 | return; |
---|
529 | } |
---|
530 | |
---|
531 | /* |
---|
532 | * |
---|
533 | * fsize () -- Routine to find out the size of a file. |
---|
534 | * |
---|
535 | */ |
---|
536 | fsize (d) |
---|
537 | int 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 | */ |
---|
551 | fis_owner (d, uid) |
---|
552 | int 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 | */ |
---|
568 | bool has_trn_access(author,mode) |
---|
569 | char *author; |
---|
570 | char mode; |
---|
571 | { |
---|
572 | char *test_modes; |
---|
573 | |
---|
574 | if (has_privs) |
---|
575 | return(TRUE); /* linked in */ |
---|
576 | |
---|
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"); |
---|
591 | /*NOTREACHED*/ |
---|
592 | } |
---|
593 | } |
---|
594 | /* |
---|
595 | * |
---|
596 | * has_mtg_access -- Routine to return true if current user can access |
---|
597 | * mtg, with given mode. |
---|
598 | * |
---|
599 | */ |
---|
600 | bool has_mtg_access(mode) |
---|
601 | char mode; |
---|
602 | { |
---|
603 | char *test_modes; |
---|
604 | char mode_str[3]; |
---|
605 | |
---|
606 | if (has_privs) /* linked in stuff */ |
---|
607 | return (TRUE); |
---|
608 | |
---|
609 | switch (mode) { |
---|
610 | case 'w': |
---|
611 | case 'a': |
---|
612 | case 'r': |
---|
613 | case 's': |
---|
614 | case 'o': |
---|
615 | mode_str[0] = mode; |
---|
616 | mode_str[1] = '\0'; |
---|
617 | test_modes = mode_str; |
---|
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 | */ |
---|
635 | panic(str) |
---|
636 | char *str; |
---|
637 | { |
---|
638 | printf("panic: %s\n",str); |
---|
639 | perror("discuss"); |
---|
640 | exit(1); |
---|
641 | } |
---|
642 | |
---|
643 | #if HAVE_ZEPHYR |
---|
644 | /* |
---|
645 | * |
---|
646 | * mtg_znotify -- send off a Zephyr notification as appropriate |
---|
647 | * |
---|
648 | */ |
---|
649 | |
---|
650 | static const char * this_host = (const char *) NULL; |
---|
651 | |
---|
652 | void mtg_znotify(mtg_name, subject, author, signature) |
---|
653 | char *mtg_name, *subject, *author, *signature; |
---|
654 | { |
---|
655 | register dsc_acl_entry *ae; |
---|
656 | register int n; |
---|
657 | ZNotice_t notice; |
---|
658 | char *msglst[5],bfr[30],fullpath[256]; |
---|
659 | int code, list_size; |
---|
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 | |
---|
682 | /* Set up the notice structure */ |
---|
683 | memset(¬ice, 0, sizeof(notice)); |
---|
684 | |
---|
685 | sprintf(fullpath,"%s:%s", this_host, mtg_name); |
---|
686 | ZOpenPort(NULL); |
---|
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; |
---|
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"; |
---|
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; |
---|
702 | list_size = 4; |
---|
703 | if (signature != NULL) { |
---|
704 | msglst[4] = signature; |
---|
705 | list_size = 5; |
---|
706 | } |
---|
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 | */ |
---|
715 | |
---|
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) { |
---|
724 | notice.z_recipient = ""; |
---|
725 | /* We really don't care if it gets through... */ |
---|
726 | code = ZSendList(¬ice,msglst,list_size,ZNOAUTH); |
---|
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; |
---|
734 | ZSendList(¬ice,msglst,list_size,ZNOAUTH); |
---|
735 | } |
---|
736 | } |
---|
737 | } |
---|
738 | #endif |
---|
739 | |
---|
740 | static unsigned long swap_32(val) |
---|
741 | unsigned 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 | |
---|
751 | static unsigned int swap_16(val) |
---|
752 | unsigned int val; |
---|
753 | { |
---|
754 | unsigned char b1 = (val >> 8) & 0xff; |
---|
755 | unsigned char b2 = val & 0xff; |
---|
756 | |
---|
757 | return ((b2 << 8) | b1); |
---|
758 | } |
---|
759 | |
---|
760 | swap_super(superp) |
---|
761 | mtg_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 | |
---|
783 | swap_chain(cbp) |
---|
784 | chain_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 | |
---|
801 | swap_trn_base(tbp) |
---|
802 | trn_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 | |
---|
814 | swap_trn(thp) |
---|
815 | trn_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 | } |
---|