source: trunk/athena/bin/discuss/server/expunge.c @ 22864

Revision 22864, 13.9 KB checked in by andersk, 16 years ago (diff)
Fix obsolete names for Kerberos library functions, which no longer worked on Mac OS X. Patch from broder.
Line 
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 *
10 * expunge -- program to expunge a meeting; i.e. really delete those
11 *            deleted transaction.  This program is linked to a server
12 *            so it can use the privileged procedure of create_mtg, and
13 *            the like.
14 *
15 */
16
17#include <stdio.h>
18#include <stdlib.h>
19#include <string.h>
20#if HAVE_FCNTL_H
21#include <fcntl.h>
22#endif
23#include <ctype.h>
24#include <sys/types.h>
25#include <sys/file.h>
26#include <sys/stat.h>
27#include <unistd.h>
28
29#include <discuss/types.h>
30#include <discuss/dsc_et.h>
31#include <discuss/tfile.h>
32#include <discuss/interface.h>
33#include <discuss/acl.h>
34#include "mtg.h"
35
36#define min(a, b) (a < b ? a : b)
37
38static int tempf;
39static char *mtg_name = NULL, *location = NULL, *chairman = NULL, *trn_file = NULL;
40static char *backup_location = NULL;
41static char *future_location = NULL;
42static int found_eof = 0;
43static int error_occurred = 0;
44static char *temp_dir = "/tmp";
45static int daemon_flag = FALSE;
46
47tfile unix_tfile ();
48
49static lower(), strip_addr(), extract_full_name();
50static char *get_header();
51
52extern char rpc_caller[];
53extern int has_privs;
54extern int errno;
55extern int no_nuke, use_zephyr;
56
57main (argc, argv)
58int argc;
59char **argv;
60{
61     int i,n,low,high;
62     mtg_info old_mtg_info,new_mtg_info;
63     trn_info3 old_trn_info;
64     int result;
65     dsc_acl *acl_list,*new_acl_list;
66     dsc_acl_entry *ae;
67     char *new_modes, *signature;
68     char new_signature[50],dtest[10];
69     tfile tf;
70     char control_name[256];
71     int control_fd;
72     static struct flock lock;
73
74
75     initialize_dsc_error_table();
76
77     for (i = 1; i < argc; i++) {
78          if (*argv[i] == '-') switch (argv[i][1]) {
79          case 'c':
80               if (++i < argc)
81                    chairman = argv[i];
82               continue;
83
84          case 'n':
85               if (++i < argc)
86                    mtg_name = argv[i];
87               continue;
88
89           case 't':
90               if (++i < argc)
91                   temp_dir = argv[i];
92               continue;
93
94          case 'd':
95               daemon_flag = TRUE;
96               continue;
97
98          default:
99               goto lusage;
100          }
101          if (location == NULL)
102               location = argv[i];
103          else goto lusage;
104     }
105
106     if (location == NULL)
107          goto lusage;                                  /* required */
108
109     has_privs = TRUE;          /* Tell discuss we're special */
110     use_zephyr = 0;            /* Don't notify of every trn copied */
111     strcpy (rpc_caller, "expunger");
112
113     /* First, we get the mtg info to make sure it exists */
114     get_mtg_info (location, &old_mtg_info, &result);
115     if (result != 0) {
116          fprintf(stderr, "%s: %s while getting mtg info\n", location, error_message(result));
117          exit (1);
118     }
119
120     get_acl (location, &result, &acl_list);
121     if (result != 0) {
122          fprintf(stderr, "%s: %s while getting acl\n", location, error_message(result));
123          exit (1);
124     }
125
126     /* Create the new meeting */
127     backup_location = malloc (strlen(location)+5);     /* be generous */
128     strcpy (backup_location, location);
129     strcat (backup_location, "~");
130
131     future_location = malloc (strlen(location)+5);     /* be generous */
132     strcpy (future_location, location);
133     strcat (future_location, "#");
134
135     printf("Creating new meeting\n");
136     fflush(stdout);
137
138     if (mtg_name == NULL) {
139          mtg_name = old_mtg_info.long_name;
140     }
141     if (chairman == NULL) {
142          chairman = old_mtg_info.chairman;
143     }
144
145     /* get acl's on old meeting, so we can make it new one */
146     get_acl (location, &result, &new_acl_list);
147     if (result != 0) {
148          fprintf(stderr, "%s: %s while getting acl\n", backup_location, error_message(result));
149          exit (1);
150     }
151
152     create_mtg_priv (backup_location, mtg_name, old_mtg_info.public_flag,
153                      old_mtg_info.date_created, chairman,
154                      new_acl_list, &result);
155     if (result != 0) {
156          fprintf (stderr, "%s: %s while creating new meeting\n",
157                   location, error_message(result));
158          exit (1);
159     }
160     
161     /* now, do the actual expunging */
162     low = old_mtg_info.lowest;
163     high = old_mtg_info.highest;
164     create_temp ();
165
166expunge_range:
167     for (i = low; i <= high; i++) {
168          get_trn_info3 (location, i, &old_trn_info, &result);
169          if (result != 0 && result != DELETED_TRN && result != EXPUNGED_TRN) {
170               fprintf(stderr,
171                       "Error getting info for transaction [%04d]: %s\n",
172                       i, error_message(result));
173               error_occurred = TRUE;
174          } else if (result != 0) {             /* expunge it */
175               no_nuke = TRUE;
176               printf("Expunging transaction [%04d]\n", i);
177               expunge_trn (backup_location, i, &result);
178               no_nuke = FALSE;
179               if (result != 0) {
180                    fprintf(stderr,
181                            "Error expunging transaction [%04d]: %s\n",
182                            i, error_message(result));
183                    error_occurred = TRUE;
184               }
185          } else if (result == 0) {
186               ftruncate(tempf,0);
187               lseek(tempf,0,SEEK_SET);
188               tf = unix_tfile (tempf);
189
190               get_trn (location, i, tf, &result);
191               if (result != 0) {
192                    fprintf(stderr, "Error getting transaction [%04d]: %s\n",
193                            i, error_message(result));
194                    error_occurred = TRUE;
195                    free(old_trn_info. author);
196                    free(old_trn_info.subject);
197                    continue;
198               }
199
200               tdestroy (tf);
201
202               signature = old_trn_info.signature;
203               if (daemon_flag && old_trn_info.signature != NULL) {
204                    memmove(dtest, old_trn_info.signature,  7);
205                    dtest[7] = '\0';
206                    if (!strcmp(dtest,"daemon@")) {
207                         if (get_from_signature(tempf, new_signature, sizeof(new_signature)))
208                              signature = new_signature;
209                    }
210               }
211               lseek(tempf,0,SEEK_SET);
212               tf = unix_tfile (tempf);
213               no_nuke = TRUE;
214               add_trn_priv (backup_location, tf, old_trn_info.subject,
215                             signature, old_trn_info.pref,
216                             old_trn_info.current, old_trn_info.author,
217                             old_trn_info.date_entered, old_trn_info.flags,
218                             &n, &result);
219               no_nuke = FALSE;
220               if (result != 0) {
221                    fprintf(stderr,
222                            "Error getting info for transaction %d: %s\n", i,
223                            error_message(result));
224                    error_occurred = TRUE;
225               }
226               tdestroy(tf);
227               free(old_trn_info.author);
228               free(old_trn_info.subject);
229               free(old_trn_info.signature);
230          }
231     }
232
233     /* Check if any new transactions have been added */
234     free(old_mtg_info.long_name);
235     free(old_mtg_info.chairman);
236     free(old_mtg_info.location);
237     get_mtg_info(location, &old_mtg_info, &result);
238     if (result != 0) {
239          fprintf(stderr, "%s: %s while getting mtg info\n", location, error_message(result));
240          error_occurred = TRUE;
241     } else if (old_mtg_info.highest > high) {          /* New transactions added */
242          low = high+1;
243          high = old_mtg_info.highest;
244          goto expunge_range;
245     }
246
247     strcpy(control_name, location);
248     strcat(control_name, "/control");
249     if ((control_fd = open (control_name, O_RDWR, 0700)) < 0) {
250          error_occurred = TRUE;
251     } else {
252          lock.l_type = F_WRLCK;
253          lock.l_start = 0;
254          lock.l_whence = 0;
255          lock.l_len = 0;
256          fcntl(control_fd, F_SETLKW, &lock);
257
258          free(old_mtg_info.long_name);
259          free(old_mtg_info.chairman);
260          free(old_mtg_info.location);
261
262          no_nuke = TRUE;
263          get_mtg_info(location, &old_mtg_info, &result);
264          if (result != 0) {           
265               fprintf(stderr, "%s: %s while getting mtg info\n", location, error_message(result));
266               error_occurred = TRUE;
267
268               lock.l_type = F_UNLCK;
269               lock.l_start = 0;
270               lock.l_whence = 0;
271               lock.l_len = 0;
272               fcntl(control_fd, F_SETLK, &lock);
273
274               close(control_fd);
275          } else if (old_mtg_info.highest > high) {             /* New transactions added */
276               low = high + 1;
277               high = old_mtg_info.highest;
278               lock.l_type = F_UNLCK;
279               lock.l_start = 0;
280               lock.l_whence = 0;
281               lock.l_len = 0;
282               fcntl(control_fd, F_SETLK, &lock);
283               close(control_fd);
284               goto expunge_range;
285          }
286     }
287
288     /* When we get here, we have the old meeting locked.  Now we do the move
289        as atomically as we can */
290     if (!error_occurred) {
291          if (rename(location, future_location) < 0) {
292               perror("rename of old meeting failed");
293               exit (1);
294          }
295          if (rename(backup_location, location) < 0) {
296               perror("rename of new meeting");
297               exit (1);
298          }
299          remove_mtg (future_location, &result);
300          if (result != 0) {
301               fprintf(stderr, "%s: %s while removing new meeting.\n",
302                       location, error_message(result));
303               exit (1);
304          }
305     } else exit (1);                           /* error occurred */
306
307     exit (0);
308
309lusage:
310     fprintf(stderr, "usage: expunge mtg_location {-c chairman} {-n name}\n");
311     exit (1);
312}
313
314/*
315 *
316 * create_temp () -- Create temp file, and let it be tempf.
317 *
318 */
319create_temp()
320{
321     char *filename;
322
323     filename = malloc (strlen (temp_dir) + 20);
324     strcpy (filename, temp_dir);
325     strcat (filename, "/rcXXXXXX");
326     mktemp (filename);
327
328     tempf = open (filename, O_RDWR | O_CREAT, 0700);
329     if (tempf < 0) {
330          fprintf (stderr, "Cannot open temp file\n");
331          exit (1);
332     }
333}
334
335/*
336 *
337 *   get_from_signature () -- Look in the file file_no, looking for a
338 *      From: line.  Construct a signature from this from line, returning
339 *      it in sign, with a maximum length of sign_len.
340 *
341 */
342
343int
344get_from_signature(file_no, sign, sign_len)
345int file_no;
346char *sign;
347int sign_len;
348{
349     char buf[2048];
350     int len;
351     char *cp, *hp;
352
353     lseek(file_no, 0, SEEK_SET);
354     len = read(file_no, buf, sizeof(buf)-1);
355     buf[len] = '\0';
356
357     hp = get_header(buf, "from");
358     if (hp == NULL)
359          return(0);
360
361     cp = strchr(hp, ':');
362     if (cp == NULL)
363          return(0);
364
365     cp++;
366
367     extract_full_name(cp, sign, sign_len);
368     return(1);
369}
370
371/* Stolen from TechMail */
372
373static
374lower(s)
375char *s;
376{
377     while (*s) {
378          if (isupper(*s))
379               *s = tolower(*s);
380          s++;
381     }
382     return;
383}
384
385static
386strip_addr(addr, dest, dest_size)
387char *addr,*dest;
388int dest_size;
389{
390     char *dest_end,*dp,*sp,*quote_start;
391     int paren_level,found_angle;
392
393     dest_end = &dest[dest_size-1];
394     dp = dest;
395     sp = addr;
396     paren_level = 0;
397
398eat_white:
399     while (isspace(*sp) && *sp != '\n')
400          sp++;
401
402     if (*sp == '(')
403          goto eat_comment;
404
405     if (*sp == '"')
406          goto eat_string;
407
408     if (*sp == '<') {
409          dp = dest;
410          sp++;
411          found_angle = TRUE;
412          goto eat_white;
413     }
414
415     if (*sp == '>' && found_angle) {
416          *sp++;
417          goto eat_white;
418     }
419
420     if (*sp == '\0' || *sp == '\n') {
421          *dp++ = '\0';
422          goto post_proc;
423     }
424
425     *dp++ = *sp++;
426     if (dp == dest_end) {
427          *dp++ = '\0';
428          goto post_proc;
429     }
430
431     goto eat_white;
432
433eat_comment:
434     paren_level++;
435     sp++;
436
437cont_comment:
438     while (*sp != ')' && *sp != '(' && *sp) {
439          sp++;
440     }
441
442     if (*sp == '\0') {
443          *dp = '\0';
444          goto post_proc;
445     }
446
447     if (*sp == '(')
448          goto eat_comment;
449
450     sp++;              /* ) */
451     paren_level--;
452     if (paren_level <= 0)
453          goto eat_white;
454
455     goto cont_comment;
456
457eat_string:
458     quote_start = sp;
459     sp++;
460
461     while(*sp != '"' && *sp)
462          sp++;
463
464     if (!*sp) {
465          *dp = '\0';
466          goto post_proc;
467     }
468
469     if (*++sp == '@') {                /* "foo"@bar */
470          sp = quote_start;
471          *dp++ = *sp++;
472          while (dp < dest_end && *sp != '"')
473               *dp++ = *sp++;
474
475          if (dp == dest_end) {
476               *dp = '\0';
477               goto post_proc;
478          }
479          *dp++ = *sp++;
480          if (dp == dest_end) {
481               *dp++ = '\0';
482               goto post_proc;
483          }
484     }
485     goto eat_white;
486
487     /* No post processing */
488post_proc:
489     return;
490}
491
492/*
493 *
494 *   Routine to extract a full name from an address.  If no full name
495 *   can be found, then we simply return the stripped address.
496 *
497 */
498
499static
500extract_full_name(addr, dest, dest_size)
501char *addr,*dest;
502int dest_size;
503{
504     char *dest_end,*dp,*sp,*bracket,*close_paren;
505     int paren_level,non_white;
506
507     dest_end = &dest[dest_size-1];
508     dp = dest;
509     sp = addr;
510
511     /* Find angle bracket (if possible) */
512     while (*sp && *sp != '<' && *sp != '\n')
513          sp++;
514
515     bracket = NULL;
516     if (*sp == '<')
517          bracket = sp;
518
519     non_white = 0;
520     if (bracket != NULL) {
521          for (sp = addr; sp < bracket; sp++) {
522               if (!isspace(*sp) && *sp != '"')
523                    non_white++;
524          }
525     }
526
527     if (non_white > 1) {               /* We have a name */
528          sp = addr;
529          while (isspace(*sp) || *sp == '"')    /* Skip leading spaces */
530               sp++;
531
532          while (isspace(*(bracket-1)) || *(bracket-1) == '"')  /* Skip trailing spaces */
533               bracket--;
534
535          /* Copy it over */
536          while (sp < bracket && dp < dest_end)
537               *dp++ = *sp++;
538
539          *dp++ = '\0';
540          return;
541     }
542
543     /* Now, let's see if we have name in a comment (look back from the
544        end for a parenthesis. */
545     for (sp = addr; *sp && *sp != '\n'; sp++)
546          ;
547
548     sp--;
549     while (sp > addr && isspace(*sp))
550          sp--;
551
552     if (*sp == ')') {                  /* Name in comment */
553          close_paren = sp;
554          paren_level = 1;
555          sp--;
556
557          for (;sp > addr; sp--) {
558               if (*sp == ')')
559                    paren_level++;
560               else if (*sp == '(') {
561                    paren_level--;
562                    if (paren_level == 0)
563                         break;
564               }
565          }
566
567          if (*sp == '(') {             /* Copy it over */
568               sp++;
569
570               while(isspace(*sp))
571                    sp++;
572
573               while (sp < close_paren && dp < dest_end)
574                    *dp++ = *sp++;
575
576               *dp = '\0';
577               return;
578          }
579     }
580
581     strip_addr(addr, dest, dest_size);
582     return;
583}         
584
585static char *
586get_header(hstring, hname)
587char *hstring, *hname;
588{
589     char *eolp, *colonp, *cp;
590     int name_len;
591     char field[33];
592
593     cp = hstring;
594     name_len = strlen(hname);
595
596     while (*cp != '\0') {
597          eolp = strchr(cp, '\n');
598          colonp = strchr(cp, ':');
599
600          if (eolp == NULL || colonp == NULL || eolp == cp)
601               return(0);
602
603          if (colonp > eolp || colonp - cp != name_len) {
604               cp = eolp+1;
605               continue;
606          }
607
608          /* Chance of a match, copy header over to name, and lower it */
609          memmove(field,cp,  colonp - cp);
610          field[colonp - cp] = '\0';
611          lower(field);
612          if (!strcmp(field,hname))
613               return(cp);
614          cp = eolp + 1;
615     }
616
617     return(NULL);
618}
Note: See TracBrowser for help on using the repository browser.