source: trunk/athena/bin/discuss/server/expunge2.c @ 23271

Revision 23271, 7.5 KB checked in by broder, 16 years ago (diff)
Add com_err support for delete and discuss on OS X.
Line 
1/*
2 *
3 * expunge -- program to expunge a meeting; i.e. really delete those
4 *            deleted transaction.  This program is linked to a server
5 *            so it can use the privileged procedure of create_mtg, and
6 *            the like.
7 *
8 */
9
10#include <stdio.h>
11#include <strings.h>
12#include <sys/types.h>
13#include <sys/file.h>
14#include <sys/stat.h>
15#include <unistd.h>
16
17#include <discuss/types.h>
18#include <discuss/dsc_et.h>
19#include <discuss/tfile.h>
20#include <discuss/interface.h>
21#include <discuss/acl.h>
22#include "mtg.h"
23
24#define NULL 0
25#define MAX_TRNS 1000
26#define min(a, b) (a < b ? a : b)
27
28static int tempf;
29static char *mtg_name = NULL, *location = NULL, *chairman = NULL, *trn_file = NULL;
30static char *backup_location = NULL;
31static char *future_location = NULL;
32static int found_eof = 0;
33static int error_occurred = 0;
34
35tfile unix_tfile ();
36char *malloc();
37
38extern char rpc_caller[];
39extern int has_privs;
40extern int errno;
41extern int no_nuke;
42
43main (argc, argv)
44int argc;
45char **argv;
46{
47     int i,n,low,high;
48     mtg_info old_mtg_info,new_mtg_info;
49     trn_info old_trn_info;
50     int result;
51     dsc_acl *acl_list,*new_acl_list;
52     dsc_acl_entry *ae;
53     char *new_modes;
54     tfile tf;
55     char control_name[256];
56     int control_fd;
57     
58#if defined(__APPLE__) && defined(__MACH__)
59     add_error_table(&et_dsc_error_table);
60#else
61     initialize_dsc_error_table();
62#endif
63
64     for (i = 1; i < argc; i++) {
65          if (*argv[i] == '-') switch (argv[i][1]) {
66          case 'c':
67               if (++i < argc)
68                    chairman = argv[i];
69               continue;
70
71          case 'n':
72               if (++i < argc)
73                    mtg_name = argv[i];
74               continue;
75
76          default:
77               goto lusage;
78          }
79          if (location == NULL)
80               location = argv[i];
81          else goto lusage;
82     }
83
84     if (location == NULL)
85          goto lusage;                                  /* required */
86
87     has_privs = TRUE;                                  /* Tell discuss we're special */
88     strcpy (rpc_caller, "expunger");
89
90     /* First, we get the mtg info to make sure it exists */
91     get_mtg_info (location, &old_mtg_info, &result);
92     if (result != 0) {
93          fprintf(stderr, "%s: %s while getting mtg info\n", location, error_message(result));
94          exit (1);
95     }
96
97     get_acl (location, &result, &acl_list);
98     if (result != 0) {
99          fprintf(stderr, "%s: %s while getting acl\n", location, error_message(result));
100          exit (1);
101     }
102
103     /* Create the new meeting */
104     backup_location = malloc (strlen(location)+5);     /* be generous */
105     strcpy (backup_location, location);
106     strcat (backup_location, "~");
107
108     future_location = malloc (strlen(location)+5);     /* be generous */
109     strcpy (future_location, location);
110     strcat (future_location, "#");
111
112     printf("Creating new meeting\n");
113     fflush(stdout);
114
115     if (mtg_name == NULL) {
116          mtg_name = old_mtg_info.long_name;
117     }
118     if (chairman == NULL) {
119          chairman = old_mtg_info.chairman;
120     }
121
122     /* get acl's on old meeting, so we can make it new one */
123     get_acl (location, &result, &new_acl_list);
124     if (result != 0) {
125          fprintf(stderr, "%s: %s while getting acl\n", backup_location, error_message(result));
126          exit (1);
127     }
128
129     create_mtg_priv (backup_location, mtg_name, old_mtg_info.public_flag,
130                      old_mtg_info.date_created, chairman,
131                      new_acl_list, &result);
132     if (result != 0) {
133          fprintf (stderr, "%s: %s while creating new meeting\n",
134                   location, error_message(result));
135          exit (1);
136     }
137     
138     /* now, do the actual expunging */
139     low = old_mtg_info.lowest;
140     high = old_mtg_info.highest;
141     create_temp ();
142
143expunge_range:
144     for (i = low; i <= high; i++) {
145          get_trn_info (location, i, &old_trn_info, &result);
146          if (result != 0 && result != DELETED_TRN && result != EXPUNGED_TRN) {
147               fprintf(stderr,
148                       "Error getting info for transaction [%04d]: %s\n",
149                       i, error_message(result));
150               error_occurred = TRUE;
151          } else if (result != 0) {             /* expunge it */
152               no_nuke = TRUE;
153               printf("Expunging transaction [%04d]\n", i);
154               expunge_trn (backup_location, i, &result);
155               no_nuke = FALSE;
156               if (result != 0) {
157                    fprintf(stderr,
158                            "Error expunging transaction [%04d]: %s\n",
159                            i, error_message(result));
160                    error_occurred = TRUE;
161               }
162          } else if (result == 0) {
163               ftruncate(tempf,0);
164               lseek(tempf,0,SEEK_SET);
165               tf = unix_tfile (tempf);
166
167               get_trn (location, i, tf, &result);
168               if (result != 0) {
169                    fprintf(stderr, "Error getting transaction [%04d]: %s\n",
170                            i, error_message(result));
171                    error_occurred = TRUE;
172                    free(old_trn_info. author);
173                    free(old_trn_info.subject);
174                    continue;
175               }
176
177               tdestroy (tf);
178               lseek(tempf,0,SEEK_SET);
179
180               tf = unix_tfile (tempf);
181               no_nuke = TRUE;
182               add_trn_priv (backup_location, tf, old_trn_info.subject,
183                             old_trn_info.pref, old_trn_info.current,
184                             old_trn_info.author, old_trn_info.date_entered,
185                             &n, &result);
186               no_nuke = FALSE;
187               if (result != 0) {
188                    fprintf(stderr,
189                            "Error getting info for transaction %d: %s\n", i,
190                            error_message(result));
191                    error_occurred = TRUE;
192               }
193               free(old_trn_info.author);
194               free(old_trn_info.subject);
195          }
196     }
197
198     /* Check if any new transactions have been added */
199     free(old_mtg_info.long_name);
200     free(old_mtg_info.chairman);
201     free(old_mtg_info.location);
202     get_mtg_info(location, &old_mtg_info, &result);
203     if (result != 0) {
204          fprintf(stderr, "%s: %s while getting mtg info\n", location, error_message(result));
205          error_occurred = TRUE;
206     } else if (old_mtg_info.highest > high) {          /* New transactions added */
207          low = high+1;
208          high = old_mtg_info.highest;
209          goto expunge_range;
210     }
211
212     strcpy(control_name, location);
213     strcat(control_name, "/control");
214     if ((control_fd = open (control_name, O_RDWR, 0700)) < 0) {
215          error_occurred = TRUE;
216     } else {
217          flock(control_fd, LOCK_EX);           /* Hold meeting by the balls */
218          free(old_mtg_info.long_name);
219          free(old_mtg_info.chairman);
220          free(old_mtg_info.location);
221
222          no_nuke = TRUE;
223          get_mtg_info(location, &old_mtg_info, &result);
224          if (result != 0) {           
225               fprintf(stderr, "%s: %s while getting mtg info\n", location, error_message(result));
226               error_occurred = TRUE;
227               flock(control_fd,LOCK_UN);
228               close(control_fd);
229          } else if (old_mtg_info.highest > high) {             /* New transactions added */
230               low = high + 1;
231               high = old_mtg_info.highest;
232               flock(control_fd,LOCK_UN);
233               close(control_fd);
234               goto expunge_range;
235          }
236     }
237
238     /* When we get here, we have the old meeting locked.  Now we do the move
239        as atomically as we can */
240     if (!error_occurred) {
241          if (rename(location, future_location) < 0) {
242               perror("rename of old meeting failed");
243               exit (1);
244          }
245          if (rename(backup_location, location) < 0) {
246               perror("rename of new meeting");
247               exit (1);
248          }
249          remove_mtg (future_location, &result);
250          if (result != 0) {
251               fprintf(stderr, "%s: %s while removing new meeting.\n",
252                       location, error_message(result));
253               exit (1);
254          }
255     } else exit (1);                           /* error occurred */
256
257     exit (0);
258
259lusage:
260     fprintf(stderr, "usage: expunge mtg_location {-c chairman} {-n name}\n");
261     exit (1);
262}
263
264/*
265 *
266 * create_temp () -- Create temp file, and let it be tempf.
267 *
268 */
269create_temp()
270{
271     char filename [20];
272
273     strcpy (filename, "/tmp/rcXXXXXX");
274     mktemp (filename);
275
276     tempf = open (filename, O_RDWR | O_CREAT, 0700);
277     if (tempf < 0) {
278          fprintf (stderr, "Cannot open temp file\n");
279          exit (1);
280     }
281}
282
283
Note: See TracBrowser for help on using the repository browser.