]> asedeno.scripts.mit.edu Git - 1ts-debian.git/blob - zephyr/clients/zctl/zctl.c
This commit was generated by cvs2svn to compensate for changes in r145,
[1ts-debian.git] / zephyr / clients / zctl / zctl.c
1 /* This file is part of the Project Athena Zephyr Notification System.
2  * It contains code for the "zctl" command.
3  *
4  *      Created by:     Robert French
5  *
6  *      $Source: /afs/athena/astaff/project/zephyr/attic2/repository/zephyr/clients/zctl/zctl.c,v $
7  *      $Author: marc $
8  *
9  *      Copyright (c) 1987,1988 by the Massachusetts Institute of Technology.
10  *      For copying and distribution information, see the file
11  *      "mit-copyright.h". 
12  */
13
14 #include <sysdep.h>
15 #include <zephyr/zephyr.h>
16 #ifdef HAVE_SS_SS_H
17 #include <ss/ss.h>
18 #else
19 # ifdef HAVE_KRB5_SS_H
20 # include <krb5/ss.h>
21 # endif
22 #endif
23 #include <com_err.h>
24 #include <pwd.h>
25 #include <netdb.h>
26 #include <errno.h>
27 #ifndef lint
28 static const char *rcsid_zctl_c = "$Id: zctl.c,v 1.28.4.1 1997/01/06 01:40:24 marc Exp $";
29 #endif
30
31 #include "zutils.h"
32
33 #define USERS_SUBS "/.zephyr.subs"
34 #define OLD_SUBS "/.subscriptions"
35
36 #define ERR             (-1)
37 #define NOT_REMOVED     0
38 #define REMOVED         1
39 int purge_subs();
40 void add_file(char *fn, char *galaxy, short wgport, ZSubscription_t *subs,
41               int mode);
42 void del_file(char *fn, char *galaxy, short wgport, ZSubscription_t *subs,
43               int mode);
44
45
46 int sci_idx;
47 char subsname[BUFSIZ];
48
49 extern ss_request_table zctl_cmds;
50
51 main(argc,argv)
52         int argc;
53         char *argv[];
54 {
55         struct passwd *pwd;
56         char ssline[BUFSIZ],oldsubsname[BUFSIZ],*envptr,*tty = NULL;
57         int retval,code,i;
58 #ifdef HAVE_SYS_UTSNAME
59         struct utsname name;
60 #endif
61
62         if ((retval = ZInitialize()) != ZERR_NONE) {
63                 com_err(argv[0],retval,"while initializing");
64                 exit (1);
65         }
66
67         /* Set hostname and tty for locations.  If we support X, use the
68          * DISPLAY environment variable for the tty name. */
69 #ifndef X_DISPLAY_MISSING
70         tty = getenv("DISPLAY");
71 #endif  
72         if ((retval = ZInitLocationInfo(NULL, tty)) != ZERR_NONE)
73             com_err(argv[0], retval, "initializing location information");
74
75         envptr = getenv("ZEPHYR_SUBS");
76         if (envptr)
77                 strcpy(subsname,envptr);
78         else {
79                 envptr = getenv("HOME");
80                 if (envptr)
81                         strcpy(subsname,envptr);
82                 else {
83                         if (!(pwd = getpwuid((int) getuid()))) {
84                                 fprintf(stderr,"Who are you?\n");
85                                 exit (1);
86                         }
87
88                         strcpy(subsname,pwd->pw_dir);
89                 }
90                 strcpy(oldsubsname,subsname);
91                 strcat(oldsubsname,OLD_SUBS);
92                 strcat(subsname,USERS_SUBS);
93                 if (!access(oldsubsname,F_OK) && access(subsname, F_OK)) {
94                         /* only if old one exists and new one does not exist */
95                         printf("The .subscriptions file in your home directory is now being used as\n.zephyr.subs . I will rename it to .zephyr.subs for you.\n");
96                         if (rename(oldsubsname,subsname))
97                                 com_err(argv[0], errno, "renaming .subscriptions");
98                 }
99         }
100
101         sci_idx = ss_create_invocation("zctl","",0,&zctl_cmds,&code);
102         if (code) {
103                 ss_perror(sci_idx,code,"while creating invocation");
104                 exit(1);
105         }
106
107         if (argc > 1) {
108                 *ssline = '\0';
109                 for (i=1;i<argc;i++)
110                         (void) sprintf(ssline+strlen(ssline),"%s ",argv[i]);
111                 ssline[strlen(ssline)-1] = '\0';
112                 code = ss_execute_line(sci_idx,ssline);
113                 if (code)
114                     fprintf (stderr, "%s: %s: %s\n",
115                              argv[0], error_message (code), ssline);
116                 exit((code != 0));
117         } 
118
119         printf("ZCTL $Revision: 1.28.4.1 $ (Protocol %s%d.%d) - Type '?' for a list of commands.\n\n",
120                ZVERSIONHDR,
121                ZVERSIONMAJOR,ZVERSIONMINOR_GALAXY);
122         
123         code = ss_listen(sci_idx);
124         exit(0);
125 }
126
127 void
128 set_file(argc,argv)
129         int argc;
130         char *argv[];
131 {
132         if (argc > 2) {
133                 fprintf(stderr,"Usage: %s filename\n",argv[0]);
134                 return;
135         }
136
137         if (argc == 1)
138                 printf("Current file: %s\n",subsname);
139         else
140                 (void) strcpy(subsname,argv[1]);
141 }
142
143 void
144 flush_locations(argc,argv)
145         int argc;
146         char *argv[];
147 {
148     int retval;
149     char *galaxy;
150     int cnt, i;
151         
152     if (argc > 2) {
153         fprintf(stderr,"Usage: %s [galaxy]\n",argv[0]);
154         return;
155     }
156
157     galaxy = (argc > 1)?argv[1]:NULL;
158
159     if (galaxy && strcmp(galaxy, "*") == 0) {
160         if (retval = ZGetGalaxyCount(&cnt)) {
161             ss_perror(sci_idx, retval, "while getting galaxy count");
162             return;
163         }
164
165         for (i=0; i<cnt; i++) {
166             if (retval = ZGetGalaxyName(i, &galaxy)) {
167                 ss_perror(sci_idx, retval, "while getting galaxy name");
168                 return;
169             }
170
171             if ((retval = ZFlushMyLocations(galaxy)) != ZERR_NONE) {
172                 ss_perror(sci_idx, retval, "while flushing locations");
173                 return;
174             }
175         }
176     } else {
177         if ((retval = ZFlushMyLocations(galaxy)) != ZERR_NONE) {
178             ss_perror(sci_idx, retval, "while flushing locations");
179             return;
180         }
181     }
182 }
183
184 void
185 wgc_control(argc,argv)
186         int argc;
187         char *argv[];
188 {
189         Code_t retval;
190
191         if (argc > 1) {
192                 fprintf(stderr,"Usage: %s\n",argv[0]);
193                 return;
194         }
195
196         if (!strcmp(argv[0],"wg_read")) {
197                 retval = send_wgc_control(USER_REREAD, NULL, 0);
198         } else if (!strcmp(argv[0],"wg_shutdown")) {
199                 retval = send_wgc_control(USER_SHUTDOWN, NULL, 0);
200         } else if (!strcmp(argv[0],"wg_startup")) {
201                 retval = send_wgc_control(USER_STARTUP, NULL, 0);
202         } else if (!strcmp(argv[0],"wg_exit")) {
203                 retval = send_wgc_control(USER_EXIT, NULL, 0);
204         } else {
205                 fprintf(stderr,
206                         "unknown WindowGram client control command %s\n",
207                         argv[0]);
208                 return;
209         }
210
211         if (retval)
212                 ss_perror(sci_idx, retval,
213                           "while sending WindowGram control message");
214 }
215
216 void
217 hm_control(argc,argv)
218         int argc;
219         char *argv[];
220 {
221     int retval;
222     ZNotice_t notice;
223     char *galaxy;
224     int cnt, i;
225
226     if (argc > 2) {
227         fprintf(stderr,"Usage: %s [galaxy]\n",argv[0]);
228         return;
229     }
230         
231     galaxy = (argc > 1)?argv[1]:NULL;
232
233     (void) memset((char *)&notice, 0, sizeof(notice));
234     notice.z_kind = HMCTL;
235     notice.z_port = 0;
236     notice.z_class = HM_CTL_CLASS;
237     notice.z_class_inst = HM_CTL_CLIENT;
238
239     if (!strcmp(argv[0],"hm_flush"))
240         notice.z_opcode = CLIENT_FLUSH;
241     if (!strcmp(argv[0],"new_server"))
242         notice.z_opcode = CLIENT_NEW_SERVER;
243     if (!notice.z_opcode) {
244         fprintf(stderr, "unknown HostManager control command %s\n",
245                 argv[0]);
246         return;
247     }
248     notice.z_sender = 0;
249     notice.z_recipient = "";
250     notice.z_default_format = "";
251     notice.z_message_len = 0;
252
253     if (galaxy && strcmp(galaxy, "*") == 0) {
254         if (retval = ZGetGalaxyCount(&cnt)) {
255             ss_perror(sci_idx, retval, "while getting galaxy count");
256             return;
257         }
258
259         for (i=0; i<cnt; i++) {
260             if (retval = ZGetGalaxyName(i, &galaxy)) {
261                 ss_perror(sci_idx, retval, "while getting galaxy name");
262                 return;
263             }
264
265             notice.z_dest_galaxy = galaxy;
266
267             if ((retval = ZSendNotice(&notice,ZNOAUTH)) != ZERR_NONE) {
268                 ss_perror(sci_idx,retval,"while sending notice");
269                 return;
270             }
271         }
272     } else {
273         if ((retval = ZSendNotice(&notice,ZNOAUTH)) != ZERR_NONE) {
274             ss_perror(sci_idx,retval,"while sending notice");
275             return;
276         }
277     }
278
279
280 void
281 show_var(argc,argv)
282         int argc;
283         char *argv[];
284 {
285         int i;
286         char *value;
287         
288         if (argc < 2) {
289                 fprintf(stderr,"Usage: %s <varname> <varname> ...\n",argv[0]);
290                 return;
291         }
292
293         for (i=1;i<argc;i++) {
294                 value = ZGetVariable(argv[i]);
295                 if (value)
296                         printf("%s: %s\n",argv[i],value);
297                 else
298                         printf("%s: not defined\n",argv[i]);
299         }
300 }
301
302 void
303 set_var(argc,argv)
304         int argc;
305         register char **argv;
306 {
307     int retval,setting_exp,i;
308     char *galaxy;
309     char varcat[BUFSIZ];
310         
311     if (argc < 2) {
312         fprintf(stderr,"Usage: %s <varname> [value]\n",
313                 argv[0]);
314         return;
315     }
316
317     setting_exp = 0;
318
319     if (strncasecmp(argv[1],"exposure",8) == 0) {
320         setting_exp = 1;
321         if (argc != 3) {
322             fprintf(stderr, "An exposure setting must be specified.\n");
323             return;
324         }
325         if (strlen(argv[1]) == 8) {
326             galaxy = NULL; /* the default */
327         } else if ((strlen(argv[1]) == 9) ||
328                    (ZGetRhs(argv[1]+9) == NULL)) {
329             fprintf(stderr, "The exposure variable's galaxy name was empty or invalid.\nUse a variable of the form exposure-GALAXYNAME.\n");
330             return;
331         } else {
332             galaxy = argv[1]+9;
333         }
334     } 
335
336     if (argc == 2)
337         retval = ZSetVariable(argv[1],"");
338     else {
339         (void) strcpy(varcat,argv[2]);
340         for (i=3;i<argc;i++) {
341             (void) strcat(varcat," ");
342             (void) strcat(varcat,argv[i]);
343         } 
344         retval = ZSetVariable(argv[1],varcat);
345     } 
346
347     if (retval != ZERR_NONE) {
348         ss_perror(sci_idx,retval,"while setting variable value");
349         return;
350     }
351
352     /* Side-effects?  Naw, us? */
353         
354     if (setting_exp)
355         set_exposure(galaxy?galaxy:"*", argv[2]);
356 }
357
358 void
359 do_hide(argc,argv)
360         int argc;
361         char *argv[];
362 {
363     char *exp_level;
364     char *galaxy;
365     int cnt, i;
366     Code_t code;
367
368     if (argc > 2) {
369         fprintf(stderr, "Usage: %s [galaxy]\n",argv[0]);
370         return;
371     }
372
373     if (strcmp(argv[0], "unhide") == 0) {
374         exp_level = ZGetVariable("exposure");
375         if (exp_level)
376             exp_level = ZParseExposureLevel(exp_level);
377         if (!exp_level)
378             exp_level = EXPOSE_REALMVIS;
379     } else {
380         exp_level = EXPOSE_OPSTAFF;
381     }
382
383     galaxy = (argc > 1)?argv[1]:NULL;
384
385     if (code = set_exposure(galaxy, exp_level)) {
386         ss_perror(sci_idx, code, "while setting exposures");
387         return;
388     }
389 }
390
391 void
392 unset_var(argc,argv)
393         int argc;
394         char *argv[];
395 {
396         int retval,i;
397         
398         if (argc < 2) {
399                 fprintf(stderr,"Usage: %s <varname> [<varname> ... ]\n",
400                         argv[0]);
401                 return;
402         }
403
404         for (i=1;i<argc;i++)
405                 if ((retval = ZUnsetVariable(argv[i])) != ZERR_NONE)
406                         ss_perror(sci_idx,retval,
407                                   "while unsetting variable value");
408 }
409         
410 void
411 cancel_subs(argc,argv)
412         int argc;
413         char *argv[];
414 {
415     int retval;
416     short wgport;
417     int i, cnt;
418     char *galaxy;
419
420     if (argc > 2) {
421         fprintf(stderr,"Usage: %s [galaxy]\n",argv[0]);
422         return;
423     }
424
425     if ((wgport = ZGetWGPort()) == -1) {
426         ss_perror(sci_idx,errno,"while finding WindowGram port");
427         return;
428     } 
429
430     galaxy = (argc > 1)?argv[1]:NULL;
431
432     if (galaxy && strcmp(galaxy, "*") == 0) {
433         if (retval = ZGetGalaxyCount(&cnt)) {
434             ss_perror(sci_idx, retval, "while getting galaxy count");
435             return;
436         }
437
438         for (i=0; i<cnt; i++) {
439             if (retval = ZGetGalaxyName(i, &galaxy)) {
440                 ss_perror(sci_idx, retval, "while getting galaxy name");
441                 return;
442             }
443
444             if ((retval = ZCancelSubscriptions(galaxy, (u_short)wgport))
445                 != ZERR_NONE) {
446                 ss_perror(sci_idx,retval,"while cancelling subscriptions");
447                 return;
448             }
449         }
450     } else {
451         if ((retval = ZCancelSubscriptions(galaxy, (u_short)wgport))
452             != ZERR_NONE) {
453             ss_perror(sci_idx,retval,"while cancelling subscriptions");
454             return;
455         }
456     }
457 }
458
459 void
460 subscribe(argc,argv)
461         int argc;
462         char *argv[];
463 {
464         int retval;
465         short wgport;
466         ZSubscription_t sub,sub2;
467         char *galaxy;
468         int mode;
469         
470         if (argc > 5 || argc < 3) {
471                 fprintf(stderr,"Usage: %s class instance [* [galaxy]]\n",
472                         argv[0]);
473                 return;
474         }
475         
476         if (strncmp(argv[0], "sub", 3) == 0) {
477                 mode = SUB;
478         } else if (strncmp(argv[0], "unsub", 5) == 0) {
479                 mode = UNSUB;
480         } else if ((strncmp(argv[0], "punt", 4) == 0) ||
481                    (strncmp(argv[0], "sup", 3) == 0)) {
482                 mode = PUNT;
483         } else if ((strncmp(argv[0], "unpunt", 6) == 0) ||
484                    (strncmp(argv[0], "unsup", 5) == 0)) {
485                 mode = UNPUNT;
486         } else {
487                 ss_perror(sci_idx, 0, "internal error in subscribe");
488                 exit(1);
489         }
490
491         sub.zsub_class = argv[1];
492         sub.zsub_classinst = argv[2];
493         sub.zsub_recipient = (argc > 3)?argv[3]:
494                 (((mode == PUNT) || (mode == UNPUNT))?"":ZGetSender());
495         galaxy = (argc > 4)?argv[4]:NULL;
496
497         fix_macros(&sub,&sub2,1);
498         
499         if ((wgport = ZGetWGPort()) == -1) {
500                 ss_perror(sci_idx,errno,"while finding WindowGram port");
501                 return;
502         } 
503
504         switch (mode) {
505         case SUB:
506                 if (retval = ZSubscribeTo(galaxy, &sub2, 1, (u_short) wgport))
507                         ss_perror(sci_idx, retval, "while subscribing");
508                 break;
509         case UNSUB:
510                 if (retval = ZUnsubscribeTo(galaxy, &sub2, 1, (u_short) wgport))
511                         ss_perror(sci_idx, retval, "while subscribing");
512                 break;
513         case PUNT:
514                 if (retval = xpunt(sub2.zsub_class, sub2.zsub_classinst,
515                                   sub2.zsub_recipient, PUNT))
516                         ss_perror(sci_idx, retval, "while suppressing");
517                 break;
518         case UNPUNT:
519                 if (retval = xpunt(sub2.zsub_class, sub2.zsub_classinst,
520                                     sub2.zsub_recipient, UNPUNT))
521                         ss_perror(sci_idx, retval, "while unsuppressing");
522                 break;
523         }
524
525
526 void
527 sub_file(argc,argv)
528         int argc;
529         char *argv[];
530 {
531         ZSubscription_t sub;
532         short wgport;
533         char fn[MAXPATHLEN];
534         char *arggalaxy, *galaxy;
535         int cnt, i;
536         Code_t retval;
537         int del, mode;
538
539         if (argc > 5 || argc < 3) {
540                 fprintf(stderr,"Usage: %s class instance [* [galaxy]]\n",
541                         argv[0]);
542                 return;
543         }
544
545         if (!strcmp(argv[0],"add")) {
546                 del = 0;
547                 mode = SUB;
548         } else if (!strcmp(argv[0],"add_unsubscription") ||
549                    !strcmp(argv[0],"add_un")) {
550                 del = 0;
551                 mode = UNSUB;
552         } else if (!strcmp(argv[0],"add_suppression") ||
553                    !strcmp(argv[0],"add_punt")) {
554                 del = 0;
555                 mode = PUNT;
556         } else if (!strcmp(argv[0],"delete") ||
557                    !strcmp(argv[0],"del") ||
558                    !strcmp(argv[0],"dl")) {
559                 del = 1;
560                 mode = SUB;
561         } else if (!strcmp(argv[0],"delete_unsubscription") ||
562                    !strcmp(argv[0],"del_un")) {
563                 del = 1;
564                 mode = UNSUB;
565         } else if (!strcmp(argv[0],"delete_suppression") ||
566                    !strcmp(argv[0],"del_punt")) {
567                 del = 1;
568                 mode = PUNT;
569         } else {
570                 ss_perror(sci_idx,0,"unknown command name");
571         }
572
573         if (argv[1][0] == '!') {
574                 ss_perror(sci_idx,0, (mode == UNSUB)?
575                           "Do not use `!' as the first character of a class.\n\tIt is automatically added before modifying the subscription file." :
576                           "Do not use `!' as the first character of a class.\n\tIt is reserved for internal use with un-subscriptions.");
577                 return;
578         } else if (argv[1][0] == '-') {
579                 ss_perror(sci_idx,0, (mode == PUNT)?
580                           "Do not use `-' as the first character of a class.\n\tIt is automatically added before modifying the subscription file." :
581                           "Do not use `-' as the first character of a class.\n\tIt is reserved for internal use with suppressions.");
582                 return;
583         }
584
585         sub.zsub_class = argv[1];
586         sub.zsub_classinst = argv[2];
587         sub.zsub_recipient = (argc > 3)?argv[3]:
588                 (((mode == PUNT) || (mode == UNPUNT))?"":TOKEN_ME);
589         arggalaxy = (argc > 4)?argv[4]:NULL;
590
591         if (arggalaxy) {
592             if (retval = ZGetGalaxyCount(&cnt)) {
593                 ss_perror(sci_idx, retval, "while getting galaxy count");
594                 return;
595             }
596
597             for (i=0; i<cnt; i++) {
598                 if (retval = ZGetGalaxyName(i, &galaxy)) {
599                     ss_perror(sci_idx, retval, "while getting galaxy name");
600                     return;
601                 }
602
603                 if (strcasecmp(galaxy, arggalaxy) == 0)
604                     break;
605             }
606
607             if (i == cnt) {
608                 ss_perror(sci_idx, 0,
609                           "unknown galaxy specified while modifying subscripion file");
610                 return;
611             }
612         } else {
613             galaxy = ZGetDefaultGalaxy();
614         }
615
616         if ((wgport = ZGetWGPort()) == -1) {
617                 ss_perror(sci_idx,errno,"while finding WindowGram port");
618                 return;
619         } 
620
621         strcpy(fn, subsname);
622         strcat(fn, "-");
623         strcat(fn, galaxy);
624
625         if (!strcmp(argv[0],"add")) {
626                 add_file(fn, galaxy, wgport, &sub, SUB);
627         } else if (!strcmp(argv[0],"add_unsubscription") ||
628                    !strcmp(argv[0],"add_un")) {
629                 add_file(fn, galaxy, wgport, &sub, UNSUB);
630         } else if (!strcmp(argv[0],"add_suppression") ||
631                    !strcmp(argv[0],"add_punt")) {
632                 add_file(fn, galaxy, wgport, &sub, PUNT);
633         } else if (!strcmp(argv[0],"delete") ||
634                    !strcmp(argv[0],"del") ||
635                    !strcmp(argv[0],"dl")) {
636                 del_file(fn, galaxy, wgport, &sub, SUB);
637         } else if (!strcmp(argv[0],"delete_unsubscription") ||
638                    !strcmp(argv[0],"del_un")) {
639                 del_file(fn, galaxy, wgport, &sub, UNSUB);
640         } else if (!strcmp(argv[0],"delete_suppression") ||
641                    !strcmp(argv[0],"del_punt")) {
642                 del_file(fn, galaxy, wgport, &sub, PUNT);
643         } else {
644                 ss_perror(sci_idx,0,"unknown command name");
645         }
646         return;
647 }
648
649 void
650 add_file(fn,galaxy,wgport,subs,mode)
651      char *fn;
652      char *galaxy;
653      short wgport;
654      ZSubscription_t *subs;
655      int mode;
656 {
657         FILE *fp;
658         char errbuf[BUFSIZ];
659         ZSubscription_t sub2;
660         Code_t retval;
661
662         (void) purge_subs(fn,subs,ALL); /* remove copies in the subs file */
663         if (!(fp = fopen(fn,"a"))) {
664                 (void) sprintf(errbuf,"while opening %s for append", fn);
665                 ss_perror(sci_idx,errno,errbuf);
666                 return;
667         } 
668         fprintf(fp,"%s%s,%s,%s\n",
669                 ((mode == UNSUB) ? "!" : 
670                  ((mode == PUNT) ? "*" :
671                   "")),
672                 subs->zsub_class, subs->zsub_classinst, subs->zsub_recipient);
673         if (fclose(fp) == EOF) {
674                 (void) sprintf(errbuf, "while closing %s", subsname);
675                 ss_perror(sci_idx, errno, errbuf);
676                 return;
677         }
678         fix_macros(subs,&sub2,1);
679         if (mode == UNSUB) {
680                 if (retval = ZUnsubscribeTo(galaxy, &sub2,1,(u_short)wgport))
681                         ss_perror(sci_idx, retval, "while subscribing");
682         } else if (mode == PUNT) {
683                 if (retval = xpunt(sub2.zsub_class, sub2.zsub_classinst,
684                                   sub2.zsub_recipient, PUNT))
685                         ss_perror(sci_idx, retval, "while unsubscribing");
686         } else {
687                 if (retval = ZSubscribeTo(galaxy, &sub2,1,(u_short)wgport))
688                         ss_perror(sci_idx, retval, "while suppressing");
689         }
690
691         return;
692 }
693
694 void
695 del_file(fn,galaxy,wgport,subs,mode)
696      char *fn;
697      char *galaxy;
698      short wgport;
699      ZSubscription_t *subs;
700      int mode;
701 {
702         ZSubscription_t sub2;
703         int retval;
704         
705         retval = purge_subs(fn, subs, mode);
706         if (retval == ERR)
707                 return;
708         if (retval == NOT_REMOVED)
709                 fprintf(stderr,
710                         "Couldn't find %sclass %s instance %s recipient %s in\n\tfile %s\n",
711                         ((mode == UNSUB) ? "un-subscription " : 
712                          ((mode == PUNT) ? "suppression " :
713                           "")),
714                         subs->zsub_class, subs->zsub_classinst,
715                         subs->zsub_recipient, subsname);
716         fix_macros(subs,&sub2,1);
717         if (mode == PUNT) {
718                 if (retval = xpunt(sub2.zsub_class, sub2.zsub_classinst,
719                                     sub2.zsub_recipient, UNPUNT))
720                         ss_perror(sci_idx,retval,"while unsuppressing");
721         } else if ((retval = ZUnsubscribeTo(galaxy, &sub2,1,(u_short)wgport)) !=
722                    ZERR_NONE) {
723                 ss_perror(sci_idx,retval,"while unsubscribing");
724         }
725 }
726
727 int
728 purge_subs(fn, subs, mode)
729      char *fn;
730      register ZSubscription_t *subs;
731      int mode;
732 {
733         FILE *fp,*fpout;
734         char errbuf[BUFSIZ],subline[BUFSIZ];
735         char backup[BUFSIZ],ourline[BUFSIZ];
736         int delflag = NOT_REMOVED;
737         int purge;
738
739         switch (mode) {
740         case SUB:
741         case UNSUB:
742         case PUNT:
743         case ALL:
744                 break;
745         default:
746                 ss_perror(sci_idx,0,"internal error in purge_subs");
747                 return(ERR);
748         }
749
750         (void) sprintf(ourline,"%s,%s,%s",
751                        subs->zsub_class,
752                        subs->zsub_classinst,
753                        subs->zsub_recipient);
754
755         if (!(fp = fopen(fn,"r"))) {
756                 if (errno == ENOENT)
757                         /* if the filw doesn't exist, then the sub
758                            is clearly purged */
759                         return(delflag);
760                 (void) sprintf(errbuf,"while opening %s for read", fn);
761                 ss_perror(sci_idx,errno,errbuf);
762                 return(ERR);
763         } 
764         (void) strcpy(backup, fn);
765         (void) strcat(backup, ".temp");
766         (void) unlink(backup);
767         if (!(fpout = fopen(backup,"w"))) {
768                 (void) sprintf(errbuf,"while opening %s for writing",backup);
769                 ss_perror(sci_idx,errno,errbuf);
770                 (void) fclose(fp);
771                 return(ERR);
772         } 
773         for (;;) {
774                 if (!fgets(subline,sizeof subline,fp))
775                         break;
776                 if (*subline)
777                         subline[strlen(subline)-1] = '\0'; /* nuke newline */
778                 switch (mode) {
779                 case SUB:
780                         purge = (strcmp(subline,ourline) == 0);
781                         break;
782                 case UNSUB:
783                         purge = (*subline == '!' &&
784                                  (strcmp(subline+1,ourline) == 0));
785                         break;
786                 case PUNT:
787                         purge = (*subline == '-' &&
788                                  (strcmp(subline+1,ourline) == 0));
789                         break;
790                 case ALL:
791                         purge = ((strcmp(subline,ourline) == 0) ||
792                                  (((*subline == '!') || (*subline == '-')) &&
793                                   (strcmp(subline+1, ourline) == 0)));
794                         break;
795                 }
796                 if (purge) {
797                         delflag = REMOVED;
798                 } else {
799                         fputs(subline, fpout);
800                         if (ferror(fpout) || (fputc('\n', fpout) == EOF)) {
801                                 (void) sprintf(errbuf, "while writing to %s",
802                                                backup);
803                                 ss_perror(sci_idx, errno, errbuf);
804                         }
805                 }
806         }
807         (void) fclose(fp);              /* open read-only, ignore errs */
808         if (fclose(fpout) == EOF) {
809                 (void) sprintf(errbuf, "while closing %s",backup);
810                 ss_perror(sci_idx, errno, errbuf);
811                 return(ERR);
812         }
813         if (rename(backup, fn) == -1) {
814                 (void) sprintf(errbuf,"while renaming %s to %s\n",
815                                backup, fn);
816                 ss_perror(sci_idx,errno,errbuf);
817                 return(ERR);
818         }
819         return(delflag);
820 }
821
822 void
823 load_subs(argc,argv)
824         int argc;
825         char *argv[];
826 {
827         int type, cnt, i;
828         char *file;
829         char *arggalaxy, *galaxy;
830         Code_t code;
831
832         if (argc > 3) {
833                 fprintf(stderr,"Usage: %s [file [galaxy]]\n",argv[0]);
834                 return;
835         }
836
837         if (*argv[0] == 'u')
838                 type = UNSUB;
839         else if (!strcmp(argv[0],"list") || !strcmp(argv[0],"ls"))
840                 type = LIST;
841         else
842                 type = SUB;
843
844         file = (argc > 1)?argv[1]:subsname;
845         arggalaxy = (argc > 2)?argv[2]:NULL;
846
847         if (arggalaxy) {
848             if (code = ZGetGalaxyCount(&cnt)) {
849                 ss_perror(sci_idx, code, "while getting galaxy count");
850                 return;
851             }
852
853             for (i=0; i<cnt; i++) {
854                 if (code = ZGetGalaxyName(i, &galaxy)) {
855                     ss_perror(sci_idx, code, "while getting galaxy name");
856                     return;
857                 }
858
859                 if (strcasecmp(galaxy, arggalaxy) == 0)
860                     break;
861             }
862
863             if (i == cnt) {
864                 ss_perror(sci_idx, 0,
865                           "unknown galaxy specified while loading subscription file");
866                 return;
867             }
868         } else {
869             galaxy = NULL;
870         }
871
872         if (code = load_sub_file(type, file, galaxy))
873             ss_perror(sci_idx, code,
874                       "while loading subscription file");
875
876 }
877
878 void
879 loadall(argc,argv)
880         int argc;
881         char *argv[];
882 {       
883     int retval;
884     char *galaxy;
885     int type, cnt, i;
886     char fn[MAXPATHLEN];
887         
888     if (argc > 1) {
889         fprintf(stderr,"Usage: %s\n",argv[0]);
890         return;
891     }
892
893     if (!strcmp(argv[0],"list") || !strcmp(argv[0],"ls"))
894         type = LIST;
895     else
896         type = SUB;
897
898     load_all_sub_files(type, subsname);
899 }
900
901 void
902 current(argc,argv)
903         int argc;
904         char *argv[];
905 {
906         FILE *fp;
907         char errbuf[BUFSIZ];
908         ZSubscription_t subs;
909         int i,nsubs,retval,save,one,defs;
910         short wgport;
911         char *galaxy, *file, backup[BUFSIZ];
912         
913         save = 0;
914         defs = 0;
915
916         if (!strcmp(argv[0],"save"))
917                 save = 1;
918         else if (!strcmp(argv[0], "defaults") || !strcmp(argv[0], "defs"))
919                 defs = 1;
920
921         if (save) {
922                 if (argc > 3) {
923                         fprintf(stderr,"Usage: %s [filename [galaxy]]\n",
924                                 argv[0]);
925                         return;
926                 } else {
927                         file = (argc > 1)?argv[1]:subsname;
928                         galaxy = (argc > 2)?argv[2]:NULL;
929                 }
930         } else {
931                 if (argc > 2) {
932                         fprintf(stderr,"Usage: %s [galaxy]\n",argv[0]);
933                         return;
934                 } else {
935                         galaxy = (argc > 1)?argv[1]:NULL;
936                 }
937         }
938
939         if (!defs)
940                 if ((wgport = ZGetWGPort()) == -1) {
941                         ss_perror(sci_idx,errno,
942                                   "while finding WindowGram port");
943                         return;
944                 } 
945
946         if (defs)
947                 retval = ZRetrieveDefaultSubscriptions(galaxy, &nsubs);
948         else
949                 retval = ZRetrieveSubscriptions(galaxy,(u_short)wgport,&nsubs);
950
951         if (retval == ZERR_TOOMANYSUBS) {
952                 fprintf(stderr,"Too many subscriptions -- some have not been returned.\n");
953                 if (save) {
954                         fprintf(stderr,"Save aborted.\n");
955                         return;
956                 }
957         }
958         else
959                 if (retval != ZERR_NONE) {
960                         ss_perror(sci_idx,retval,"retrieving subscriptions");
961                         return;
962                 }
963
964         if (save) {
965                 (void) strcpy(backup,file);
966                 (void) strcat(backup,".temp");
967                 if (!(fp = fopen(backup,"w"))) {
968                         (void) sprintf(errbuf,"while opening %s for write",
969                                        backup);
970                         ss_perror(sci_idx,errno,errbuf);
971                         return;
972                 }
973         }
974         
975         for (i=0;i<nsubs;i++) {
976                 one = 1;
977                 if ((retval = ZGetSubscriptions(&subs,&one)) != ZERR_NONE) {
978                         ss_perror(sci_idx,retval,"while getting subscription");
979                         if (save) {
980                                 fprintf(stderr,"Subscriptions file not modified\n");
981                                 (void) fclose(fp);
982                                 (void) unlink(backup);
983                         }
984                         return;
985                 } 
986                 if (save)
987                         fprintf(fp,"%s,%s,%s\n",subs.zsub_class,
988                                 subs.zsub_classinst, subs.zsub_recipient);
989                 else
990                         printf("Class %s Instance %s Recipient %s\n",
991                                subs.zsub_class, subs.zsub_classinst,
992                                subs.zsub_recipient);
993         }
994
995         if (save) {
996                 if (fclose(fp) == EOF) {
997                         (void) sprintf(errbuf, "while closing %s", backup);
998                         ss_perror(sci_idx, errno, errbuf);
999                         return;
1000                 }
1001                 if (rename(backup,file) == -1) {
1002                         (void) sprintf(errbuf,"while renaming %s to %s",
1003                                        backup,file);
1004                         ss_perror(sci_idx,retval,errbuf);
1005                         (void) unlink(backup);
1006                 }
1007         }
1008 }