source: trunk/athena/bin/discuss/client/addmtg.c @ 25764

Revision 25764, 12.1 KB checked in by jdreed, 12 years ago (diff)
In discuss: * Fix buffer overflow when re-adding meeting (Trac: #973)
Line 
1/*
2 *
3 *    Copyright (C) 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 *  addmtg () --
10 *      The add_meeting command in discuss.  This request adds a
11 *      meeting to the user's list of meetings.  There are several
12 *      ways that this can occur -- the user could put the meeting
13 *      on the command line, in the form of host:pathname.
14 *     
15 *      Or the user could put some transaction specifiers on the
16 *      command line, in which case they are used as meeting announcements.
17 *
18 *      $Id: addmtg.c,v 1.34 2006-03-10 07:11:30 ghudson Exp $
19 *
20 */
21
22#ifndef lint
23static char rcsid_addmtg_c[] =
24    "$Id: addmtg.c,v 1.34 2006-03-10 07:11:30 ghudson Exp $";
25#endif /* lint */
26
27#include <string.h>
28#include <stdio.h>
29#include <stdlib.h>
30#include <netdb.h>
31#include <sys/file.h>
32#if HAVE_FCNTL_H
33#include <fcntl.h>
34#endif
35#include <discuss/discuss.h>
36#include "globals.h"
37#include <ss/ss.h>
38
39extern tfile unix_tfile();
40static int add_mtg_it();
41
42static int mtgs_added;
43static del_the_mtg();
44
45name_blk *set;
46int num;
47
48add_mtg(argc, argv)
49     int argc;
50     char **argv;
51{
52        int i, *used;
53        name_blk nb;
54        int code,have_names;
55        char *user,*realm,cerror[80],*pathp,*hostp;
56        char auser_id[BUFSIZ];
57        trn_info t_info;
58        selection_list *trn_list,*trn_temp;
59
60        used = (int *)calloc(argc+1, sizeof(int));
61        user = "";
62        realm = user;
63        set = NULL;
64        dsc_expand_mtg_set(user_id, "*", &set, &num, &code);
65
66        i = 1;
67        have_names = 0;
68
69        /* If we're attending a meeting, try to interpret the arguments
70           as transaction specifiers for the current meeting.  If no
71           arguments are given, then we default to the current transaction */
72        if (dsc_public.attending) {
73                dsc_destroy_mtg_info(&dsc_public.m_info);
74                dsc_get_mtg_info(&dsc_public.nb,
75                                 &dsc_public.m_info,&code);     /* get mtg info for trn mapping */
76                if (code) {
77                        (void) ss_perror(sci_idx, code,
78                                         "Can't get meeting info for current meeting");
79                        goto punt;
80                }
81                dsc_get_trn_info(&dsc_public.nb,
82                                 dsc_public.current, &t_info, &code);
83                if (code)
84                        t_info.current = 0;
85                dsc_destroy_trn_info (&t_info);
86                if (argc == 1) {
87                        trn_list = trn_select(&t_info, "current",
88                                              (selection_list *)NULL, &code);
89                        if (code) {
90                                ss_perror(sci_idx, code, "");
91                                sl_free(trn_list);
92                                goto punt;
93                        }
94                        used[1] = 1;
95                } else {
96                        trn_list = (selection_list *)NULL;
97                        for (;i<argc;i++) {
98                                trn_temp = trn_select(&t_info, argv[i],
99                                                      trn_list, &code);
100                                if (code)
101                                        break;
102                                trn_list = trn_temp;
103                                used[i] = 1;
104                        }
105                }
106                mtgs_added = FALSE;
107                (void) sl_map(add_mtg_it,trn_list,FALSE);
108                sl_free(trn_list);
109                if (!mtgs_added)                /* Check if we had args */
110                     for (i = 1; i <argc; i++)
111                          if (used[i]) {
112                               ss_perror(sci_idx, 0, "No transactions selected");
113                               break;
114                          }
115                have_names = 1;
116        }
117
118
119        /* now we parse the command line for '-user' and meeting names */
120        for (;i<argc;i++) {
121                if (!strcmp("-user", argv[i])) {
122                        if (i == argc-1) {
123                                fprintf(stderr,
124                                        "Missing argument for -user\n");
125                                goto punt;
126                        }
127                        if (user[0] != '\0') {
128                                fprintf(stderr,
129                                        "Only one of -user, -public allowed\n");
130                                goto punt;
131                        }
132                        used[i] = 1;
133                        user = argv[++i];
134                        used[i] = 1;
135                }
136                else if (!strcmp(argv[i],"-public")) {
137                        if (user[0] != '\0') {
138                                fprintf(stderr,
139                                        "Only one of -user, -public allowed\n");
140                                goto punt;
141                        }
142                        user = "discuss";
143                        used[i] = 1;
144                }
145                else if (*argv[i] == '-') {
146                        fprintf(stderr,
147                                "Unknown control argument %s\n",
148                                argv[i]);
149                        free((char *)used);
150                        goto punt;
151                }
152                else {
153                        have_names = 1;
154                }
155        }
156
157        /* Convert user given to include realm name */
158        strcpy(auser_id, user_id);
159        if (user[0] != '\0')
160                strcpy(auser_id, user);
161        {
162                register char *at = strchr(auser_id, '@');
163                if (at) *at = '\0';
164        }
165        strcat(auser_id, "@");
166        if (realm[0] != '\0')
167                strcat(auser_id, realm);
168        else
169                strcat(auser_id, strchr(user_id, '@')+1);
170
171        if (!have_names) {
172                (void) fprintf(stderr,
173                               "Usage:  %s {-user user|-public} [mtg_names]\n",
174                               argv[0]);
175                (void) fprintf(stderr,
176                               "        %s transactions\n", argv[0]);
177                goto punt;
178        }
179
180        /* add the meeting names we're given */
181        for (i = 1; i < argc; i++) {
182             if (!used[i]) {
183                  if ((pathp = strchr (argv[i], ':')) != NULL) {
184                       hostp = argv[i];
185                       *pathp++ = '\0';
186                       sprintf(cerror, "Adding meeting %s:%s", hostp,pathp);
187                       hostpath_to_nb (hostp, pathp, &nb, &code);
188                       if (code) {
189                            ss_perror(sci_idx, code, cerror);
190                            continue;
191                       }
192                  } else {
193                       sprintf(cerror, "Adding meeting (%s)", argv[i]);
194                       dsc_get_mtg (auser_id, argv[i], &nb, &code);
195                       if (code) {
196                            ss_perror(sci_idx, code, cerror);
197                            continue;
198                       }
199                  }
200                  add_the_mtg(&nb,&code);
201                  if (code && code != DISC_ACTION_NOT_PERFORMED)
202                       ss_perror(sci_idx, code, cerror);
203                 else if (code != DISC_ACTION_NOT_PERFORMED)
204                      printf ("Meeting %s (%s) added.\n", nb.aliases[0], nb.aliases[1]);
205                  dsc_destroy_name_blk(&nb);
206             }
207        }
208
209punt:
210        dsc_destroy_mtg_set (set, num);
211        free((char *)used);
212        return;
213}
214
215static
216add_mtg_it(t_infop, codep)
217trn_info3 *t_infop;
218int *codep;
219{
220     char cerror[80];
221     name_blk nb;
222
223     mtgs_added = TRUE;
224     if (*codep != 0) {
225          sprintf (cerror, "Transaction [%04d]", t_infop->current);
226          ss_perror(sci_idx, *codep, cerror);
227          *codep = 0;
228          return;
229     }
230
231     parse_mtg_info (&dsc_public.nb, t_infop->current, &nb, codep);
232     if (*codep != 0) {
233          if (*codep == DISC_NOT_ANNOUNCEMENT) {
234               sprintf (cerror, "Transaction [%04d] is not a properly formatted meeting announcement", t_infop->current);
235               ss_perror (sci_idx, 0, cerror);
236          } else {
237               sprintf (cerror, "Transaction [%04d]", t_infop->current);
238               ss_perror(sci_idx, *codep, cerror);
239          }
240          return;
241     }
242     
243     add_the_mtg (&nb, codep);
244     if (*codep != 0 && *codep != DISC_ACTION_NOT_PERFORMED) {
245          sprintf (cerror, "Error adding meeting in transaction [%04d]", t_infop->current);
246          ss_perror(sci_idx, *codep, cerror);
247     } else if (*codep != DISC_ACTION_NOT_PERFORMED)
248          printf ("Transaction [%04d] Meeting %s (%s) added.\n", t_infop->current, nb.aliases[0], nb.aliases[1]);
249     
250     dsc_destroy_name_blk (&nb);
251     *codep = 0;
252     return;
253}
254
255parse_mtg_info(mtg_nbp, trn_no, result_nbp, code)
256name_blk *mtg_nbp;
257int trn_no;
258name_blk *result_nbp;
259int *code;
260{
261     int fd,dummy;
262     char tempbfr[256],host[100];
263     tfile tf;
264     FILE *fp;
265
266     *code = 0;
267
268     /* initialize puntable state */
269     fp = NULL;
270
271     unlink(temp_file);
272     fd = open(temp_file,O_WRONLY|O_CREAT,0700);
273     tf = unix_tfile(fd);
274     dsc_get_trn(mtg_nbp,trn_no,tf,code);
275     close(fd);
276     tclose(tf,&dummy);
277     tdestroy(tf);
278
279     if (*code)
280          return;
281       
282     fp = fopen(temp_file,"r");
283     if (!fp)
284          goto not_ann;
285     if (!fgets(tempbfr,256,fp))
286          goto not_ann;
287     if (strncmp(tempbfr,"  Meeting Name:  ",17))
288          goto not_ann;
289     if (!fgets(tempbfr,256,fp))
290          goto not_ann;
291     if (strncmp(tempbfr,"  Host:          ",17))
292          goto not_ann;
293     tempbfr[strlen(tempbfr)-1] = '\0';
294     strcpy(host,tempbfr+17);
295     if (!fgets(tempbfr,256,fp))
296          goto not_ann;
297     if (strncmp(tempbfr,"  Pathname:      ",17))
298          goto not_ann;
299     fclose(fp);
300     fp = NULL;
301     tempbfr[strlen(tempbfr)-1] = '\0';
302
303     hostpath_to_nb (host, &tempbfr[17], result_nbp, code);
304     goto punt;
305
306not_ann:
307     *code = DISC_NOT_ANNOUNCEMENT;
308
309punt:
310     if (fp != NULL)
311          fclose(fp);
312
313     return;
314}
315
316hostpath_to_nb (host, path, nbp, code)
317char *host, *path;
318name_blk *nbp;
319int *code;
320{
321     struct hostent *hp;
322     mtg_info m_info;
323     char *short_name;
324
325     nbp -> hostname = nbp -> pathname = nbp -> user_id = nbp -> spare = NULL;
326     nbp -> date_attended = nbp -> last = nbp -> status = 0;
327
328     hp = gethostbyname (host);
329     if (hp != NULL)
330          host = hp -> h_name;                  /* use canonical if possible */
331     nbp -> hostname = malloc((unsigned)strlen(host)+1);
332     strcpy(nbp -> hostname,host);
333     nbp -> pathname = malloc((unsigned)strlen(path)+1);
334     strcpy(nbp -> pathname, path);
335     nbp -> user_id = malloc((unsigned)strlen(user_id)+1);
336     strcpy(nbp -> user_id, user_id);
337     nbp -> aliases = (char **)NULL;
338     dsc_get_mtg_info(nbp, &m_info, code);
339     if (*code) {
340          if (*code == NO_ACCESS) {
341               *code = CANT_ATTEND;             /* friendlier error msg */
342          }
343          goto punt;
344     }
345     short_name = strrchr(path,'/');
346     if (!short_name)
347          short_name = strrchr(path,':');
348     nbp -> aliases = (char **)calloc(3, sizeof(char *));
349     nbp -> aliases[0] = malloc(strlen(m_info.long_name)+1);
350     strcpy(nbp -> aliases[0], m_info.long_name);
351     nbp -> aliases[1] = malloc(strlen(short_name));
352     strcpy(nbp -> aliases[1],short_name+1);
353     nbp -> aliases[2] = (char *)NULL;
354     *(nbp->spare = malloc(1)) = '\0';
355     free(m_info.location);
356     free(m_info.chairman);
357     free(m_info.long_name);
358
359     return;
360
361punt:
362     dsc_destroy_name_blk (nbp);
363     return;
364}
365
366add_the_mtg(new_nbp,code)
367        name_blk *new_nbp;
368        int *code;
369{
370        name_blk *nbp,temp_nb;
371        const char *prompt = "Meeting %s already exists.\nDo you wish to delete the old one and add the new one? ";
372        char *question = NULL;
373        int j;
374
375        /* see if we're already attending... */
376        for (j = 0,nbp = set; j < num; j++,nbp++) {
377                if (!namcmp (nbp ->hostname, new_nbp->hostname) && !strcmp(nbp->pathname, new_nbp->pathname)) {
378                        *code = DISC_DUPLICATE_MTG;
379                        return;
380                }
381        }
382
383        for (j = 0; new_nbp->aliases[j] != NULL; j++) {
384             dsc_get_mtg (user_id, new_nbp->aliases[j], &temp_nb, code);
385             if (*code == 0) {                          /* already exists */
386                  question = malloc(strlen(prompt) - 2 + strlen(new_nbp -> aliases[j]) + 1);
387                       if (! question) {
388                            fprintf(stderr, "Couldn't malloc.  Too bad...");
389                            return;
390                       }
391                  sprintf (question, prompt, new_nbp -> aliases[j]);
392                  if (!command_query (question)) {
393                       printf ("Meeting not added.\n");
394                       dsc_destroy_name_blk (&temp_nb);
395                       *code = DISC_ACTION_NOT_PERFORMED;
396                       free(question);
397                       return;
398                  }
399                  free(question);
400                  del_the_mtg (&temp_nb, code);
401                  if (*code != 0) {
402                       dsc_destroy_name_blk (&temp_nb);
403                       return;
404                  }
405                  dsc_destroy_name_blk(&temp_nb);
406             }
407        }
408             
409        dsc_update_mtg_set(user_id, new_nbp, 1, code);
410        if (*code) {
411                return;
412        }
413        return;
414}
415
416del_mtg(argc, argv)
417     int argc;
418     char **argv;
419{
420        int i, *used;
421        name_blk nb;
422        int code,have_names;
423        char *user,*realm;
424        char auser_id[BUFSIZ];
425
426        used = (int *)calloc(argc, sizeof(int));
427        user = "";
428        realm = user;
429
430        have_names = 0;
431             
432        for (i=1; i<argc; i++) {
433                if (*argv[i] == '-') {
434                        fprintf(stderr,
435                                "Unknown control argument %s\n",
436                                argv[i]);
437                        free((char *)used);
438                        return;
439                }
440                else {
441                        have_names = 1;
442                }
443        }
444
445        strcpy(auser_id, user_id);
446        if (user[0] != '\0')
447                strcpy(auser_id, user);
448        {
449                register char *at = strchr(auser_id, '@');
450                if (at) *at = '\0';
451        }
452        strcat(auser_id, "@");
453        if (realm[0] != '\0')
454                strcat(auser_id, realm);
455        else
456                strcat(auser_id, strchr(user_id, '@')+1);
457
458        if (!have_names) {
459                (void) fprintf(stderr,
460                               "Usage:  %s [mtg_names]\n",
461                               argv[0]);
462                goto punt;
463        }
464
465        for (i = 1; i < argc; i++) {
466                if (!used[i]) {
467                        dsc_get_mtg (auser_id, argv[i], &nb, &code);
468                        if (code) {
469                                ss_perror(sci_idx, code, argv[i]);
470                                continue;
471                        }
472                        del_the_mtg (&nb, &code);
473                        if (code) {
474                                ss_perror(sci_idx, code, argv[i]);
475                        }
476                }
477        }
478
479 punt:
480        free((char *)used);
481        return;
482}
483
484static
485del_the_mtg (nbp,code)
486name_blk *nbp;
487int *code;
488{
489     /* If we're attending the meeting we're deleting,
490        we leave it, so than we don't accidentally
491        add it again when we leave it */
492     if (dsc_public.attending && !strcmp (nbp->aliases[0], dsc_public.nb.aliases[0]))
493          leave_mtg();
494     nbp->status |= DSC_ST_DELETED;
495     dsc_update_mtg_set(user_id, nbp, 1, code);
496}
497     
498/*
499 *
500 *  command_query () --
501 *      Routine to ask the user a question, and return TRUE/FALSE depending
502 *      on whether it is 'yes'/'no'
503 *
504 */
505command_query (question)
506char *question;
507{
508     int result;
509     char answer [20];
510
511     printf ("%s", question);
512     fflush (stdout);
513     if (fgets (answer, 10, stdin) == NULL)
514          return(FALSE);
515
516
517     return (answer [0] == 'Y' || answer [0] == 'y');
518}
Note: See TracBrowser for help on using the repository browser.