1392 lines
33 KiB
C
1392 lines
33 KiB
C
/* This file is part of the Project Athena Zephyr Notification System.
|
|
* It contains code for the "zctl" command.
|
|
*
|
|
* Created by: Robert French
|
|
*
|
|
* $Id$
|
|
*
|
|
* Copyright (c) 1987,1988 by the Massachusetts Institute of Technology.
|
|
* For copying and distribution information, see the file
|
|
* "mit-copyright.h".
|
|
*/
|
|
|
|
#include <sysdep.h>
|
|
#include <zephyr/zephyr.h>
|
|
#ifdef HAVE_SS
|
|
#include <ss/ss.h>
|
|
#endif
|
|
#include <pwd.h>
|
|
#include <netdb.h>
|
|
#include <arpa/nameser.h>
|
|
#ifndef lint
|
|
static const char rcsid_zctl_c[] = "$Id$";
|
|
#endif
|
|
|
|
#define SUBSATONCE 7
|
|
#define SUB 0
|
|
#define UNSUB 1
|
|
#define LIST 2
|
|
|
|
#define USERS_SUBS "/.zephyr.subs"
|
|
#define OLD_SUBS "/.subscriptions"
|
|
|
|
#define TOKEN_HOSTNAME "%host%"
|
|
#define TOKEN_CANONNAME "%canon%"
|
|
#define TOKEN_ME "%me%"
|
|
#define TOKEN_WILD "*"
|
|
|
|
#define ALL 0
|
|
#define UNSUBONLY 1
|
|
#define SUBONLY 2
|
|
|
|
#define ERR (-1)
|
|
#define NOT_REMOVED 0
|
|
#define REMOVED 1
|
|
|
|
#ifdef HAVE_SS
|
|
int sci_idx;
|
|
#endif
|
|
char subsname[BUFSIZ];
|
|
char ourhost[NS_MAXDNAME], ourhostcanon[NS_MAXDNAME];
|
|
|
|
#ifdef HAVE_SS
|
|
extern ss_request_table zctl_cmds;
|
|
#endif
|
|
|
|
int purge_subs(register ZSubscription_t *, int);
|
|
void add_file(short, ZSubscription_t *, int);
|
|
void del_file(short, ZSubscription_t *, int);
|
|
void fix_macros(ZSubscription_t *, ZSubscription_t *, int);
|
|
void fix_macros2(char *, char **);
|
|
int make_exist(char *);
|
|
char *whoami;
|
|
|
|
#ifndef HAVE_SS
|
|
static void run_command(int, char *[]);
|
|
static void show_commands(int, char *[]);
|
|
#endif
|
|
|
|
/* Prototype all of the commands.
|
|
* These really should be in a header also visible to zctl_cmds.c,
|
|
* but mk_cmds doesn't make that easy.
|
|
*/
|
|
void cancel_subs(int argc, char *argv[]);
|
|
void current(int argc, char *argv[]);
|
|
void do_hide(int argc, char *argv[]);
|
|
void do_punt(int argc, char *argv[]);
|
|
void flush_locations(int argc, char *argv[]);
|
|
void flush_subscr(int argc, char *argv[]);
|
|
void hm_control(int argc, char *argv[]);
|
|
void list_punts(int argc, char *argv[]);
|
|
void load_subs(int argc, char *argv[]);
|
|
void set_file(int argc, char *argv[]);
|
|
void set_var(int argc, char *argv[]);
|
|
void show_var(int argc, char *argv[]);
|
|
void sub_file(int argc, char *argv[]);
|
|
void subscribe(int argc, char *argv[]);
|
|
void unset_var(int argc, char *argv[]);
|
|
void wgc_control(int argc, char *argv[]);
|
|
|
|
|
|
int
|
|
main(int argc,
|
|
char *argv[])
|
|
{
|
|
struct passwd *pwd;
|
|
struct hostent *hent;
|
|
char ssline[BUFSIZ],oldsubsname[BUFSIZ],*envptr,*tty = NULL;
|
|
int retval,code,i;
|
|
#ifdef HAVE_SYS_UTSNAME
|
|
struct utsname name;
|
|
#endif
|
|
|
|
whoami = argv[0];
|
|
if ((retval = ZInitialize()) != ZERR_NONE) {
|
|
com_err(argv[0],retval,"while initializing");
|
|
exit (1);
|
|
}
|
|
|
|
/* Set hostname and tty for locations. If we support X, use the
|
|
* DISPLAY environment variable for the tty name. */
|
|
#ifndef X_DISPLAY_MISSING
|
|
tty = getenv("DISPLAY");
|
|
#endif
|
|
if ((retval = ZInitLocationInfo(NULL, tty)) != ZERR_NONE)
|
|
com_err(argv[0], retval, "initializing location information");
|
|
|
|
envptr = getenv("ZEPHYR_SUBS");
|
|
if (envptr)
|
|
strcpy(subsname,envptr);
|
|
else {
|
|
envptr = getenv("HOME");
|
|
if (envptr)
|
|
strcpy(subsname,envptr);
|
|
else {
|
|
if (!(pwd = getpwuid((int) getuid()))) {
|
|
fprintf(stderr,"Who are you?\n");
|
|
exit (1);
|
|
}
|
|
|
|
strcpy(subsname,pwd->pw_dir);
|
|
}
|
|
strcpy(oldsubsname,subsname);
|
|
strcat(oldsubsname,OLD_SUBS);
|
|
strcat(subsname,USERS_SUBS);
|
|
if (!access(oldsubsname,F_OK) && access(subsname, F_OK)) {
|
|
/* only if old one exists and new one does not exist */
|
|
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");
|
|
if (rename(oldsubsname,subsname))
|
|
com_err(argv[0], errno, "renaming .subscriptions");
|
|
}
|
|
}
|
|
|
|
#ifdef HAVE_SYS_UTSNAME
|
|
uname(&name);
|
|
strcpy(ourhost, name.nodename);
|
|
#else
|
|
if (gethostname(ourhost, sizeof(ourhost)) == -1) {
|
|
com_err(argv[0],errno,"while getting host name");
|
|
exit (1);
|
|
}
|
|
#endif
|
|
|
|
if (!(hent = gethostbyname(ourhost))) {
|
|
fprintf(stderr,"%s: Can't resolve hostname %s; %s may be "
|
|
"wrong in subscriptions\n",argv[0],ourhost,
|
|
TOKEN_CANONNAME);
|
|
strncpy(ourhostcanon,ourhost,sizeof(ourhostcanon)-1);
|
|
} else
|
|
strncpy(ourhostcanon,hent->h_name,sizeof(ourhostcanon)-1);
|
|
|
|
#ifdef HAVE_SS
|
|
sci_idx = ss_create_invocation("zctl","",0,&zctl_cmds,&code);
|
|
if (code) {
|
|
ss_perror(sci_idx,code,"while creating invocation");
|
|
exit(1);
|
|
#else
|
|
if (argc <= 1) {
|
|
printf("ZCTL $Revision$ (Protocol %s%d.%d)\nType '%s help' for a list of subcommands.\n\n",
|
|
ZVERSIONHDR,
|
|
ZVERSIONMAJOR,ZVERSIONMINOR,
|
|
argv[0]);
|
|
exit(0);
|
|
#endif
|
|
}
|
|
|
|
#ifdef HAVE_SS
|
|
if (argc > 1) {
|
|
*ssline = '\0';
|
|
for (i=1;i<argc;i++)
|
|
(void) sprintf(ssline+strlen(ssline),"%s ",argv[i]);
|
|
ssline[strlen(ssline)-1] = '\0';
|
|
code = ss_execute_line(sci_idx,ssline);
|
|
if (code)
|
|
fprintf (stderr, "%s: %s: %s\n",
|
|
argv[0], error_message (code), ssline);
|
|
exit((code != 0));
|
|
}
|
|
|
|
printf("ZCTL $Revision$ (Protocol %s%d.%d) - Type '?' for a list of commands.\n\n",
|
|
ZVERSIONHDR,
|
|
ZVERSIONMAJOR,ZVERSIONMINOR);
|
|
|
|
ss_listen(sci_idx);
|
|
#else
|
|
run_command(argc-1, argv+1);
|
|
#endif
|
|
exit(0);
|
|
}
|
|
|
|
void
|
|
set_file(int argc,
|
|
char *argv[])
|
|
{
|
|
if (argc > 2) {
|
|
fprintf(stderr,"Usage: %s filename\n",argv[0]);
|
|
return;
|
|
}
|
|
|
|
if (argc == 1)
|
|
printf("Current file: %s\n",subsname);
|
|
else
|
|
(void) strcpy(subsname,argv[1]);
|
|
}
|
|
|
|
void
|
|
flush_locations(int argc,
|
|
char *argv[])
|
|
{
|
|
int retval;
|
|
|
|
if (argc > 2) {
|
|
fprintf(stderr,"Usage: %s [user]\n",argv[0]);
|
|
return;
|
|
}
|
|
|
|
if (argc > 1)
|
|
retval = ZFlushUserLocations(argv[1]);
|
|
else
|
|
retval = ZFlushMyLocations();
|
|
|
|
if (retval != ZERR_NONE)
|
|
com_err(whoami, retval, "while flushing locations");
|
|
}
|
|
|
|
void
|
|
flush_subscr(int argc,
|
|
char *argv[])
|
|
{
|
|
int retval;
|
|
|
|
if (argc > 2) {
|
|
fprintf(stderr,"Usage: %s [recipient]\n",argv[0]);
|
|
return;
|
|
}
|
|
|
|
retval = ZFlushUserSubscriptions((argc > 1) ? argv[1] : NULL);
|
|
if (retval != ZERR_NONE)
|
|
com_err(whoami, retval, "while flushing subscriptions");
|
|
}
|
|
|
|
void
|
|
wgc_control(int argc,
|
|
char *argv[])
|
|
{
|
|
int retval;
|
|
short newport;
|
|
struct sockaddr_in newsin;
|
|
ZNotice_t notice;
|
|
|
|
newsin = ZGetDestAddr();
|
|
|
|
if (argc > 1) {
|
|
fprintf(stderr,"Usage: %s\n",argv[0]);
|
|
return;
|
|
}
|
|
|
|
if ((newport = ZGetWGPort()) == -1) {
|
|
com_err(whoami, errno, "while getting WindowGram port");
|
|
return;
|
|
}
|
|
|
|
newsin.sin_port = (u_short) newport;
|
|
if ((retval = ZSetDestAddr(&newsin)) != ZERR_NONE) {
|
|
com_err(whoami, retval, "while setting destination address");
|
|
return;
|
|
}
|
|
|
|
(void) memset((char *)¬ice, 0, sizeof(notice));
|
|
notice.z_kind = UNSAFE;
|
|
notice.z_port = 0;
|
|
notice.z_class = WG_CTL_CLASS;
|
|
notice.z_class_inst = WG_CTL_USER;
|
|
|
|
if (!strcmp(argv[0],"wg_read"))
|
|
notice.z_opcode = USER_REREAD;
|
|
if (!strcmp(argv[0],"wg_shutdown"))
|
|
notice.z_opcode = USER_SHUTDOWN;
|
|
if (!strcmp(argv[0],"wg_startup"))
|
|
notice.z_opcode = USER_STARTUP;
|
|
if (!strcmp(argv[0],"wg_exit"))
|
|
notice.z_opcode = USER_EXIT;
|
|
if (!notice.z_opcode) {
|
|
fprintf(stderr,
|
|
"unknown WindowGram client control command %s\n",
|
|
argv[0]);
|
|
return;
|
|
}
|
|
notice.z_sender = 0;
|
|
notice.z_recipient = "";
|
|
notice.z_default_format = "";
|
|
notice.z_message_len = 0;
|
|
|
|
if ((retval = ZSendNotice(¬ice,ZNOAUTH)) != ZERR_NONE)
|
|
com_err(whoami, retval, "while sending notice");
|
|
|
|
if ((retval = ZInitialize()) != ZERR_NONE)
|
|
com_err(whoami, retval,
|
|
"while reinitializing");
|
|
}
|
|
|
|
void
|
|
hm_control(int argc,
|
|
char *argv[])
|
|
{
|
|
int retval;
|
|
ZNotice_t notice;
|
|
|
|
if (argc > 1) {
|
|
fprintf(stderr,"Usage: %s\n",argv[0]);
|
|
return;
|
|
}
|
|
|
|
(void) memset((char *)¬ice, 0, sizeof(notice));
|
|
notice.z_kind = HMCTL;
|
|
notice.z_port = 0;
|
|
notice.z_class = HM_CTL_CLASS;
|
|
notice.z_class_inst = HM_CTL_CLIENT;
|
|
|
|
if (!strcmp(argv[0],"hm_flush"))
|
|
notice.z_opcode = CLIENT_FLUSH;
|
|
if (!strcmp(argv[0],"new_server"))
|
|
notice.z_opcode = CLIENT_NEW_SERVER;
|
|
if (!notice.z_opcode) {
|
|
fprintf(stderr, "unknown HostManager control command %s\n",
|
|
argv[0]);
|
|
return;
|
|
}
|
|
notice.z_sender = 0;
|
|
notice.z_recipient = "";
|
|
notice.z_default_format = "";
|
|
notice.z_message_len = 0;
|
|
|
|
if ((retval = ZSendNotice(¬ice,ZNOAUTH)) != ZERR_NONE)
|
|
com_err(whoami, retval, "while sending notice");
|
|
}
|
|
|
|
void
|
|
show_var(int argc,
|
|
char *argv[])
|
|
{
|
|
int i;
|
|
char *value;
|
|
|
|
if (argc < 2) {
|
|
fprintf(stderr,"Usage: %s <varname> <varname> ...\n",argv[0]);
|
|
return;
|
|
}
|
|
|
|
for (i=1;i<argc;i++) {
|
|
value = ZGetVariable(argv[i]);
|
|
if (value)
|
|
printf("%s: %s\n",argv[i],value);
|
|
else
|
|
printf("%s: not defined\n",argv[i]);
|
|
}
|
|
}
|
|
|
|
void
|
|
set_var(int argc, char *argv[])
|
|
{
|
|
int retval,setting_exp,i;
|
|
char *exp_level = NULL;
|
|
char *newargv[1];
|
|
char varcat[BUFSIZ];
|
|
|
|
if (argc < 2) {
|
|
fprintf(stderr,"Usage: %s <varname> [value]\n",
|
|
argv[0]);
|
|
return;
|
|
}
|
|
|
|
setting_exp = 0;
|
|
|
|
if (!strcasecmp(argv[1],"exposure")) {
|
|
setting_exp = 1;
|
|
if (argc != 3) {
|
|
fprintf(stderr,"An exposure setting must be specified.\n");
|
|
return;
|
|
}
|
|
exp_level = (char *)0;
|
|
if (!strcasecmp(argv[2],EXPOSE_NONE))
|
|
exp_level = EXPOSE_NONE;
|
|
if (!strcasecmp(argv[2],EXPOSE_OPSTAFF))
|
|
exp_level = EXPOSE_OPSTAFF;
|
|
if (!strcasecmp(argv[2],EXPOSE_REALMVIS))
|
|
exp_level = EXPOSE_REALMVIS;
|
|
if (!strcasecmp(argv[2],EXPOSE_REALMANN))
|
|
exp_level = EXPOSE_REALMANN;
|
|
if (!strcasecmp(argv[2],EXPOSE_NETVIS))
|
|
exp_level = EXPOSE_NETVIS;
|
|
if (!strcasecmp(argv[2],EXPOSE_NETANN))
|
|
exp_level = EXPOSE_NETANN;
|
|
if (!exp_level) {
|
|
fprintf(stderr,"The exposure setting must be one of:\n");
|
|
fprintf(stderr,"%s, %s, %s, %s, %s, %s.\n",
|
|
EXPOSE_NONE,
|
|
EXPOSE_OPSTAFF,
|
|
EXPOSE_REALMVIS,
|
|
EXPOSE_REALMANN,
|
|
EXPOSE_NETVIS,
|
|
EXPOSE_NETANN);
|
|
return;
|
|
}
|
|
}
|
|
if (argc == 2)
|
|
retval = ZSetVariable(argv[1],"");
|
|
else {
|
|
(void) strcpy(varcat,argv[2]);
|
|
for (i=3;i<argc;i++) {
|
|
(void) strcat(varcat," ");
|
|
(void) strcat(varcat,argv[i]);
|
|
}
|
|
retval = ZSetVariable(argv[1],varcat);
|
|
}
|
|
|
|
if (retval != ZERR_NONE) {
|
|
com_err(whoami, retval, "while setting variable value");
|
|
return;
|
|
}
|
|
|
|
/* Side-effects? Naw, us? */
|
|
|
|
if (setting_exp) {
|
|
if ((retval = ZSetLocation(exp_level)) != ZERR_NONE)
|
|
com_err(whoami, retval, "while changing exposure status");
|
|
if (!strcmp(exp_level,EXPOSE_NONE)) {
|
|
newargv[0] = "wg_shutdown";
|
|
wgc_control(1,newargv);
|
|
} else {
|
|
newargv[0] = "wg_startup";
|
|
wgc_control(1,newargv);
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
|
|
void
|
|
do_hide(int argc,
|
|
char *argv[])
|
|
{
|
|
char *exp_level = NULL;
|
|
Code_t retval;
|
|
|
|
if (argc != 1) {
|
|
fprintf(stderr, "Usage: %s\n",argv[0]);
|
|
return;
|
|
}
|
|
if (!strcmp(argv[0],"unhide"))
|
|
exp_level = EXPOSE_REALMVIS;
|
|
else
|
|
exp_level = EXPOSE_OPSTAFF;
|
|
if ((retval = ZSetLocation(exp_level)) != ZERR_NONE)
|
|
com_err(whoami,retval,"while changing exposure status");
|
|
return;
|
|
}
|
|
|
|
void
|
|
unset_var(int argc,
|
|
char *argv[])
|
|
{
|
|
int retval,i;
|
|
|
|
if (argc < 2) {
|
|
fprintf(stderr,"Usage: %s <varname> [<varname> ... ]\n",
|
|
argv[0]);
|
|
return;
|
|
}
|
|
|
|
for (i=1;i<argc;i++)
|
|
if ((retval = ZUnsetVariable(argv[i])) != ZERR_NONE)
|
|
com_err(whoami, retval,
|
|
"while unsetting variable value");
|
|
}
|
|
|
|
void
|
|
cancel_subs(int argc,
|
|
char *argv[])
|
|
{
|
|
int retval;
|
|
short wgport;
|
|
|
|
if (argc != 1) {
|
|
fprintf(stderr,"Usage: %s\n",argv[0]);
|
|
return;
|
|
}
|
|
|
|
if ((wgport = ZGetWGPort()) == -1) {
|
|
com_err(whoami, errno, "while finding WindowGram port");
|
|
return;
|
|
}
|
|
if ((retval = ZCancelSubscriptions((u_short)wgport)) != ZERR_NONE)
|
|
com_err(whoami, retval, "while cancelling subscriptions");
|
|
}
|
|
|
|
void
|
|
subscribe(int argc,
|
|
char *argv[])
|
|
{
|
|
int retval;
|
|
short wgport;
|
|
ZSubscription_t sub,sub2;
|
|
|
|
if (argc > 4 || argc < 3) {
|
|
fprintf(stderr,"Usage: %s class instance [*]\n",argv[0]);
|
|
return;
|
|
}
|
|
|
|
sub.zsub_class = argv[1];
|
|
sub.zsub_classinst = argv[2];
|
|
sub.zsub_recipient = (argc == 3)?ZGetSender():argv[3];
|
|
|
|
fix_macros(&sub,&sub2,1);
|
|
|
|
if ((wgport = ZGetWGPort()) == -1) {
|
|
com_err(whoami, errno, "while finding WindowGram port");
|
|
return;
|
|
}
|
|
|
|
retval = (*argv[0] == 's') ?
|
|
ZSubscribeToSansDefaults(&sub2,1,(u_short)wgport) :
|
|
ZUnsubscribeTo(&sub2,1,(u_short)wgport);
|
|
|
|
if (retval != ZERR_NONE)
|
|
com_err(whoami, retval, "while subscribing");
|
|
}
|
|
|
|
void
|
|
sub_file(int argc,
|
|
char *argv[])
|
|
{
|
|
ZSubscription_t sub;
|
|
short wgport;
|
|
|
|
if (argc > 4 || argc < 3) {
|
|
fprintf(stderr,"Usage: %s class instance [*]\n",argv[0]);
|
|
return;
|
|
}
|
|
|
|
if (argv[1][0] == '!') {
|
|
com_err(whoami, 0,
|
|
(!strcmp(argv[0],"add_unsubscription") ||
|
|
!strcmp(argv[0],"add_un") ||
|
|
!strcmp(argv[0],"delete_unsubscription") ||
|
|
!strcmp(argv[0],"del_un")) ?
|
|
"Do not use `!' as the first character of a class.\n\tIt is automatically added before modifying the subscription file." :
|
|
"Do not use `!' as the first character of a class.\n\tIt is reserved for internal use with un-subscriptions.");
|
|
return;
|
|
}
|
|
sub.zsub_class = argv[1];
|
|
sub.zsub_classinst = argv[2];
|
|
sub.zsub_recipient = (argc == 3)?TOKEN_ME:argv[3];
|
|
|
|
if (make_exist(subsname))
|
|
return;
|
|
if ((wgport = ZGetWGPort()) == -1) {
|
|
com_err(whoami, errno, "while finding WindowGram port");
|
|
return;
|
|
}
|
|
|
|
if (!strcmp(argv[0],"add"))
|
|
add_file(wgport,&sub,0);
|
|
else if (!strcmp(argv[0],"add_unsubscription") ||
|
|
!strcmp(argv[0],"add_un"))
|
|
add_file(wgport,&sub,1);
|
|
else if (!strcmp(argv[0],"delete") ||
|
|
!strcmp(argv[0],"del") ||
|
|
!strcmp(argv[0],"dl"))
|
|
del_file(wgport,&sub,0);
|
|
else if (!strcmp(argv[0],"delete_unsubscription") ||
|
|
!strcmp(argv[0],"del_un")) {
|
|
del_file(wgport,&sub,1);
|
|
} else
|
|
com_err(whoami, 0, "unknown command name");
|
|
return;
|
|
}
|
|
|
|
void
|
|
add_file(short wgport,
|
|
ZSubscription_t *subs,
|
|
int unsub)
|
|
{
|
|
FILE *fp;
|
|
ZSubscription_t sub2;
|
|
Code_t retval;
|
|
|
|
(void) purge_subs(subs,ALL); /* remove copies in the subs file */
|
|
if (!(fp = fopen(subsname,"a"))) {
|
|
com_err(whoami, errno, "while opening %s for append", subsname);
|
|
return;
|
|
}
|
|
fprintf(fp,"%s%s,%s,%s\n",
|
|
unsub ? "!" : "",
|
|
subs->zsub_class, subs->zsub_classinst, subs->zsub_recipient);
|
|
if (fclose(fp) == EOF) {
|
|
com_err(whoami, errno, "while closing %s", subsname);
|
|
return;
|
|
}
|
|
fix_macros(subs,&sub2,1);
|
|
retval = (unsub
|
|
? ZUnsubscribeTo(&sub2,1,(u_short)wgport)
|
|
: ZSubscribeToSansDefaults(&sub2,1,(u_short)wgport));
|
|
if (retval)
|
|
com_err(whoami, retval,
|
|
unsub ? "while unsubscribing" :
|
|
"while subscribing");
|
|
return;
|
|
}
|
|
|
|
void
|
|
del_file(short wgport,
|
|
register ZSubscription_t *subs,
|
|
int unsub)
|
|
{
|
|
ZSubscription_t sub2;
|
|
int retval;
|
|
|
|
retval = purge_subs(subs, unsub ? UNSUBONLY : SUBONLY);
|
|
if (retval == ERR)
|
|
return;
|
|
if (retval == NOT_REMOVED)
|
|
fprintf(stderr,
|
|
"Couldn't find %sclass %s instance %s recipient %s in\n\tfile %s\n",
|
|
unsub ? "un-subscription " : "",
|
|
subs->zsub_class, subs->zsub_classinst,
|
|
subs->zsub_recipient, subsname);
|
|
fix_macros(subs,&sub2,1);
|
|
if ((retval = ZUnsubscribeTo(&sub2,1,(u_short)wgport)) !=
|
|
ZERR_NONE)
|
|
com_err(whoami, retval, "while unsubscribing");
|
|
return;
|
|
}
|
|
|
|
int
|
|
purge_subs(register ZSubscription_t *subs,
|
|
int which)
|
|
{
|
|
FILE *fp,*fpout;
|
|
char subline[BUFSIZ];
|
|
char backup[BUFSIZ],ourline[BUFSIZ];
|
|
int delflag = NOT_REMOVED;
|
|
int keep = 0;
|
|
|
|
switch (which) {
|
|
case SUBONLY:
|
|
case UNSUBONLY:
|
|
case ALL:
|
|
break;
|
|
default:
|
|
com_err(whoami, 0, "internal error in purge_subs");
|
|
return(ERR);
|
|
}
|
|
|
|
(void) sprintf(ourline,"%s,%s,%s",
|
|
subs->zsub_class,
|
|
subs->zsub_classinst,
|
|
subs->zsub_recipient);
|
|
|
|
if (!(fp = fopen(subsname,"r"))) {
|
|
com_err(whoami, errno, "while opening %s for read", subsname);
|
|
return(ERR);
|
|
}
|
|
(void) strcpy(backup, subsname);
|
|
(void) strcat(backup, ".temp");
|
|
(void) unlink(backup);
|
|
if (!(fpout = fopen(backup,"w"))) {
|
|
com_err(whoami, errno, "while opening %s for writing", backup);
|
|
(void) fclose(fp);
|
|
return(ERR);
|
|
}
|
|
for (;;) {
|
|
if (!fgets(subline,sizeof subline,fp))
|
|
break;
|
|
if (*subline)
|
|
subline[strlen(subline)-1] = '\0'; /* nuke newline */
|
|
switch (which) {
|
|
case SUBONLY:
|
|
keep = strcmp(subline,ourline);
|
|
break;
|
|
case UNSUBONLY:
|
|
keep = (*subline != '!' || strcmp(subline+1,ourline));
|
|
break;
|
|
case ALL:
|
|
keep = (strcmp(subline,ourline) &&
|
|
(*subline != '!' || strcmp(subline+1,
|
|
ourline)));
|
|
break;
|
|
}
|
|
if (keep) {
|
|
fputs(subline, fpout);
|
|
if (ferror(fpout) || (fputc('\n', fpout) == EOF)) {
|
|
com_err(whoami, errno, "while writing to %s",
|
|
backup);
|
|
}
|
|
} else
|
|
delflag = REMOVED;
|
|
}
|
|
(void) fclose(fp); /* open read-only, ignore errs */
|
|
if (fclose(fpout) == EOF) {
|
|
com_err(whoami, errno, "while closing %s", backup);
|
|
return(ERR);
|
|
}
|
|
if (rename(backup,subsname) == -1) {
|
|
com_err(whoami, errno, "while renaming %s to %s\n",
|
|
backup, subsname);
|
|
return(ERR);
|
|
}
|
|
return(delflag);
|
|
}
|
|
|
|
void
|
|
load_subs(int argc,
|
|
char *argv[])
|
|
{
|
|
ZSubscription_t subs[SUBSATONCE],subs2[SUBSATONCE],unsubs[SUBSATONCE];
|
|
#ifdef CMU_ZCTL_PUNT
|
|
ZSubscription_t punts[SUBSATONCE];
|
|
int pind;
|
|
#endif
|
|
FILE *fp;
|
|
int ind,unind,lineno,i,retval,type;
|
|
short wgport = 0;
|
|
char *comma,*comma2,*file,subline[BUFSIZ];
|
|
|
|
if (argc > 2) {
|
|
fprintf(stderr,"Usage: %s [file]\n",argv[0]);
|
|
return;
|
|
}
|
|
|
|
if (*argv[0] == 'u')
|
|
type = UNSUB;
|
|
else
|
|
if (!strcmp(argv[0],"list") || !strcmp(argv[0],"ls"))
|
|
type = LIST;
|
|
else
|
|
type = SUB;
|
|
|
|
if (type != LIST)
|
|
if ((wgport = ZGetWGPort()) == -1) {
|
|
com_err(whoami, errno,
|
|
"while finding WindowGram port");
|
|
return;
|
|
}
|
|
|
|
file = (argc == 1) ? subsname : argv[1];
|
|
|
|
fp = fopen(file,"r");
|
|
|
|
if (fp == NULL) {
|
|
com_err(whoami, errno,
|
|
"while loading subscription file");
|
|
return;
|
|
}
|
|
|
|
#ifdef CMU_ZCTL_PUNT
|
|
pind =
|
|
#endif
|
|
ind = unind = 0;
|
|
lineno = 1;
|
|
|
|
for (;;lineno++) {
|
|
if (!fgets(subline,sizeof subline,fp))
|
|
break;
|
|
if (*subline == '#' || !*subline)
|
|
continue;
|
|
subline[strlen(subline)-1] = '\0'; /* nuke newline */
|
|
comma = strchr(subline,',');
|
|
if (comma)
|
|
comma2 = strchr(comma+1,',');
|
|
else
|
|
comma2 = 0;
|
|
if (!comma || !comma2) {
|
|
fprintf(stderr,
|
|
"Malformed subscription at line %d of %s:\n%s\n",
|
|
lineno,file,subline);
|
|
continue;
|
|
}
|
|
*comma = '\0';
|
|
*comma2 = '\0';
|
|
if (type == LIST) {
|
|
if (*subline == '!')
|
|
printf("(Un-subscription) Class %s instance %s recipient %s\n",
|
|
subline+1, comma+1, comma2+1);
|
|
#ifdef CMU_ZCTL_PUNT
|
|
else if(*subline == '-')
|
|
printf("(Punted) Class %s instance %s recipient %s\n",
|
|
subline+1, comma+1, comma2+1);
|
|
#endif
|
|
else
|
|
printf("Class %s instance %s recipient %s\n",
|
|
subline, comma+1, comma2+1);
|
|
continue;
|
|
}
|
|
if (*subline == '!') { /* an un-subscription */
|
|
/* if we are explicitly un-subscribing to
|
|
the contents of a subscription file, ignore
|
|
any un-subscriptions in that file */
|
|
if (type == UNSUB)
|
|
continue;
|
|
unsubs[unind].zsub_class =
|
|
(char *)malloc((unsigned)(strlen(subline)));
|
|
/* XXX check malloc return */
|
|
/* skip the leading '!' */
|
|
(void) strcpy(unsubs[unind].zsub_class,subline+1);
|
|
unsubs[unind].zsub_classinst =
|
|
(char *)malloc((unsigned)(strlen(comma+1)+1));
|
|
/* XXX check malloc return */
|
|
(void) strcpy(unsubs[unind].zsub_classinst,comma+1);
|
|
unsubs[unind].zsub_recipient =
|
|
(char *)malloc((unsigned)(strlen(comma2+1)+1));
|
|
/* XXX check malloc return */
|
|
(void) strcpy(unsubs[unind].zsub_recipient,comma2+1);
|
|
unind++;
|
|
} else
|
|
#ifdef CMU_ZCTL_PUNT
|
|
if (*subline == '-') { /* a punt */
|
|
if (type == UNSUB)
|
|
continue;
|
|
punts[pind].zsub_class =
|
|
(char *)malloc((unsigned)(strlen(subline)+1));
|
|
/* XXX check malloc return */
|
|
(void) strcpy(punts[pind].zsub_class,subline+1);
|
|
punts[pind].zsub_classinst =
|
|
(char *)malloc((unsigned)(strlen(comma+1)+1));
|
|
/* XXX check malloc return */
|
|
(void) strcpy(punts[pind].zsub_classinst,comma+1);
|
|
punts[pind].zsub_recipient =
|
|
(char *)malloc((unsigned)(strlen(comma2+1)+1));
|
|
/* XXX check malloc return */
|
|
(void) strcpy(punts[pind].zsub_recipient,comma2+1);
|
|
pind++;
|
|
} else
|
|
#endif
|
|
{
|
|
subs[ind].zsub_class =
|
|
(char *)malloc((unsigned)(strlen(subline)+1));
|
|
/* XXX check malloc return */
|
|
(void) strcpy(subs[ind].zsub_class,subline);
|
|
subs[ind].zsub_classinst =
|
|
(char *)malloc((unsigned)(strlen(comma+1)+1));
|
|
/* XXX check malloc return */
|
|
(void) strcpy(subs[ind].zsub_classinst,comma+1);
|
|
subs[ind].zsub_recipient =
|
|
(char *)malloc((unsigned)(strlen(comma2+1)+1));
|
|
/* XXX check malloc return */
|
|
(void) strcpy(subs[ind].zsub_recipient,comma2+1);
|
|
ind++;
|
|
}
|
|
#ifdef CMU_ZCTL_PUNT
|
|
if (pind == SUBSATONCE) {
|
|
fix_macros(punts,subs2,pind);
|
|
if ((retval = ZPunt(subs2,pind,(u_short)wgport) !=
|
|
ZERR_NONE))
|
|
{
|
|
com_err(whoami, retval,
|
|
"while punting");
|
|
goto cleanup;
|
|
}
|
|
for (i=0;i<pind;i++) {
|
|
free(punts[i].zsub_class);
|
|
free(punts[i].zsub_classinst);
|
|
free(punts[i].zsub_recipient);
|
|
}
|
|
pind = 0;
|
|
}
|
|
#endif
|
|
if (ind == SUBSATONCE) {
|
|
fix_macros(subs,subs2,ind);
|
|
if ((retval = (type == SUB)?
|
|
ZSubscribeTo(subs2,ind,(u_short)wgport):
|
|
ZUnsubscribeTo(subs2,ind,(u_short)wgport)) !=
|
|
ZERR_NONE) {
|
|
com_err(whoami, retval, (type == SUB) ?
|
|
"while subscribing":
|
|
"while unsubscribing");
|
|
goto cleanup;
|
|
}
|
|
for (i=0;i<ind;i++) {
|
|
free(subs[i].zsub_class);
|
|
free(subs[i].zsub_classinst);
|
|
free(subs[i].zsub_recipient);
|
|
}
|
|
ind = 0;
|
|
}
|
|
if (unind == SUBSATONCE) {
|
|
fix_macros(unsubs,subs2,unind);
|
|
if ((retval = ZUnsubscribeTo(subs2,unind,(u_short)wgport)) != ZERR_NONE) {
|
|
com_err(whoami, retval,
|
|
"while unsubscribing to un-subscriptions");
|
|
goto cleanup;
|
|
}
|
|
for (i=0;i<unind;i++) {
|
|
free(unsubs[i].zsub_class);
|
|
free(unsubs[i].zsub_classinst);
|
|
free(unsubs[i].zsub_recipient);
|
|
}
|
|
unind = 0;
|
|
}
|
|
}
|
|
|
|
if (type != LIST) {
|
|
/* even if we have no subscriptions, be sure to send
|
|
an empty packet to trigger the default subscriptions */
|
|
fix_macros(subs,subs2,ind);
|
|
if ((retval = (type == SUB)?ZSubscribeTo(subs2,ind,(u_short)wgport):
|
|
ZUnsubscribeTo(subs2,ind,(u_short)wgport)) != ZERR_NONE) {
|
|
com_err(whoami, retval, (type == SUB) ?
|
|
"while subscribing":
|
|
"while unsubscribing");
|
|
goto cleanup;
|
|
}
|
|
if (unind) {
|
|
fix_macros(unsubs,subs2,unind);
|
|
if ((retval =
|
|
ZUnsubscribeTo(subs2,unind,(u_short)wgport)) != ZERR_NONE) {
|
|
com_err(whoami, retval,
|
|
"while unsubscribing to un-subscriptions");
|
|
goto cleanup;
|
|
}
|
|
}
|
|
#ifdef CMU_ZCTL_PUNT
|
|
if (pind) {
|
|
fix_macros(punts,subs2,pind);
|
|
if ((retval = ZPunt(subs2,pind,(u_short)wgport) !=
|
|
ZERR_NONE))
|
|
{
|
|
com_err(whoami,retval,
|
|
"while punting");
|
|
goto cleanup;
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
cleanup:
|
|
for (i=0;i<ind;i++) {
|
|
free(subs[i].zsub_class);
|
|
free(subs[i].zsub_classinst);
|
|
free(subs[i].zsub_recipient);
|
|
}
|
|
for (i=0;i<unind;i++) {
|
|
free(unsubs[i].zsub_class);
|
|
free(unsubs[i].zsub_classinst);
|
|
free(unsubs[i].zsub_recipient);
|
|
}
|
|
#ifdef CMU_ZCTL_PUNT
|
|
for (i=0;i<pind;i++) {
|
|
free(punts[i].zsub_class);
|
|
free(punts[i].zsub_classinst);
|
|
free(punts[i].zsub_recipient);
|
|
}
|
|
#endif
|
|
|
|
(void) fclose(fp); /* ignore errs--file is read-only */
|
|
return;
|
|
}
|
|
|
|
void
|
|
current(int argc,
|
|
char *argv[])
|
|
{
|
|
FILE *fp = NULL;
|
|
ZSubscription_t subs;
|
|
int i,nsubs,retval,save,one,defs;
|
|
short wgport;
|
|
char backup[BUFSIZ];
|
|
char *file = NULL;
|
|
|
|
save = 0;
|
|
defs = 0;
|
|
|
|
if (!strcmp(argv[0],"save"))
|
|
save = 1;
|
|
else if (!strcmp(argv[0], "defaults") || !strcmp(argv[0], "defs"))
|
|
defs = 1;
|
|
|
|
if (argc != 1 && !(save && argc == 2)) {
|
|
fprintf(stderr,"Usage: %s%s\n",argv[0],save?" [filename]":"");
|
|
return;
|
|
}
|
|
|
|
if (!defs)
|
|
if ((wgport = ZGetWGPort()) == -1) {
|
|
com_err(whoami, errno,
|
|
"while finding WindowGram port");
|
|
return;
|
|
}
|
|
|
|
if (defs)
|
|
retval = ZRetrieveDefaultSubscriptions(&nsubs);
|
|
else
|
|
retval = ZRetrieveSubscriptions((u_short)wgport,&nsubs);
|
|
|
|
if (retval == ZERR_TOOMANYSUBS) {
|
|
fprintf(stderr,"Too many subscriptions -- some have not been returned.\n");
|
|
if (save) {
|
|
fprintf(stderr,"Save aborted.\n");
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
if (retval != ZERR_NONE) {
|
|
com_err(whoami, retval, "retrieving subscriptions");
|
|
return;
|
|
}
|
|
|
|
if (save) {
|
|
file = (argc == 1)?subsname:argv[1];
|
|
(void) strcpy(backup,file);
|
|
(void) strcat(backup,".temp");
|
|
if (!(fp = fopen(backup,"w"))) {
|
|
com_err(whoami, errno, "while opening %s for write",
|
|
backup);
|
|
return;
|
|
}
|
|
}
|
|
|
|
for (i=0;i<nsubs;i++) {
|
|
one = 1;
|
|
if ((retval = ZGetSubscriptions(&subs,&one)) != ZERR_NONE) {
|
|
com_err(whoami, retval, "while getting subscription");
|
|
if (save) {
|
|
fprintf(stderr,"Subscriptions file not modified\n");
|
|
(void) fclose(fp);
|
|
(void) unlink(backup);
|
|
}
|
|
return;
|
|
}
|
|
if (save)
|
|
fprintf(fp,"%s,%s,%s\n",subs.zsub_class,
|
|
subs.zsub_classinst, subs.zsub_recipient);
|
|
else
|
|
printf("Class %s Instance %s Recipient %s\n",
|
|
subs.zsub_class, subs.zsub_classinst,
|
|
subs.zsub_recipient);
|
|
}
|
|
|
|
if (save) {
|
|
if (fclose(fp) == EOF) {
|
|
com_err(whoami, errno, "while closing %s", backup);
|
|
return;
|
|
}
|
|
if (rename(backup,file) == -1) {
|
|
com_err(whoami, retval, "while renaming %s to %s",
|
|
backup, file);
|
|
(void) unlink(backup);
|
|
}
|
|
}
|
|
}
|
|
|
|
int
|
|
make_exist(char *filename)
|
|
{
|
|
FILE *fpout;
|
|
|
|
if (!access(filename,F_OK))
|
|
return (0);
|
|
|
|
if (!(fpout = fopen(filename,"w"))) {
|
|
com_err(whoami, errno,"while opening %s for write", filename);
|
|
return (1);
|
|
}
|
|
|
|
if (fclose(fpout) == EOF) {
|
|
com_err(whoami, errno, "while closing %s", filename);
|
|
return(1);
|
|
}
|
|
return (0);
|
|
}
|
|
|
|
void
|
|
fix_macros(ZSubscription_t *subs,
|
|
ZSubscription_t *subs2,
|
|
int num)
|
|
{
|
|
int i;
|
|
|
|
for (i=0;i<num;i++) {
|
|
subs2[i] = subs[i];
|
|
fix_macros2(subs[i].zsub_class,&subs2[i].zsub_class);
|
|
fix_macros2(subs[i].zsub_classinst,&subs2[i].zsub_classinst);
|
|
fix_macros2(subs[i].zsub_recipient,&subs2[i].zsub_recipient);
|
|
}
|
|
}
|
|
|
|
void
|
|
fix_macros2(char *src, char **dest)
|
|
{
|
|
if (!strcmp(src,TOKEN_HOSTNAME)) {
|
|
*dest = ourhost;
|
|
return;
|
|
}
|
|
if (!strcmp(src,TOKEN_CANONNAME)) {
|
|
*dest = ourhostcanon;
|
|
return;
|
|
}
|
|
if (!strcmp(src,TOKEN_ME))
|
|
*dest = ZGetSender();
|
|
}
|
|
|
|
void
|
|
do_punt(int argc, char *argv[])
|
|
{
|
|
#ifdef CMU_ZCTL_PUNT
|
|
char *class, *inst, *recip, *msg, *cmd = argv[0];
|
|
int retval, punt;
|
|
short newport;
|
|
struct sockaddr_in newsin;
|
|
ZNotice_t notice;
|
|
|
|
if (! strcmp(cmd, "punt")) punt = 1;
|
|
else punt = 0;
|
|
|
|
switch (argc) {
|
|
case 2:
|
|
class = "message";
|
|
inst = argv[1];
|
|
recip = "";
|
|
break;
|
|
case 3:
|
|
class = argv[1];
|
|
inst = argv[2];
|
|
recip = "";
|
|
break;
|
|
case 4:
|
|
class = argv[1];
|
|
inst = argv[2];
|
|
recip = argv[3];
|
|
if (*argv[3] == '*') /* fixed so realm punts would work (vs0r) */
|
|
if (*(argv[3]+1) == '@')
|
|
if (!strcmp((char *)ZGetRealm(), (char *)ZExpandRealm(argv[3]+2)))
|
|
/*check local*/
|
|
recip = "";
|
|
break;
|
|
default:
|
|
fprintf(stderr, "Usages:\n");
|
|
fprintf(stderr, "\t%s instance\n", cmd);
|
|
fprintf(stderr, "\t%s class instance\n", cmd);
|
|
fprintf(stderr, "\t%s class instance recipient\n", cmd);
|
|
return;
|
|
}
|
|
|
|
retval = ZOpenPort((u_short *) 0);
|
|
if(retval != ZERR_NONE) {
|
|
com_err(whoami, retval, "while opening Zephyr port.");
|
|
return;
|
|
}
|
|
|
|
newsin = ZGetDestAddr();
|
|
if ((newport = ZGetWGPort()) == -1) {
|
|
fprintf(stderr, "%s: Can't find windowgram port\n", whoami);
|
|
return;
|
|
}
|
|
|
|
newsin.sin_port = (unsigned short) newport;
|
|
if ((retval = ZSetDestAddr(&newsin)) != ZERR_NONE) {
|
|
com_err(whoami,retval,"while setting destination address");
|
|
return;
|
|
}
|
|
|
|
msg = (char *) malloc(strlen(class) + strlen(inst) + strlen(recip) + 4);
|
|
sprintf(msg, "%s%c%s%c%s", class, '\0', inst, '\0', recip);
|
|
|
|
if (*recip == '*')
|
|
if (*(recip+1) == '@')
|
|
if (strcmp(recip+2, (char *)ZExpandRealm(recip+2)))
|
|
sprintf(msg, "%s%c%s%c%s", class, '\0', inst, '\0',
|
|
(char *)ZExpandRealm(recip+2));
|
|
printf("%s <%s,%s,%s>\n", punt ? "Punting" : "Unpunting",
|
|
class, inst, *recip ? recip : "*");
|
|
|
|
memset((char *) ¬ice, 0, sizeof(ZNotice_t));
|
|
notice.z_kind = UNSAFE;
|
|
notice.z_class = WG_CTL_CLASS;
|
|
notice.z_class_inst = WG_CTL_USER;
|
|
notice.z_recipient = "";
|
|
notice.z_default_format = "";
|
|
notice.z_opcode = (punt) ? "SUPPRESS" : "UNSUPPRESS";
|
|
notice.z_port = 0;
|
|
notice.z_message = msg;
|
|
notice.z_message_len = strlen(class)+strlen(inst)+strlen(recip)+3;
|
|
|
|
if ((retval = ZSendNotice(¬ice,ZNOAUTH)) != ZERR_NONE)
|
|
fprintf(stderr,"%s: while sending notice\n",whoami);
|
|
|
|
free(msg);
|
|
|
|
ZClosePort();
|
|
#endif
|
|
return;
|
|
}
|
|
|
|
void
|
|
list_punts(int argc, char *argv[])
|
|
{
|
|
#ifdef CMU_ZCTL_PUNT
|
|
ZNotice_t notice;
|
|
int retval;
|
|
struct sockaddr_in old, to, from;
|
|
u_short ourport, zwgcport;
|
|
char *msg;
|
|
|
|
ourport=0;
|
|
retval = ZOpenPort(&ourport);
|
|
if(retval != ZERR_NONE) {
|
|
com_err("zctl", retval, "while opening Zephyr port.");
|
|
return;
|
|
}
|
|
|
|
old = ZGetDestAddr();
|
|
to = old;
|
|
if ((zwgcport = ZGetWGPort()) == (u_short)-1) {
|
|
fprintf(stderr, "zctl: Can't find windowgram port\n");
|
|
return;
|
|
}
|
|
|
|
to.sin_port = (u_short) zwgcport;
|
|
if ((retval = ZSetDestAddr(&to)) != ZERR_NONE) {
|
|
com_err("zctl",retval,"while setting destination address");
|
|
return;
|
|
}
|
|
|
|
memset((char *) ¬ice, 0, sizeof(ZNotice_t));
|
|
notice.z_kind = UNSAFE;
|
|
notice.z_class = WG_CTL_CLASS;
|
|
notice.z_class_inst = WG_CTL_USER;
|
|
notice.z_recipient = "";
|
|
notice.z_default_format = "";
|
|
notice.z_opcode = "LIST-SUPPRESSED" /*USER_LIST_SUPPRESSED*/;
|
|
notice.z_port = ourport;
|
|
notice.z_message = NULL;
|
|
notice.z_message_len = 0;
|
|
|
|
if ((retval = ZSendNotice(¬ice,ZNOAUTH)) != ZERR_NONE)
|
|
com_err("zctl",retval,"while sending notice");
|
|
|
|
if ((retval = ZReceiveNotice(¬ice,&from)) != ZERR_NONE)
|
|
com_err("zctl",retval,"while receiving ack");
|
|
|
|
(void) ZFreeNotice(¬ice);
|
|
|
|
if ((retval = ZReceiveNotice(¬ice,&from)) != ZERR_NONE)
|
|
com_err("zctl",retval,"while receiving notice");
|
|
|
|
notice.z_auth = ZCheckAuthentication(¬ice, &from);
|
|
|
|
if ((retval = ZSetDestAddr(&old)) != ZERR_NONE) {
|
|
com_err("zctl",retval,"while resetting destination address");
|
|
return;
|
|
}
|
|
|
|
msg = (char *) malloc((notice.z_message_len+1) * sizeof(char));
|
|
(void) strncpy(msg,notice.z_message, notice.z_message_len);
|
|
msg[notice.z_message_len]=(char)0;
|
|
printf("%s", msg);
|
|
(void) free(msg);
|
|
(void) ZFreeNotice(¬ice);
|
|
(void) ZClosePort();
|
|
|
|
#endif /* CMU_ZCTL_PUNT */
|
|
return;
|
|
}
|
|
|
|
#ifndef HAVE_SS
|
|
#define MAXNAMES 3
|
|
static const struct {
|
|
void (*fptr)(int, char *[]);
|
|
const char *doc;
|
|
const char *names[MAXNAMES];
|
|
} commands[] = {
|
|
/* { set_file, "Set default subscriptions file.", "file" }, */
|
|
{ cancel_subs, "Cancel all subscriptions.",
|
|
{ "cancel" } },
|
|
{ load_subs, "Subscribe to a subscriptions file.",
|
|
{ "load", "ld" } },
|
|
{ load_subs, "Unsubscribe to a subscriptions file.",
|
|
{ "unload", "unld" } },
|
|
{ load_subs, "List a subscriptions file.",
|
|
{ "list", "ls" } },
|
|
{ subscribe, "Subscribe to a class/class instance.",
|
|
{ "subscribe", "sub" } },
|
|
{ subscribe, "Unsubscribe to a class/class instance.",
|
|
{ "unsubscribe", "unsub" } },
|
|
{ sub_file, "Subscribe and add to subscriptions file.",
|
|
{ "add" } },
|
|
{ sub_file, "Unsubscribe and add to subscriptions file\nas un-subscription.",
|
|
{ "add_unsubscription", "add_un" } },
|
|
{ sub_file, "Unsubscribe and delete subscription from\nsubscriptions file.",
|
|
{ "delete", "del", "dl" } },
|
|
{ sub_file, "Delete un-subscription from subscriptions file.",
|
|
{ "delete_unsubscription", "del_un" } },
|
|
{ current, "Retrieve current subscriptions.",
|
|
{ "retrieve", "ret" } },
|
|
{ current, "Retrieve system-wide default subscriptions.",
|
|
{ "defaults", "defs" } },
|
|
{ current, "Save current subscriptions (replacing existing file).",
|
|
{ "save" } },
|
|
{ show_var, "Show a variable's value.",
|
|
{ "show" } },
|
|
{ set_var, "Set a variable's value.",
|
|
{ "set" } },
|
|
{ unset_var, "Delete a variable's value.",
|
|
{ "unset" } },
|
|
{ wgc_control, "Get the WindowGram to reread its description file.",
|
|
{ "wg_read" } },
|
|
{ wgc_control, "Tell the WindowGram not to react to incoming notices.",
|
|
{ "wg_shutdown" } },
|
|
{ wgc_control, "Tell the WindowGram to react to incoming notices.",
|
|
{ "wg_startup" } },
|
|
{ wgc_control, "Tell the WindowGram to exit completely.",
|
|
{ "wg_exit" } },
|
|
{ hm_control, "Tell the server to flush information about this host.",
|
|
{ "hm_flush" } },
|
|
{ hm_control, "Tell the HostManager to find a new server.",
|
|
{ "new_server" } },
|
|
{ flush_locations, "Flush all location information.",
|
|
{ "flush_locs" } },
|
|
{ flush_subscr, "Flush all subscription information.",
|
|
{ "flush_subs" } },
|
|
{ do_hide, "Hide your location.",
|
|
{ "hide" } },
|
|
{ do_hide, "Show (un-hide) your location.",
|
|
{ "unhide" } },
|
|
{ show_commands, "List available commands.",
|
|
{ "help", "?" } },
|
|
#ifdef CMU_ZCTL_PUNT
|
|
{ do_punt, "Ignore specified messages.",
|
|
{ "punt" } },
|
|
{ do_punt, "Stop ignoring specified messages.",
|
|
{ "unpunt" } },
|
|
{ list_punts, "List current messages to ignore.",
|
|
{ "list_punts", "lp" } },
|
|
#endif
|
|
};
|
|
#define MAXCOMMAND (sizeof(commands)/sizeof(commands[0]))
|
|
|
|
#define DOCCOL 25
|
|
|
|
static void
|
|
show_commands(int argc, char *argv[])
|
|
{
|
|
int i, j, col, len;
|
|
const char *str, *s;
|
|
printf("Available zctl requests:\n\n");
|
|
for (i = 0; i < MAXCOMMAND; i++) {
|
|
col = 0;
|
|
printf("%s", commands[i].names[0]);
|
|
col += strlen(commands[i].names[0]);
|
|
for (j = 1; j < MAXNAMES && commands[i].names[j]; j++) {
|
|
printf(", %s", commands[i].names[j]);
|
|
col += 2 + strlen(commands[i].names[j]);
|
|
}
|
|
if (col > DOCCOL - 2) {
|
|
printf("\n");
|
|
col = 0;
|
|
}
|
|
printf("%*s", DOCCOL - col, "");
|
|
str = commands[i].doc;
|
|
while ((s = strchr(str, '\n')) != NULL) {
|
|
printf("%.*s\n%*s", (int)(s-str), str, DOCCOL, "");
|
|
str = s+1;
|
|
}
|
|
printf("%s\n", str);
|
|
}
|
|
}
|
|
|
|
static void
|
|
run_command(int argc, char *argv[])
|
|
{
|
|
int i, j;
|
|
for (i = 0; i < MAXCOMMAND; i++)
|
|
for (j = 0; j < MAXNAMES; j++)
|
|
if (commands[i].names[j] != NULL &&
|
|
!strcmp(commands[i].names[j], argv[0])) {
|
|
commands[i].fptr(argc, argv);
|
|
return;
|
|
}
|
|
com_err(whoami, 0,
|
|
"Unknown command '%s'; use '%s help' for a list of commands.",
|
|
argv[0], whoami);
|
|
exit(1);
|
|
}
|
|
#endif
|