home *** CD-ROM | disk | FTP | other *** search
- /*
- * NIM daemon command parser
- *
- * Frank Pronk
- * Copyright (c) 1984
- */
-
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <sys/ioctl.h>
- #include <netccitt/x25.h>
- #include <netdb.h>
-
- #include "../h/x29.h"
-
- #include "nim.h"
-
- #define NEXTC (*sym.s_next ? *sym.s_next++ : (char)0)
-
- #define SSET 0200+0
- #define SPAR 0200+1
- #define SPROF 0200+2
- #define SSTATUS 0200+3
- #define SRESET 0200+4
- #define SINT 0200+5
- #define SINTD 0200+6
- #define SCLEAR 0200+7
- #define SHELP 0200+8
- #define SCALL 0200+9
- #define SPRI 0200+10
- #define SREV 0200+11
- #define SNUM 0200+12
- #define SSTR 0200+13
- #define SNUI 0200+14
-
- struct NIMCommand {
- char *c_name;
- short c_value;
- } Commands[] = {
- "set", SSET,
- "par", SPAR,
- "prof", SPROF,
- "profile", SPROF,
- "stat", SSTATUS,
- "status", SSTATUS,
- "reset", SRESET,
- "int", SINT,
- "intd", SINTD,
- "clear", SCLEAR,
- "help", SHELP,
- "call", SCALL,
- "p", SPRI,
- "rev", SREV,
- "nui", SNUI,
- 0, 0,
- };
-
- struct sockaddr_x25 RemoteHostAddr;
- char *RemoteHostName;
- char *Nui; /* network user identification */
-
- /*
- * Structure used by insymbol() keep track of its
- * current position in the command string being
- * parsed and to hold the results of the last
- * call to insymbol()
- */
-
- struct symbol {
- char *s_start; /* start of line to be parsed */
- char *s_next; /* current position in line */
- short s_type; /* see defines above */
- int s_num; /* value if current symbol is a number */
- char *s_str; /* address of symbol if a string */
- } sym;
-
- /*
- * List of symbolic names that can be
- * used as replacements for numeric codes
- * in specific "set parameter" requests
- */
-
- struct NameList {
- char *n_name;
- short n_value;
- } ForwardList[] = { "cr", 2, "control", 126, "off", 0, 0, 0 },
- OnOffList[] = { "on", 1, "off", 0, 0, 0},
- LfList[] = { "on", 4, "off", 0, "none", 0, "local", 4, "remote", 1, "both", 5, 0, 0};
-
- /*
- * list of x.29 symbolic keywords that can be substituted
- * for numeric codes. Note that this list contains only
- * the x.29 parameters that an average user would ever
- * want to change.
- */
-
- struct X29Keyword {
- char *x_word; /* parameter name */
- short x_param; /* parameter code */
- struct NameList *x_list;
- } X29Keywords[] = {
- "escape", X29_ESCAPE_TO_CMD_CODE, OnOffList,
- "echo", X29_ECHO_CODE, OnOffList,
- "forward", X29_FORWARDING_SIGNAL_CODE, ForwardList,
- "timer", X29_IDLE_TIMER_CODE, OnOffList,
- "break", X29_BREAK_PROCEDURE_CODE, 0,
- "lf", X29_LF_AFTER_CR, LfList,
- "lf-insertion", X29_LF_AFTER_CR, LfList,
- "editing", X29_EDITING, OnOffList,
- "erase", X29_CHARACTER_DELETE, 0,
- "kill", X29_LINE_DELETE, 0,
- "replay", X29_LINE_DISPLAY, 0,
- "display", X29_LINE_DISPLAY, 0,
- 0, 0, 0
- };
-
- /*
- * Attempt to parse string pointed to by 'cp'.
- */
-
- NimCommand(cp)
- register char *cp;
- {
-
- sym.s_start = sym.s_next = cp;
- /*
- * strip parity bit from command
- */
- while ((*cp&0177) != '\0')
- *cp++ &= 0177;
- switch(insymbol(0)) {
- case SCLEAR:
- ClearCommand();
- return;
-
- case SHELP:
- case '?':
- HelpCommand();
- return;
-
- case SINT:
- InterruptCommand(0);
- break;
-
- case SINTD:
- InterruptCommand(1);
- return;
-
- case SPAR:
- ParCommand();
- return;
-
- case SPROF:
- ProfileCommand();
- return;
-
- case SRESET:
- ResetCommand();
- return;
-
- case SSET:
- SetCommand();
- return;
-
- case SSTATUS:
- StatusCommand();
- return;
-
- case SPRI:
- case SREV:
- case SNUM:
- X121CallCommand();
- return;
-
- case SCALL:
- CallCommand();
- return;
-
- case SNUI:
- NuiCommand ();
- return;
-
- case '\0':
- NullCommand();
- return;
-
- case '.':
- DotCommand();
- return;
-
- default:
- message ("Unknown NIM command\r");
- return;
- }
- }
-
- GetNumber(np)
- register struct NameList *np;
- {
-
- (void) insymbol(0);
- if (sym.s_type == SNUM)
- return (1);
- if (sym.s_type == '(') {
- register int value;
-
- switch (insymbol(1)) {
- case SSTR:
- if (strlen (sym.s_str) != 1)
- return (0);
- value = *sym.s_str;
- break;
-
- case SNUM:
- value = sym.s_num;
- break;
-
- default:
- if (sym.s_type == '\r')
- return (0);
- value = sym.s_type;
- }
- (void) insymbol(0);
- if(sym.s_type == ')') {
- sym.s_num = value;
- return(1);
- }
- return(0);
- }
- if (sym.s_type == SSTR && np)
- for (; np->n_name; np++)
- if (strcmp(np->n_name, sym.s_str) == 0) {
- sym.s_num = np->n_value;
- return (1);
- }
- return (0);
- }
-
- /*
- * Save the string pointed to by 's'
- */
-
- char *
- saves(s)
- char *s;
- {
- register char *p;
- char *malloc();
-
- p = malloc(strlen(s) + 1);
- strcpy(p, s);
- return (p);
- }
-
- char
- GetEscaped ()
- {
- register char c, value;
-
- c = NEXTC;
- if (c < '0' || c > '7')
- return (c);
- value = c - '0';
- c = NEXTC;
- if (c >= '0' && c <= '7') {
- register int n;
-
- value = value*8 + c - '0';
- c = NEXTC;
- if (c >= '0' && c <= '7' && (n = value*8 + c-'0') < 256) {
- value = n;
- c = NEXTC;
- }
- }
- return (value);
- }
-
- insymbol(special)
- {
- register char c, *cp;
- char buf[128];
-
- if (sym.s_str) {
- free(sym.s_str);
- sym.s_str = 0;
- }
-
- cp = buf;
- while ((c = NEXTC) == ' ' || c == '\t');
-
- if (c == '\'' || c == '"') {
- register char quote = c;
-
- while (1) {
- c = NEXTC;
- if (c == '\0')
- return (sym.s_type = 0);
- if (c == quote)
- break;
- if (c == '\\')
- c = GetEscaped ();
- if(cp < buf + sizeof (buf))
- *cp++ = c;
- }
- *cp = '\0';
- sym.s_type = SSTR;
- sym.s_str = saves (buf);
- return (sym.s_type);
- }
-
- if (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c == '\\') {
- do {
- if (c == '\\')
- c = GetEscaped ();
- if(cp < buf + sizeof (buf)) {
- if (!special && c >= 'A' && c <= 'Z')
- c -= 'A' - 'a';
- *cp++ = c;
- }
- c = NEXTC;
- } while (c >= '0' && c <= '9' || c >= 'a' && c <= 'z' ||
- c >= 'A' && c <= 'Z' || c == '_' || c == '-');
- *cp = '\0';
- if (c)
- sym.s_next--;
-
- /*
- * set symbol type to SSTR and
- * then look for keywords
- */
-
- sym.s_type = SSTR;
- if (!special) {
- register struct NIMCommand *np;
-
- cp = &buf[0];
- for (np = Commands; np->c_name; np++)
- if(strcmp(cp, np->c_name) == 0) {
- sym.s_type = np->c_value;
- break;
- }
- }
- if (sym.s_type == SSTR)
- sym.s_str = saves(buf);
- return (sym.s_type);
- }
-
- if (c >= '0' && c <= '9') {
- do {
- if(cp < buf + sizeof (buf))
- *cp++ = c;
- c = NEXTC;
- } while(c >= '0' && c <= '9');
- *cp = '\0';
- if (c)
- sym.s_next--;
- sym.s_num = atoi(buf);
- sym.s_type = SNUM;
- sym.s_str = saves(buf);
- return (SNUM);
- }
- return (sym.s_type = c);
- }
-
- /*
- * Does nothing useful - retained for
- * compatibility with Datapac.
- */
-
- DotCommand()
- {
- message (Banner);
- }
-
- X121CallCommand()
- {
- register int len, havenet = 0;
-
- if (State & ST_DATA) {
- message ("You are connected to %s, please clear this call before attempting another\r",
- RemoteHostName?RemoteHostName:(char *)RemoteHostAddr.x25_addr);
- return;
- }
- bzero ((char *)&RemoteHostAddr, sizeof (RemoteHostAddr));
- if (RemoteHostName) {
- free (RemoteHostName);
- RemoteHostName = (char *)0;
- }
-
- while (sym.s_type == SPRI || sym.s_type == SREV) {
- if (sym.s_type == SPRI) /* Datapac specific */
- RemoteHostAddr.x25_opts.op_psize = X25_PS128;
- else if (sym.s_type == SREV)
- RemoteHostAddr.x25_opts.op_flags |= X25_REVERSE_CHARGE;
- (void) insymbol(0);
- }
- getaddr:
- if (sym.s_type != SNUM) {
- message("Non-numeric destination address\r");
- return;
- }
- if (strlen(sym.s_str) > sizeof (RemoteHostAddr.x25_addr) - 1) {
- message ("Destination address too long\r");
- return;
- }
- strcpy(RemoteHostAddr.x25_addr, sym.s_str);
-
- (void) insymbol(1);
- if (sym.s_type == ':' || sym.s_type == '.') {
- if (havenet) {
- message("Destination address error\r");
- return;
- }
- havenet++;
- RemoteHostAddr.x25_net = atoi(RemoteHostAddr.x25_addr);
- (void) insymbol(1);
- goto getaddr;
- }
-
- if (sym.s_type == ',') /* skip optional comma */
- (void) insymbol(1);
-
- RemoteHostAddr.x25_udata[0] = ITI_CALL;
- RemoteHostAddr.x25_udlen = 4;
- if (sym.s_type == SSTR || sym.s_type == SNUM) {
- if ((len = strlen(sym.s_str)) > sizeof (RemoteHostAddr.x25_udata) - 4) {
- message ("Userdata field too long\r");
- RemoteHostAddr.x25_addr[0] = '\0';
- return;
- }
- strcpy(RemoteHostAddr.x25_udata + 4, sym.s_str);
- RemoteHostAddr.x25_udlen += len;
- (void) insymbol(1);
- }
-
- if (sym.s_type == ',') /* skip optional comma */
- (void) insymbol(1);
- if (sym.s_type == SSTR || sym.s_type == SNUM) { /* protocol id */
- if (strlen(sym.s_str) > 4) {
- message ("Protocol field too long\r");
- RemoteHostAddr.x25_addr[0] = '\0';
- return;
- }
- strcpy(RemoteHostAddr.x25_udata, sym.s_str);
- (void) insymbol(0);
- }
-
- if (sym.s_type != '\0') { /* still more to come? */
- message ("usage: [options] address [userdata] [protocol id]\r");
- RemoteHostAddr.x25_addr[0] = '\0';
- return;
- }
-
- InitiateSession ();
- }
-
- CallCommand ()
- {
- register struct hostent *hp;
- struct hostent *getx25hostbyname ();
-
- if (insymbol(1) == '\0') {
- if (RemoteHostAddr.x25_addr[0] == '\0') {
- message ("Call who?\r");
- return;
- }
- } else {
- if (sym.s_type != SSTR) {
- message("nimd: usage: call [hostname]\r");
- return;
- }
- if ((hp = getx25hostbyname (sym.s_str)) == 0) {
- message ("nimd: can't find \"%s\" in host table\r",
- sym.s_str);
- return;
- }
- if (RemoteHostName)
- free (RemoteHostName);
- RemoteHostName = saves (sym.s_str);
- bcopy (hp->h_addr, (char *)&RemoteHostAddr, sizeof (RemoteHostAddr));
- RemoteHostAddr.x25_udata[0] = ITI_CALL;
- }
- InitiateSession ();
- }
-
- InitiateSession ()
- {
- register char *cp;
- struct sockaddr_x25 peer;
- int slen = sizeof (struct sockaddr_x25);
- char buf[256];
- int on = 1;
-
- #ifdef waterloo
- extern char user_name[];
-
- if ((RemoteHostAddr.x25_opts.op_flags & X25_REVERSE_CHARGE) == 0 &&
- !(user_name[0] ? x25_can_callin(user_name) : 1)) {
- message("You may not place locally charged calls\r");
- return;
- }
- #endif
- sprint (buf, "calling %s", RemoteHostAddr.x25_addr);
- cp = buf + strlen (buf);
- if (RemoteHostName) {
- sprint (cp, " (%s)", RemoteHostName);
- cp = cp + strlen (cp);
- }
- if (RemoteHostAddr.x25_opts.op_flags & X25_REVERSE_CHARGE)
- strcat (cp, " collect");
- log (buf);
- if ((NetFd = socket (AF_CCITT, SOCK_STREAM, 0)) < 0) {
- error ();
- return;
- }
- RemoteHostAddr.x25_family = AF_CCITT;
- RemoteHostAddr.x25_opts.op_flags |= X25_MQBIT;
- if (connect (NetFd, (char *)&RemoteHostAddr, sizeof (RemoteHostAddr)) < 0) {
- error ();
- close (NetFd);
- NetFd = -1;
- return;
- }
- if (getpeername (NetFd, (struct sockaddr *)&peer, &slen))
- error ();
- NetInfo.n_psize = (1 << peer.x25_opts.op_psize);
- log ("call succeeded: packet size=%d", NetInfo.n_psize);
- if (CurrentX29Parms[X29_RECEIVE_NET_MSGS_CODE]) {
- message ("nimd:\tCall connected to %s", RemoteHostAddr.x25_addr);
- if (RemoteHostName)
- message (" (%s)", RemoteHostName);
- message ("\r\t(%s charging, packet size: %d)\r\r",
- RemoteHostAddr.x25_opts.op_flags & X25_REVERSE_CHARGE ?
- "remote" : "local", NetInfo.n_psize);
- }
-
- ioctl (NetFd, FIONBIO, (char *)&on);
- State |= ST_DATA;
- State &= ~ST_COMMAND;
- }
-
- struct X29Keyword *
- LookupX29Keyword(word)
- char *word;
- {
- register struct X29Keyword *xp;
-
- for (xp = X29Keywords; xp->x_word; xp++)
- if (strcmp(word, xp->x_word) == 0)
- return (xp);
- return ((struct X29Keyword *)0);
- }
-
- ParCommand()
- {
- register int param;
- register struct X29Keyword *xp;
-
- if (insymbol(0) == '\0') {
- DisplayCurrentParms();
- return;
- }
- while (sym.s_type != '\0') {
- switch (sym.s_type) {
- case SNUM:
- param = sym.s_num;
- xp = 0;
- break;
-
- case SSTR:
- if ((xp = LookupX29Keyword(sym.s_str)) == 0) {
- message("%s: unknown X.29 parameter\r", sym.s_str);
- return;
- }
- param = xp->x_param;
- break;
-
- default:
- message("number or X.29 parameter name expected\r");
- return;
- }
- if (xp)
- message ("%s:%d\r", xp->x_word, CurrentX29Parms[param]);
- else
- message ("%d:%d\r", param, CurrentX29Parms[param]);
- if (insymbol(0) == ',') /* skip optional comma */
- (void) insymbol(0);
- }
- }
-
- DisplayCurrentParms()
- {
- register int nparams, pnum, i;
-
- nparams = NetInfo.n_nparms;
- for (i=0; i<nparams; i++) {
- pnum = pnums[i];
- message (i%6 ? ", %d:%d" : "\t%d:%d", pnum,
- CurrentX29Parms[pnum]);
- if (i % 6 == 5)
- message ("\r");
- }
- if (nparams % 6)
- message ("\r");
- }
-
- SetCommand()
- {
- register int setandread = 0, param;
- register struct X29Keyword *xp;
-
- (void) insymbol(0);
- if (sym.s_type == '?') {
- setandread++;
- insymbol(0);
- }
- while (sym.s_type != '\0') {
- switch (sym.s_type) {
- case SNUM:
- param = sym.s_num;
- xp = 0;
- break;
-
- case SSTR:
- if ((xp = LookupX29Keyword(sym.s_str)) == 0) {
- message("%s: unknown X.29 parameter\r", sym.s_str);
- return;
- }
- param = xp->x_param;
- break;
-
- default:
- message("number or X.29 parameter name expected\r");
- return;
- }
- (void) insymbol(0);
- if (sym.s_type != ':' && sym.s_type != '=') {
- message("':' or '=' expected between parameter and value\r");
- return;
- }
- if (GetNumber(xp ? xp->x_list : 0)) {
- if (SetX29Parm(param, sym.s_num))
- if (xp)
- message ("par %s:invalid\r", xp->x_word);
- else
- message("par %d:invalid\r", param);
- else
- if (setandread)
- if (xp)
- message ("par %s:%d\r",
- xp->x_word, sym.s_num);
- else
- message("PAR %d:%d\r", param, sym.s_num);
- } else {
- message("number expected\r");
- return;
- }
- (void) insymbol(0);
- if (sym.s_type == ',') /* skip optional comma */
- (void) insymbol(0);
- }
- }
-
- ProfileCommand()
- {
- register int displayonly = 0, profile;
-
- if (insymbol(0) == '?') {
- displayonly++;
- (void) insymbol(0);
- }
- if (sym.s_type == SNUM) {
- profile = sym.s_num;
- if (profile >= 0 && profile <= 6)
- if (insymbol(0) == '\0') {
- if (displayonly)
- DisplayProfile(profile);
- else
- InitProfile(profile);
- return;
- }
- }
- message("usage: prof n or prof?n where n is a number between 1 and 6\r");
- }
-
- DisplayProfile (profile)
- {
- register int i, nparms, pnum, value;
- extern char profiles[NPROFILES+1][NX29_PARMS];
-
- nparms = NetInfo.n_nparms;
- for (i=1; i<=nparms; i++) {
- pnum = pnums[i];
- value = profiles[profile][pnum];
- if (i % 6 == 0)
- if (i == 0)
- message ("prof %d\t%d:%d", profile, pnum, value);
- else
- message ("\t%d:%d", pnum, value);
- else
- message (", %d:%d", pnum, value);
- if (i % 6 == 5)
- message ("\r");
- }
- if (nparms % 6)
- message ("\r");
- }
-
- StatusCommand ()
- {
- if (State & ST_DATA)
- message ("Connected to %s\r", RemoteHostName);
- else
- message ("idle\r");
- }
-
- InterruptCommand(discard)
- {
- if (discard)
- Break (21);
- else
- Break (1);
- }
-
- ClearCommand ()
- {
- if (State & ST_DATA)
- ExitDataState ("local directive");
- else
- message ("you are not connected to anybody\r");
- }
-
- NullCommand ()
- {
- if (State & ST_ESCCOMM)
- State &= ~(ST_COMMAND|ST_ESCCOMM);
- else
- message (Banner);
- }
-
- ResetCommand()
- {
- ResetBufs ();
- }
-
- HelpCommand()
- {
- GetHelp ("general-info");
- }
-
- GetHelp (topic)
- char *topic;
- {
- register int fd;
- char HelpFile[128];
-
- strcpy (HelpFile, HELPFILE);
- strcat (HelpFile, topic);
- if ((fd = open (HelpFile, 0)) < 0) {
- message ("No help with %s\r", topic);
- return;
- }
- /* not yet implemented */
- close (fd);
- }
-
- NuiCommand () /* net completely implemented */
- {
- if (insymbol (1) == '\0') {
- if (Nui)
- message ("NUI = %s\r", Nui);
- else
- message ("No valid NUI\r");
- return;
- }
- }
-