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 | * $Source: /afs/dev.mit.edu/source/repository/athena/bin/discuss/server/coreutil.c,v $ |
---|
10 | * $Header: /afs/dev.mit.edu/source/repository/athena/bin/discuss/server/coreutil.c,v 1.22 1990-02-24 20:05:09 srz Exp $ |
---|
11 | * |
---|
12 | * |
---|
13 | * coreutil.c -- These contain lower-layer, utility type routines to |
---|
14 | * be used by core. These include things to handle the |
---|
15 | * in-memory superblock, and to open & close meetings. |
---|
16 | * |
---|
17 | * $Log: not supported by cvs2svn $ |
---|
18 | * Revision 1.21 90/02/24 18:56:30 srz |
---|
19 | * Changed read_trn to return the signature (if it exists), and changed |
---|
20 | * mtg_znotify to handle the signature if it exists. |
---|
21 | * |
---|
22 | * Revision 1.20 89/09/01 11:54:13 srz |
---|
23 | * Defined use_zephyr variable, even when ZEPHYR is not defined. |
---|
24 | * |
---|
25 | * Revision 1.19 89/09/01 11:51:18 srz |
---|
26 | * Fixed memory leak, and cut connection between super_chairman and access. |
---|
27 | * |
---|
28 | * Revision 1.18 89/08/09 22:39:43 srz |
---|
29 | * Added meeting forwarding. |
---|
30 | * |
---|
31 | * Revision 1.17 89/06/03 00:42:34 srz |
---|
32 | * Added standard copyright notice. |
---|
33 | * |
---|
34 | * Revision 1.16 89/06/03 00:36:43 srz |
---|
35 | * Include file fixups, more efficient Zephyr service. |
---|
36 | * |
---|
37 | * Revision 1.15 88/10/13 01:26:29 discuss |
---|
38 | * Fixed Zephyr stuff. Can you say, "Insufficient documentation?" -srz |
---|
39 | * |
---|
40 | * Revision 1.14 88/10/08 03:28:49 srz |
---|
41 | * Attempt at fixing Zephyr (doesn't work). |
---|
42 | * |
---|
43 | * Revision 1.13 88/10/08 01:28:26 srz |
---|
44 | * Changes for new expunge. Fix to Zephyr stuff. |
---|
45 | * |
---|
46 | * Revision 1.12 88/09/23 17:07:33 raeburn |
---|
47 | * Changed type names in accordance with acl.h. Included include/internal.h. |
---|
48 | * |
---|
49 | * Revision 1.11 88/03/06 19:53:28 srz |
---|
50 | * Reversed order of checking magic number and version, so that |
---|
51 | * INCONSISTENT is returned instead of NEW_VERSION when that |
---|
52 | * is trully the case. |
---|
53 | * |
---|
54 | * Revision 1.10 88/01/05 01:37:54 srz |
---|
55 | * Really ifdef'd zephyr. |
---|
56 | * |
---|
57 | * Revision 1.9 88/01/05 01:08:02 rfrench |
---|
58 | * #ifdef'd ZEPHYR stuff |
---|
59 | * |
---|
60 | * Revision 1.8 87/08/22 18:12:30 rfrench |
---|
61 | * Added Zephyr notifications |
---|
62 | * |
---|
63 | * Revision 1.7 87/03/25 15:04:31 srz |
---|
64 | * toma change: Expanded has_mtg_access to take more modes as arguments |
---|
65 | * |
---|
66 | * Revision 1.6 87/03/17 02:24:10 srz |
---|
67 | * Added expunging. An ACL change will require meeting to be reopened, in |
---|
68 | * case an expunge is taking place. Also added has_privs, which allows |
---|
69 | * wheel access for programs that are linked in. |
---|
70 | * |
---|
71 | * Revision 1.5 87/03/11 18:00:27 srz |
---|
72 | * Made sure that write's were error checked. |
---|
73 | * |
---|
74 | * Revision 1.4 87/02/04 15:48:18 srz |
---|
75 | * When there is a choice between making lint happy or cc happy, I tend |
---|
76 | * to prefer 'cc'. uid_t is not in 4.2 BSD. |
---|
77 | * |
---|
78 | * Revision 1.3 86/11/22 06:25:42 spook |
---|
79 | * Changed to make lint happy. |
---|
80 | * |
---|
81 | * Revision 1.2 86/11/16 06:05:37 wesommer |
---|
82 | * Changed open_mtg to stat(2) the acl file before assuming that it's |
---|
83 | * up to date, and revert the acl from there if the in-core version |
---|
84 | * is stale. |
---|
85 | * |
---|
86 | */ |
---|
87 | |
---|
88 | #ifndef lint |
---|
89 | #ifdef __STDC__ |
---|
90 | const |
---|
91 | #endif |
---|
92 | static char rcsid_coreutil_c[] = |
---|
93 | "$Header: /afs/dev.mit.edu/source/repository/athena/bin/discuss/server/coreutil.c,v 1.22 1990-02-24 20:05:09 srz Exp $"; |
---|
94 | #endif /* lint */ |
---|
95 | |
---|
96 | #include <discuss/types.h> |
---|
97 | #include <discuss/dsc_et.h> |
---|
98 | #include "atom.h" |
---|
99 | #include "mtg.h" |
---|
100 | #include <discuss/tfile.h> |
---|
101 | #include <discuss/acl.h> |
---|
102 | #include "internal.h" |
---|
103 | #include "ansi.h" |
---|
104 | #ifdef ZEPHYR |
---|
105 | #include <zephyr/zephyr.h> |
---|
106 | #endif ZEPHYR |
---|
107 | #include <errno.h> |
---|
108 | #include <sys/types.h> |
---|
109 | #include <netdb.h> |
---|
110 | #include <sys/file.h> |
---|
111 | #include <sys/stat.h> |
---|
112 | #include <strings.h> |
---|
113 | |
---|
114 | #define NULL 0 |
---|
115 | |
---|
116 | /* global variables */ |
---|
117 | char current_mtg [256] = ""; /* meeting that's opened */ |
---|
118 | int u_trn_f,u_control_f,u_acl_f; /* UNIX file descriptors */ |
---|
119 | bool nuclear = FALSE; /* Using atomic reads/writes */ |
---|
120 | afile a_control_f = NULL; /* radioactive file descriptor */ |
---|
121 | tfile abort_file = NULL; /* close this on abort */ |
---|
122 | bool read_lock = FALSE; /* have lock on u_control_f */ |
---|
123 | dsc_acl *mtg_acl = NULL; /* current mtg acl */ |
---|
124 | int last_acl_mod; /* last mod to ACL */ |
---|
125 | mtg_super super; |
---|
126 | char *super_chairman; |
---|
127 | char *super_long_name; |
---|
128 | int has_privs = 0; /* Has privileges (linked) */ |
---|
129 | int no_nuke = 0; /* Don't be atomic (linked) */ |
---|
130 | #ifdef ZEPHYR |
---|
131 | int use_zephyr = 1; /* Actually do use Zephyr. */ |
---|
132 | #else |
---|
133 | int use_zephyr = 0; |
---|
134 | #endif |
---|
135 | |
---|
136 | |
---|
137 | /* EXTERNAL */ |
---|
138 | extern char *malloc(); |
---|
139 | extern off_t lseek(); |
---|
140 | extern int errno; |
---|
141 | extern char rpc_caller []; |
---|
142 | |
---|
143 | /* |
---|
144 | * |
---|
145 | * new_string (s) -- Routine to create a copy of the given string, using |
---|
146 | * malloc. |
---|
147 | * |
---|
148 | */ |
---|
149 | char *new_string (s) |
---|
150 | char *s; |
---|
151 | { |
---|
152 | int len; |
---|
153 | char *newstr; |
---|
154 | |
---|
155 | len = strlen (s) + 1; |
---|
156 | newstr = malloc ((unsigned)len); |
---|
157 | (void) strcpy (newstr, s); |
---|
158 | return (newstr); |
---|
159 | } |
---|
160 | |
---|
161 | /* |
---|
162 | * |
---|
163 | * open_mtg (mtg_name) -- Routine to open a meeting, if necessary. |
---|
164 | * |
---|
165 | */ |
---|
166 | int open_mtg (mtg_name) |
---|
167 | char *mtg_name; |
---|
168 | { |
---|
169 | char str[256]; |
---|
170 | int result; |
---|
171 | int mtg_name_len; |
---|
172 | trn_base tb; |
---|
173 | int uid = (int)geteuid(); |
---|
174 | struct stat sb; |
---|
175 | |
---|
176 | mtg_name_len = strlen (mtg_name); |
---|
177 | if (mtg_name[0] != '/' || mtg_name_len == 0 || mtg_name_len > 168 |
---|
178 | || mtg_name [mtg_name_len-1] == '/') { |
---|
179 | return (BAD_PATH); |
---|
180 | } |
---|
181 | |
---|
182 | /* Check for moved meeting */ |
---|
183 | (void) strcpy (str, mtg_name); |
---|
184 | (void) strcat (str, "/forward"); |
---|
185 | if (!stat(str, &sb)) { |
---|
186 | return(MTG_MOVED); |
---|
187 | } |
---|
188 | |
---|
189 | (void) strcpy (str, mtg_name); |
---|
190 | (void) strcat (str, "/acl"); |
---|
191 | |
---|
192 | if (!strcmp (mtg_name, current_mtg)) { |
---|
193 | /* |
---|
194 | * is acl stale? |
---|
195 | */ |
---|
196 | if (stat(str, &sb) >= 0) |
---|
197 | if (sb.st_mtime <= last_acl_mod) |
---|
198 | return (0); /* that was easy */ |
---|
199 | } |
---|
200 | |
---|
201 | if (current_mtg [0] != '\0') { /* close previous meeting */ |
---|
202 | if (nuclear) |
---|
203 | panic ("Nuclear flag error"); /* should never happen */ |
---|
204 | (void) close (u_trn_f); |
---|
205 | (void) close (u_control_f); |
---|
206 | current_mtg [0] = '\0'; |
---|
207 | acl_destroy(mtg_acl); |
---|
208 | } |
---|
209 | |
---|
210 | u_trn_f = u_control_f = u_acl_f = 0; |
---|
211 | |
---|
212 | if ((u_acl_f = open(str, O_RDONLY, 0700)) < 0) { |
---|
213 | if (errno == ENOENT) |
---|
214 | result = NO_SUCH_MTG; |
---|
215 | else if (errno == EACCES) |
---|
216 | result = NO_ACCESS; |
---|
217 | else |
---|
218 | result = BAD_PATH; |
---|
219 | goto punt; |
---|
220 | } |
---|
221 | if (!fis_owner (u_acl_f, uid)) { |
---|
222 | result = NO_ACCESS; |
---|
223 | goto punt; |
---|
224 | } |
---|
225 | |
---|
226 | mtg_acl = acl_read (u_acl_f); |
---|
227 | (void) fstat(u_acl_f, &sb); |
---|
228 | last_acl_mod = sb.st_mtime; |
---|
229 | (void) close(u_acl_f); |
---|
230 | u_acl_f = 0; |
---|
231 | |
---|
232 | (void) strcpy (str, mtg_name); |
---|
233 | (void) strcat (str, "/control"); |
---|
234 | |
---|
235 | if ((u_control_f = open(str, O_RDWR, 0700)) < 0) { |
---|
236 | if (errno == ENOENT) |
---|
237 | result = NO_SUCH_MTG; |
---|
238 | else if (errno == EACCES) |
---|
239 | result = NO_ACCESS; |
---|
240 | else |
---|
241 | result = BAD_PATH; |
---|
242 | goto punt; |
---|
243 | } |
---|
244 | |
---|
245 | if (!fis_owner (u_control_f, uid)) { |
---|
246 | result = NO_ACCESS; |
---|
247 | goto punt; |
---|
248 | } |
---|
249 | |
---|
250 | (void) strcpy (str, mtg_name); |
---|
251 | (void) strcat (str, "/transactions"); |
---|
252 | |
---|
253 | if ((u_trn_f = open(str, O_RDWR, 0700)) < 0) { |
---|
254 | if (errno == ENOENT) |
---|
255 | result = NO_SUCH_MTG; |
---|
256 | else if (errno == EACCES) |
---|
257 | result = NO_ACCESS; |
---|
258 | else |
---|
259 | result = BAD_PATH; |
---|
260 | goto punt; |
---|
261 | } |
---|
262 | |
---|
263 | if (!fis_owner (u_trn_f, uid)) { |
---|
264 | result = NO_ACCESS; |
---|
265 | goto punt; |
---|
266 | } |
---|
267 | |
---|
268 | read (u_trn_f, (char *) &tb, sizeof (trn_base)); |
---|
269 | if (tb.unique != TRN_BASE_UNIQUE) { |
---|
270 | result = INCONSISTENT; |
---|
271 | goto punt; |
---|
272 | } |
---|
273 | |
---|
274 | (void) strcpy (current_mtg, mtg_name); |
---|
275 | |
---|
276 | return (0); |
---|
277 | |
---|
278 | punt: |
---|
279 | if (u_trn_f) |
---|
280 | (void) close(u_trn_f); |
---|
281 | if (u_control_f) |
---|
282 | (void) close(u_control_f); |
---|
283 | if (u_acl_f) |
---|
284 | (void) close(u_acl_f); |
---|
285 | acl_destroy(mtg_acl); |
---|
286 | mtg_acl = NULL; |
---|
287 | return (result); |
---|
288 | } |
---|
289 | |
---|
290 | |
---|
291 | int read_super() |
---|
292 | { |
---|
293 | if (nuclear) { |
---|
294 | aread (a_control_f, (char *) &super, sizeof(super), 0); |
---|
295 | } else { |
---|
296 | lseek (u_control_f, (long)0, 0); |
---|
297 | read (u_control_f, (char *) &super, sizeof (super)); |
---|
298 | } |
---|
299 | |
---|
300 | if (super.unique != MTG_SUPER_UNIQUE) |
---|
301 | return (INCONSISTENT); |
---|
302 | |
---|
303 | if (super.version != MTG_SUPER_1) |
---|
304 | return (NEW_VERSION); |
---|
305 | |
---|
306 | super_long_name = malloc ((unsigned)super.long_name_len); |
---|
307 | super_chairman = malloc ((unsigned)super.chairman_len); |
---|
308 | |
---|
309 | if (nuclear) { |
---|
310 | aread (a_control_f, super_long_name, super.long_name_len, super.long_name_addr); |
---|
311 | aread (a_control_f, super_chairman, super.chairman_len, super.chairman_addr); |
---|
312 | } else { |
---|
313 | lseek (u_control_f, (long)super.long_name_addr, 0); |
---|
314 | read (u_control_f, super_long_name, super.long_name_len); |
---|
315 | lseek (u_control_f, (long)super.chairman_addr, 0); |
---|
316 | read (u_control_f, super_chairman, super.chairman_len); |
---|
317 | } |
---|
318 | |
---|
319 | return(0); |
---|
320 | } |
---|
321 | |
---|
322 | write_super () |
---|
323 | { |
---|
324 | int sc_len, sl_len; |
---|
325 | |
---|
326 | sc_len = strlen (super_chairman)+1; |
---|
327 | sl_len = strlen (super_long_name)+1; |
---|
328 | |
---|
329 | if (sc_len != super.chairman_len || sl_len != super.long_name_len) { /* reallocate things */ |
---|
330 | super.long_name_addr = sizeof (super); |
---|
331 | super.long_name_len = sl_len; |
---|
332 | super.chairman_addr = super.long_name_addr + super.long_name_len; |
---|
333 | super.chairman_len = sc_len; |
---|
334 | } |
---|
335 | |
---|
336 | if (nuclear) { |
---|
337 | awrite (a_control_f, (char *) &super, sizeof (super), 0); |
---|
338 | awrite (a_control_f, super_long_name, super.long_name_len, super.long_name_addr); |
---|
339 | awrite (a_control_f, super_chairman, super.chairman_len, super.chairman_addr); |
---|
340 | } else { |
---|
341 | lseek (u_control_f, (long)0, 0); |
---|
342 | write (u_control_f, (char *) &super, sizeof (super)); |
---|
343 | lseek (u_control_f, (long)super.long_name_addr, 0); |
---|
344 | write (u_control_f, super_long_name, super.long_name_len); |
---|
345 | lseek (u_control_f, (long)super.chairman_addr, 0); |
---|
346 | write (u_control_f, super_chairman, super.chairman_len); |
---|
347 | } |
---|
348 | |
---|
349 | free (super_chairman); |
---|
350 | super_chairman = NULL; |
---|
351 | free (super_long_name); |
---|
352 | super_long_name = NULL; |
---|
353 | super.unique = 0; /* prevent accidents */ |
---|
354 | |
---|
355 | return; |
---|
356 | } |
---|
357 | |
---|
358 | /* |
---|
359 | * |
---|
360 | * forget_super () -- Routine to dump superblock, like when we just read |
---|
361 | * it. This frees any alloc'd storage. |
---|
362 | * |
---|
363 | */ |
---|
364 | forget_super() |
---|
365 | { |
---|
366 | if (super_long_name != NULL) |
---|
367 | free(super_long_name); |
---|
368 | super_long_name = NULL; |
---|
369 | |
---|
370 | if (super_chairman != NULL) |
---|
371 | free(super_chairman); |
---|
372 | super_chairman = NULL; |
---|
373 | super.unique = 0; |
---|
374 | } |
---|
375 | |
---|
376 | /* |
---|
377 | * |
---|
378 | * start_read () -- This reserves the meeting for non-destructive reading. |
---|
379 | * Simply does an flock. |
---|
380 | * |
---|
381 | */ |
---|
382 | start_read() |
---|
383 | { |
---|
384 | if (!no_nuke) { |
---|
385 | if (flock (u_control_f, LOCK_SH) < 0) |
---|
386 | panic ("Cannot share lock"); |
---|
387 | read_lock = TRUE; |
---|
388 | } |
---|
389 | } |
---|
390 | |
---|
391 | /* |
---|
392 | * |
---|
393 | * finish_read () -- This frees up our reservation on the meeting. This |
---|
394 | * does the opposite of start_read. |
---|
395 | * |
---|
396 | */ |
---|
397 | finish_read() |
---|
398 | { |
---|
399 | if (!no_nuke) { |
---|
400 | flock(u_control_f,LOCK_UN); |
---|
401 | read_lock = 0; |
---|
402 | } |
---|
403 | } |
---|
404 | |
---|
405 | /* |
---|
406 | * |
---|
407 | * chain_addr -- Returns address of given chain block. |
---|
408 | * |
---|
409 | */ |
---|
410 | faddr chain_addr(trn) |
---|
411 | trn_nums trn; |
---|
412 | { |
---|
413 | if (trn < super.lowest || trn > super.highest) |
---|
414 | return (0); |
---|
415 | |
---|
416 | return (super.chain_start + (trn-1) * sizeof (chain_blk)); |
---|
417 | } |
---|
418 | |
---|
419 | int read_chain (trn, cb) |
---|
420 | trn_nums trn; |
---|
421 | chain_blk *cb; |
---|
422 | { |
---|
423 | faddr cbaddr; |
---|
424 | |
---|
425 | cbaddr = chain_addr (trn); |
---|
426 | if (cbaddr == 0) |
---|
427 | return (NO_SUCH_TRN); |
---|
428 | |
---|
429 | if (nuclear) |
---|
430 | aread (a_control_f, (char *) cb, sizeof (chain_blk), cbaddr); |
---|
431 | else { |
---|
432 | lseek (u_control_f, (long)cbaddr, 0); |
---|
433 | read (u_control_f, (char *) cb, sizeof (chain_blk)); |
---|
434 | } |
---|
435 | |
---|
436 | if (cb -> unique != CHAIN_BLK_UNIQUE || cb -> current != trn) |
---|
437 | return (INCONSISTENT); |
---|
438 | |
---|
439 | if (cb -> version != CHAIN_BLK_1) |
---|
440 | return (NEW_VERSION); |
---|
441 | |
---|
442 | return (0); |
---|
443 | } |
---|
444 | |
---|
445 | int write_chain (cb) |
---|
446 | chain_blk *cb; |
---|
447 | { |
---|
448 | faddr cbaddr; |
---|
449 | |
---|
450 | cbaddr = chain_addr (cb -> current); |
---|
451 | if (cbaddr == 0) |
---|
452 | return (NO_SUCH_TRN); |
---|
453 | |
---|
454 | if (nuclear) { |
---|
455 | if (awrite (a_control_f, (char *) cb, sizeof (chain_blk), cbaddr) != sizeof (chain_blk)) |
---|
456 | return (NO_WRITE); |
---|
457 | } |
---|
458 | else { |
---|
459 | lseek (u_control_f, (long)cbaddr, 0); |
---|
460 | if (write (u_control_f, (char *) cb, sizeof (chain_blk)) != sizeof (chain_blk)) |
---|
461 | return (NO_WRITE); |
---|
462 | } |
---|
463 | |
---|
464 | return (0); |
---|
465 | } |
---|
466 | |
---|
467 | /* |
---|
468 | * |
---|
469 | * read_trn -- routine to read a transaction from the transaction file. |
---|
470 | * |
---|
471 | */ |
---|
472 | int read_trn (trn_addr, th, th_subject, th_author, th_signature) |
---|
473 | faddr trn_addr; |
---|
474 | trn_hdr *th; |
---|
475 | char **th_subject, **th_author, **th_signature; |
---|
476 | { |
---|
477 | char *author; |
---|
478 | |
---|
479 | lseek (u_trn_f, (long)trn_addr, 0); |
---|
480 | read (u_trn_f, (char *) th, sizeof (trn_hdr)); |
---|
481 | |
---|
482 | if (th -> unique != TRN_HDR_UNIQUE) |
---|
483 | return (INCONSISTENT); |
---|
484 | |
---|
485 | if (th -> version != TRN_HDR_1) |
---|
486 | return(NEW_VERSION); |
---|
487 | |
---|
488 | if (th_subject != NULL) { |
---|
489 | *th_subject = malloc ((unsigned)(th -> subject_len)); |
---|
490 | lseek (u_trn_f, (long)(th -> subject_addr), 0); |
---|
491 | read (u_trn_f, *th_subject, th -> subject_len); |
---|
492 | } |
---|
493 | |
---|
494 | if (th_author != NULL || th_signature != NULL) { |
---|
495 | author = malloc ((unsigned)(th -> author_len)); |
---|
496 | lseek (u_trn_f, (long)(th -> author_addr), 0); |
---|
497 | read (u_trn_f, author, th -> author_len); |
---|
498 | } |
---|
499 | |
---|
500 | if (th_author != NULL) |
---|
501 | *th_author = author; |
---|
502 | |
---|
503 | if (th_signature != NULL) { |
---|
504 | if (strlen(author)+1 == th -> author_len) { |
---|
505 | *th_signature = new_string(author); /* No signature, return author */ |
---|
506 | } else { |
---|
507 | *th_signature = new_string(&author[strlen(author)+1]); |
---|
508 | } |
---|
509 | if (th_author == NULL) |
---|
510 | free(author); |
---|
511 | } |
---|
512 | |
---|
513 | return(0); |
---|
514 | } |
---|
515 | |
---|
516 | |
---|
517 | /* |
---|
518 | * |
---|
519 | * core_abort () -- Routine for use by core routines to clean things up. |
---|
520 | * |
---|
521 | */ |
---|
522 | core_abort () |
---|
523 | { |
---|
524 | int dummy; |
---|
525 | |
---|
526 | if (nuclear) { |
---|
527 | aabort(a_control_f); |
---|
528 | nuclear = FALSE; |
---|
529 | } |
---|
530 | |
---|
531 | if (abort_file != NULL) { |
---|
532 | tclose (abort_file,&dummy); |
---|
533 | abort_file = NULL; |
---|
534 | } |
---|
535 | |
---|
536 | if (read_lock) |
---|
537 | finish_read(); |
---|
538 | |
---|
539 | forget_super(); |
---|
540 | |
---|
541 | return; |
---|
542 | } |
---|
543 | |
---|
544 | /* |
---|
545 | * |
---|
546 | * fsize () -- Routine to find out the size of a file. |
---|
547 | * |
---|
548 | */ |
---|
549 | fsize (d) |
---|
550 | int d; |
---|
551 | { |
---|
552 | struct stat buf; |
---|
553 | |
---|
554 | if (fstat (d, &buf) < 0) |
---|
555 | return (0); |
---|
556 | |
---|
557 | return (buf.st_size); |
---|
558 | } |
---|
559 | /* |
---|
560 | * |
---|
561 | * fis_owner () -- Routine to find out if uid is owner of file. |
---|
562 | * |
---|
563 | */ |
---|
564 | fis_owner (d, uid) |
---|
565 | int d,uid; |
---|
566 | { |
---|
567 | struct stat buf; |
---|
568 | |
---|
569 | if (fstat (d, &buf) < 0) |
---|
570 | return (0); |
---|
571 | |
---|
572 | return (uid == buf.st_uid); |
---|
573 | } |
---|
574 | |
---|
575 | /* |
---|
576 | * |
---|
577 | * has_trn_access -- Routine to return true if current user can access |
---|
578 | * transaction. |
---|
579 | * |
---|
580 | */ |
---|
581 | bool has_trn_access(author,mode) |
---|
582 | char *author; |
---|
583 | char mode; |
---|
584 | { |
---|
585 | char *test_modes; |
---|
586 | |
---|
587 | if (has_privs) |
---|
588 | return(TRUE); /* linked in */ |
---|
589 | |
---|
590 | switch (mode) { |
---|
591 | case 'd': |
---|
592 | if (!strcmp(author,rpc_caller)) { |
---|
593 | test_modes = "o"; |
---|
594 | } else { |
---|
595 | test_modes = "d"; |
---|
596 | } |
---|
597 | return (acl_check(mtg_acl,rpc_caller,test_modes)); |
---|
598 | |
---|
599 | case 'r': |
---|
600 | return (acl_check(mtg_acl,rpc_caller,"r") || |
---|
601 | ((!strcmp (author, rpc_caller)) && acl_check(mtg_acl,rpc_caller,"o"))); |
---|
602 | default: |
---|
603 | panic ("Invalid mode"); |
---|
604 | /*NOTREACHED*/ |
---|
605 | } |
---|
606 | } |
---|
607 | /* |
---|
608 | * |
---|
609 | * has_mtg_access -- Routine to return true if current user can access |
---|
610 | * mtg, with given mode. |
---|
611 | * |
---|
612 | */ |
---|
613 | bool has_mtg_access(mode) |
---|
614 | char mode; |
---|
615 | { |
---|
616 | char *test_modes; |
---|
617 | char mode_str[3]; |
---|
618 | |
---|
619 | if (has_privs) /* linked in stuff */ |
---|
620 | return (TRUE); |
---|
621 | |
---|
622 | switch (mode) { |
---|
623 | case 'w': |
---|
624 | case 'a': |
---|
625 | case 'r': |
---|
626 | case 's': |
---|
627 | case 'o': |
---|
628 | mode_str[0] = mode; |
---|
629 | mode_str[1] = '\0'; |
---|
630 | test_modes = mode_str; |
---|
631 | break; |
---|
632 | |
---|
633 | case 'c': |
---|
634 | test_modes = "c"; |
---|
635 | break; |
---|
636 | |
---|
637 | default: |
---|
638 | panic("Invalid mode"); |
---|
639 | } |
---|
640 | |
---|
641 | return(acl_check(mtg_acl,rpc_caller,test_modes)); |
---|
642 | } |
---|
643 | /* |
---|
644 | * |
---|
645 | * panic -- just a printf |
---|
646 | * |
---|
647 | */ |
---|
648 | panic(str) |
---|
649 | char *str; |
---|
650 | { |
---|
651 | printf("panic: %s\n",str); |
---|
652 | perror("discuss"); |
---|
653 | exit(1); |
---|
654 | } |
---|
655 | |
---|
656 | #ifdef ZEPHYR |
---|
657 | /* |
---|
658 | * |
---|
659 | * mtg_znotify -- send off a Zephyr notification as appropriate |
---|
660 | * |
---|
661 | */ |
---|
662 | |
---|
663 | static const char * this_host = (const char *) NULL; |
---|
664 | |
---|
665 | void mtg_znotify(mtg_name, subject, author, signature) |
---|
666 | char *mtg_name, *subject, *author, *signature; |
---|
667 | { |
---|
668 | register dsc_acl_entry *ae; |
---|
669 | register int n; |
---|
670 | ZNotice_t notice; |
---|
671 | char *msglst[5],bfr[30],fullpath[256]; |
---|
672 | int code, list_size; |
---|
673 | |
---|
674 | if (!use_zephyr) |
---|
675 | return; |
---|
676 | |
---|
677 | if (!this_host) { |
---|
678 | /* perform initializations */ |
---|
679 | char *h; |
---|
680 | char host[100]; |
---|
681 | struct hostent *hent; |
---|
682 | if (gethostname(host,100) != 0) |
---|
683 | return; |
---|
684 | hent = (struct hostent *) gethostbyname(host); |
---|
685 | if (hent == 0) |
---|
686 | return; |
---|
687 | h = (char *) malloc (strlen (hent->h_name) + 1); |
---|
688 | if (!h) |
---|
689 | return; |
---|
690 | strcpy (h, hent->h_name); |
---|
691 | this_host = h; |
---|
692 | ZInitialize(); |
---|
693 | } |
---|
694 | |
---|
695 | /* Set up the notice structure */ |
---|
696 | bzero(¬ice, sizeof(notice)); |
---|
697 | |
---|
698 | sprintf(fullpath,"%s:%s", this_host, mtg_name); |
---|
699 | ZOpenPort(NULL); |
---|
700 | notice.z_kind = UNSAFE; |
---|
701 | notice.z_port = 0; |
---|
702 | notice.z_class = "DISCUSS"; |
---|
703 | notice.z_class_inst = fullpath; |
---|
704 | notice.z_opcode = "NEW_TRN"; |
---|
705 | notice.z_sender = 0; |
---|
706 | if (signature == NULL) |
---|
707 | notice.z_default_format = "New transaction [$1] entered in $2\nFrom: $3\nSubject: $4"; |
---|
708 | else |
---|
709 | notice.z_default_format = "New transaction [$1] entered in $2\nFrom: $3 ($5)\nSubject: $4"; |
---|
710 | msglst[0] = bfr; |
---|
711 | sprintf(msglst[0],"%04d",super.highest); |
---|
712 | msglst[1] = super_long_name; |
---|
713 | msglst[2] = author; |
---|
714 | msglst[3] = subject; |
---|
715 | list_size = 4; |
---|
716 | if (signature != NULL) { |
---|
717 | msglst[4] = signature; |
---|
718 | list_size = 5; |
---|
719 | } |
---|
720 | |
---|
721 | /* Does "*" have read access? If so, just send out a global |
---|
722 | * notice. |
---|
723 | */ |
---|
724 | |
---|
725 | /* XXX |
---|
726 | * Check at some point for people who don't have access, etc. |
---|
727 | */ |
---|
728 | |
---|
729 | for (ae = mtg_acl->acl_entries, n=mtg_acl->acl_length; |
---|
730 | n; |
---|
731 | ae++, n--) { |
---|
732 | if ((strcmp("*", ae->principal) == 0) && |
---|
733 | acl_is_subset("r", ae->modes)) |
---|
734 | break; |
---|
735 | } |
---|
736 | if (n) { |
---|
737 | notice.z_recipient = ""; |
---|
738 | /* We really don't care if it gets through... */ |
---|
739 | code = ZSendList(¬ice,msglst,list_size,ZNOAUTH); |
---|
740 | return; |
---|
741 | } |
---|
742 | for (ae = mtg_acl->acl_entries, n=mtg_acl->acl_length; |
---|
743 | n; |
---|
744 | ae++, n--) { |
---|
745 | if (acl_is_subset("r", ae->modes)) { |
---|
746 | notice.z_recipient = ae->principal; |
---|
747 | ZSendList(¬ice,msglst,list_size,ZNOAUTH); |
---|
748 | } |
---|
749 | } |
---|
750 | } |
---|
751 | #endif /* ZEPHYR */ |
---|