/* * Copyright (c) 1999-2003 Smithsonian Astrophysical Observatory */ #include /* *---------------------------------------------------------------------------- * * * Private Routines and Data * * *---------------------------------------------------------------------------- */ /* this is the static xpa struct that holds the reserved commands */ static XPA rxpa=NULL; /* *---------------------------------------------------------------------------- * * Routine: XPACmdParseNames * * Purpose: massage a name string, changing multiple sequential spaces * into a single space * * Returns: new name, with spaces massaged (also number of spacess) * *---------------------------------------------------------------------------- */ #ifdef ANSI_FUNC static char * XPACmdParseNames(char *lbuf, int *ntokens) #else static char *XPACmdParseNames(lbuf, ntokens) char *lbuf; int *ntokens; #endif { char tbuf[SZ_LINE]; int lp=0; char *buf; /* can't be larger than the original string */ buf = (char *)xmalloc(strlen(lbuf)+1); *buf = '\0'; *ntokens = 0; /* pick off each word, separating by a single space */ while( word(lbuf, tbuf, &lp)){ if( *buf != '\0' ) strcat(buf, " "); strcat(buf, tbuf); *ntokens += 1; } /* make the string the right size */ buf = (char *)xrealloc(buf, strlen(buf)+1); return(buf); } /* *---------------------------------------------------------------------------- * * Routine: XPAReceiveNSConnect * * Purpose: reset and re-establish connection to name server * * Returns: xpa callback error codes * *---------------------------------------------------------------------------- */ #ifdef ANSI_FUNC static int XPAReceiveNSConnect (void *client_data, void *call_data, char *paramlist, char *buf, size_t len) #else static int XPAReceiveNSConnect(client_data, call_data, paramlist, buf, len) void *client_data; void *call_data; char *paramlist; char *buf; size_t len; #endif { XPA xpa = (XPA)call_data; XPA txpa; char tbuf[SZ_LINE]; int doall=0; int lp=0; if( paramlist && *paramlist ){ if( word(paramlist, tbuf, &lp) && !strcmp(tbuf, "-all") ){ doall = 1; } } if( doall ){ for(txpa=XPAListHead(); txpa!=NULL; txpa=txpa->next){ XPANSAdd(txpa, NULL, NULL); } } else{ XPANSAdd(xpa, NULL, NULL); } return(0); } /* *---------------------------------------------------------------------------- * * Routine: XPAReceiveNSDisconnect * * Purpose: break connection to name server * * Returns: xpa callback error codes * *---------------------------------------------------------------------------- */ #ifdef ANSI_FUNC static int XPAReceiveNSDisconnect (void *client_data, void *call_data, char *paramlist, char *buf, size_t len) #else static int XPAReceiveNSDisconnect(client_data, call_data, paramlist, buf, len) void *client_data; void *call_data; char *paramlist; char *buf; size_t len; #endif { XPA xpa = (XPA)call_data; XPA txpa; NS ns, tns; char tbuf[SZ_LINE]; int doall=0; int lp=0; if( paramlist && *paramlist ){ if( word(paramlist, tbuf, &lp) && !strcmp(tbuf, "-all") ){ doall = 1; } } if( doall ){ for(txpa=XPAListHead(); txpa!=NULL; txpa=txpa->next){ for(ns=txpa->nshead; ns!= NULL; ){ tns = ns->next; XPANSClose(txpa, ns); ns = tns; } } } else{ for(ns=xpa->nshead; ns!= NULL; ){ tns = ns->next; XPANSClose(xpa, ns); ns = tns; } } return(0); } /* *---------------------------------------------------------------------------- * * Routine: XPAReceiveEnv * * Purpose: set an environment variable * * Returns: xpa callback error codes * *---------------------------------------------------------------------------- */ #ifdef ANSI_FUNC static int XPAReceiveEnv (void *client_data, void *call_data, char *paramlist, char *buf, size_t len) #else static int XPAReceiveEnv(client_data, call_data, paramlist, buf, len) void *client_data; void *call_data; char *paramlist; char *buf; size_t len; #endif { XPA xpa = (XPA)call_data; char name[SZ_LINE]; char value[SZ_LINE]; char *tbuf; int lp=0; if( word(paramlist, name, &lp) ){ if( word(paramlist, value, &lp) ){ tbuf = (char *)xmalloc(strlen(name)+1+strlen(value)+1); snprintf(tbuf, SZ_LINE, "%s=%s", name, value); putenv(tbuf); return(0); } else{ if( strchr(name, '=') != NULL ){ tbuf = xstrdup(name); putenv(tbuf); return(0); } else{ XPAError(xpa, "XPA setenv requires name and value pair\n"); return(-1); } } } else{ XPAError(xpa, "XPA setenv requires name and value pair\n"); return(-1); } } /* *---------------------------------------------------------------------------- * * Routine: XPASendEnv * * Purpose: return an environment variable to client * * Returns: xpa callback error codes * *---------------------------------------------------------------------------- */ #ifdef ANSI_FUNC static int XPASendEnv (void *client_data, void *call_data, char *paramlist, char **buf, size_t *len) #else static int XPASendEnv(client_data, call_data, paramlist, buf, len) void *client_data; void *call_data; char *paramlist; char **buf; size_t *len; #endif { int tlen; char *tbuf; char *ebuf; if( (ebuf = (char *)getenv(paramlist)) != NULL ){ tlen = strlen(ebuf)+2; tbuf = (char *)xmalloc(tlen); snprintf(tbuf, tlen, "%s\n", ebuf); *buf = tbuf; *len = strlen(tbuf); } else{ *buf = xstrdup("\n"); *len = 1; } return(0); } /* *---------------------------------------------------------------------------- * * Routine: XPAReceiveReserved * * Purpose: execute reserved command * * Returns: xpa callback error codes * *---------------------------------------------------------------------------- */ #ifdef ANSI_FUNC static int XPAReceiveReserved (void *client_data, void *call_data, char *paramlist, char *buf, size_t len) #else static int XPAReceiveReserved(client_data, call_data, paramlist, buf, len) void *client_data; void *call_data; char *paramlist; char *buf; size_t len; #endif { char *cmd = (char *)client_data; XPA xpa = (XPA)call_data; if( !strcmp(cmd, "end") ){ xpa->comm->status |= XPA_STATUS_ENDBUF; return(0); } else if( !strcmp(cmd, "exec") ){ xpa->comm->status |= XPA_STATUS_READBUF; return(0); } else{ return(-1); } } /* *---------------------------------------------------------------------------- * * Routine: XPASendHelp * * Purpose: send help strings * * Returns: xpa callback error codes * *---------------------------------------------------------------------------- */ #ifdef ANSI_FUNC static int XPASendHelp (void *client_data, void *call_data, char *paramlist, char **buf, size_t *len) #else static int XPASendHelp(client_data, call_data, paramlist, buf, len) void *client_data; void *call_data; char *paramlist; char **buf; size_t *len; #endif { XPA xpa = (XPA)call_data; XPACmd cmd; int lp=0; int slen; char tbuf[SZ_LINE]; char lbuf[SZ_LINE]; char *sbuf; if( !paramlist || !*paramlist ){ if( xpa->version != NULL ){ snprintf(lbuf, SZ_LINE, "XPA version: %s\n", xpa->version); send(xpa_datafd(xpa), lbuf, strlen(lbuf), 0); } } if( xpa->commands == NULL ){ if( xpa->help != NULL ){ slen = strlen(xpa->help)+SZ_LINE; sbuf = (char *)xmalloc(slen); snprintf(sbuf, slen, "%s\n", xpa->help); send(xpa_datafd(xpa), sbuf, strlen(sbuf), 0); xfree(sbuf); } else{ strcpy(lbuf, "\n"); send(xpa_datafd(xpa), lbuf, strlen(lbuf), 0); } } else{ if( paramlist && *paramlist ){ while( word(paramlist, tbuf, &lp) ){ for(cmd=xpa->commands; cmd!=NULL; cmd=cmd->next){ if( !strcmp(tbuf, cmd->name) ){ if( cmd->help != NULL ){ slen = strlen(cmd->name)+strlen(cmd->help)+SZ_LINE; sbuf = (char *)xmalloc(slen); snprintf(sbuf, slen, "%s:\t%s\n", cmd->name, cmd->help); send(xpa_datafd(xpa), sbuf, strlen(sbuf), 0); xfree(sbuf); } else{ snprintf(lbuf, SZ_LINE, "%s:\t(no help available)\n", cmd->name); send(xpa_datafd(xpa), lbuf, strlen(lbuf), 0); } } } } } else{ for(cmd=xpa->commands; cmd!=NULL; cmd=cmd->next){ if( cmd->help != NULL ){ slen = strlen(cmd->name)+strlen(cmd->help)+SZ_LINE; sbuf = (char *)xmalloc(slen); snprintf(sbuf, slen, "%s:\t%s\n", cmd->name, cmd->help); send(xpa_datafd(xpa), sbuf, strlen(sbuf), 0); xfree(sbuf); } else{ snprintf(lbuf, SZ_LINE, "%s:\t(no help available)\n", cmd->name); send(xpa_datafd(xpa), lbuf, strlen(lbuf), 0); } } } } return(0); } /* *---------------------------------------------------------------------------- * * Routine: XPASendVersion * * Purpose: send XPA version string * * Returns: xpa callback error codes * *---------------------------------------------------------------------------- */ #ifdef ANSI_FUNC static int XPASendVersion (void *client_data, void *call_data, char *paramlist, char **buf, size_t *len) #else static int XPASendVersion(client_data, call_data, paramlist, buf, len) void *client_data; void *call_data; char *paramlist; char **buf; size_t *len; #endif { XPA xpa = (XPA)call_data; char lbuf[SZ_LINE]; if( xpa->version != NULL ) snprintf(lbuf, SZ_LINE, "%s\n", xpa->version); else strcpy(lbuf, "\n"); send(xpa_datafd(xpa), lbuf, strlen(lbuf), 0); return(0); } /* *---------------------------------------------------------------------------- * * * Semi-Public Routines and Data * * These routines are used by XPAHandler and XPANew * * *---------------------------------------------------------------------------- */ /* *---------------------------------------------------------------------------- * * Routine: XPAInitReserved * * Purpose: add the reserved commands to the reserved xpa struct * * Results: none * *---------------------------------------------------------------------------- */ #ifdef ANSI_FUNC void XPAInitReserved (void) #else void XPAInitReserved() #endif { if( !rxpa ){ if( (rxpa = (XPA)xcalloc(1, sizeof(struct xparec))) == NULL ) return; /* XPACmdAdd requires that the callbacks be defined explicitly in rxpa */ rxpa->send_callback = XPASendCommands; rxpa->receive_callback = XPAReceiveCommands; /* add reserved commands */ XPACmdAdd(rxpa, "-acl", "\tget (set) the access control list\n\t\t options: host type acl", XPASendAcl, NULL, NULL, XPAReceiveAcl, NULL, "fillbuf=false"); XPACmdAdd(rxpa, "-env", "\tget (set) an environment variable\n\t\t options: name (value)", XPASendEnv, NULL, NULL, XPAReceiveEnv, NULL, NULL); XPACmdAdd(rxpa, "-exec", "\texecute commands from buffer\n\t\t options: none", NULL, NULL, NULL, XPAReceiveReserved, (void *)"exec", NULL); XPACmdAdd(rxpa, "-help", "\treturn help string for specified XPA\n\t\t options: cmd name (commands only)", XPASendHelp, NULL, NULL, NULL, NULL, NULL); XPACmdAdd(rxpa, "-ltimeout", "\tget (set) long timeout\n\t\t options: seconds|reset", XPASendLTimeout, NULL, NULL, XPAReceiveLTimeout, NULL, NULL); XPACmdAdd(rxpa, "-nsconnect", "\tre-establish name server connection to this XPA\n\t\t options: -all", NULL, NULL, NULL, XPAReceiveNSConnect, NULL, NULL); XPACmdAdd(rxpa, "-nsdisconnect", "\tbreak name server connection to this XPA\n\t\t options: -all", NULL, NULL, NULL, XPAReceiveNSDisconnect, NULL, NULL); XPACmdAdd(rxpa, "-remote", "\tconnect to remote name service with specified acl \n\t\t options: host:port +|-|acl -proxy", XPASendRemote, NULL, NULL, XPAReceiveRemote, NULL, "fillbuf=false"); XPACmdAdd(rxpa, "-clipboard", "\tset/get clipboard information \n\t\t options: [cmd] name", XPASendClipboard, NULL, NULL, XPAReceiveClipboard, NULL, NULL); XPACmdAdd(rxpa, "-stimeout", "\tget (set) short timeout\n\t\t options: seconds|reset", XPASendSTimeout, NULL, NULL, XPAReceiveSTimeout, NULL, NULL); XPACmdAdd(rxpa, "-version", "\treturn XPA version string\n\t\t options: none", XPASendVersion, NULL, NULL, NULL, NULL, NULL); } } #ifdef ANSI_FUNC void XPAFreeReserved (void) #else void XPAFreeReserved() #endif { XPACmd cmd, tcmd; if( !rxpa ) return; /* free reserved commands */ for(cmd=rxpa->commands; cmd!=NULL; ){ tcmd = cmd->next; XPACmdDel(rxpa, cmd); cmd = tcmd; } xfree(rxpa); rxpa = NULL; } /* *---------------------------------------------------------------------------- * * Routine: XPACmdLookupReserved * * Purpose: lookup a reserved command name * * Results: cmd struct or null * *---------------------------------------------------------------------------- */ #ifdef ANSI_FUNC XPACmd XPACmdLookupReserved (XPA xpa, char *lbuf, int *lp) #else XPACmd XPACmdLookupReserved(xpa, lbuf, lp) XPA xpa; char *lbuf; int *lp; #endif { XPACmd cmd; int lp2=0; char *lptr; char name[SZ_LINE]; /* make sure we have something to work with */ if( (rxpa==NULL) || (lbuf==NULL) || (lbuf[*lp]=='\0') ) return(NULL); /* this is where we start parsing */ lptr = &(lbuf[*lp]); /* to simplify life, we assume reserved words are 1 token */ if( !word(lptr, name, &lp2) ) return(NULL); /* look for reserved keywords that have callbacks */ for(cmd=rxpa->commands; cmd!=NULL; cmd=cmd->next){ if( !strcmp(name, cmd->name) ){ *lp += lp2; return(cmd); } } /* nothing, nowhere */ return(NULL); } /* *---------------------------------------------------------------------------- * * Routine: XPACmdLookup * * Purpose: lookup a user-defined command name * * Results: cmd struct or null * *---------------------------------------------------------------------------- */ #ifdef ANSI_FUNC XPACmd XPACmdLookup (XPA xpa, char *lbuf, int *lp) #else XPACmd XPACmdLookup(xpa, lbuf, lp) XPA xpa; char *lbuf; int *lp; #endif { XPACmd cmd; int i; int lp2; int len, tlen; char *lptr; char tbuf[SZ_LINE]; char name[SZ_LINE]; /* make sure we have something to work with */ if( (xpa==NULL) || (lbuf==NULL) || (lbuf[*lp]=='\0') ) return(NULL); /* this is where we start parsing */ lptr = &(lbuf[*lp]); /* look up commands for this name */ for(cmd=xpa->commands; cmd!=NULL; cmd=cmd->next){ /* make up a name with the required number of tokens for this command */ *name = '\0'; lp2 = 0; tlen = 0; for(i=0; intokens; i++){ if( word(lptr, tbuf, &lp2)){ len = strlen(tbuf)+1; if( (tlen+len) <= (SZ_LINE-1) ){ if( *name != '\0' ) strcat(name, " "); strcat(name, tbuf); tlen += len; } /* not enough room */ else{ *name = '\0'; break; } } } /* we now have the name, see if its what we want */ if( *name && !strcmp(cmd->name, name) ){ *lp += lp2; return(cmd); } } /* did not find the command in this xpa -- now look through reserved */ return(XPACmdLookupReserved(xpa, lbuf, lp)); } /* *---------------------------------------------------------------------------- * * Routine: XPAReceiveCommands * * Purpose: process a list of commands from xpaset * * Results: number of commands processed * *---------------------------------------------------------------------------- */ #ifdef ANSI_FUNC int XPAReceiveCommands (void *client_data, void *call_data, char *paramlist, char *buf, size_t len) #else int XPAReceiveCommands(client_data, call_data, paramlist, buf, len) void *client_data; void *call_data; char *paramlist; char *buf; size_t len; #endif { XPA xpa = (XPA)call_data; XPACmd cmd; int lp; int savelp; int plen; int bgot; int got=0; int gotbuf=0; int freebuf=1; char lbuf[SZ_LINE]; char tbuf[SZ_LINE]; char tbuf1[SZ_LINE]; /* use ";" as a command separator (as well as \n) */ newdtable(";"); /* if we already have buf, there will be no need to get it */ if( buf ) gotbuf++; /* if we have no paramlist, we read from the socket */ if( (xpa_datafd(xpa) >=0) && (!paramlist || (*paramlist == '\0')) ){ xpa->comm->status |= XPA_STATUS_READBUF; XPAGets(xpa, xpa_datafd(xpa), lbuf, SZ_LINE, XPALongTimeout()); FPRINTF((stderr, "%sXPAReceiveCommands: read %s\n", _sp, lbuf)); } else{ xpa->comm->status &= ~XPA_STATUS_READBUF; nowhite(paramlist, lbuf); } /* we must have something to start with */ if( *lbuf == '\0' ){ XPAError(xpa, xpaMessbuf[XPA_RTN_NOCMD2]); got = -1; goto done; } /* This look either executes the one set of commands in paramlist, or reads one line at a time from the socket and executes commands. In the latter case, each callback can read the socket as well */ while( 1 ){ FPRINTF((stderr, "%sXPAReceiveCommands: top of loop: %s\n", _sp, lbuf)); lp = 0; while( lbuf[lp] != '\0' ){ if( (cmd = XPACmdLookup(xpa, lbuf, &lp)) == NULL ){ XPAError(xpa, xpaMessbuf[XPA_RTN_UNCMD]); got = -1; goto done; } /* reserved commands can only be called from the same host as the server, or from local (unix) sockets */ if( (cmd->xpa == rxpa) && strcmp(cmd->name, "-help") && strcmp(cmd->name, "-version") ){ if( XPAMtype() == XPA_INET ){ if( (!xpa->comm || !LOCALIP(xpa->comm->cmdip)) ){ FPRINTF((stderr, "%sXPAReceiveCommands: rejecting reserved: %s\n", _sp, cmd->name)); XPAError(xpa, xpaMessbuf[XPA_RTN_NOAUTH]); got = -1; goto done; } } } FPRINTF((stderr, "%sXPAReceiveCommands: cmd->name: %s\n", _sp, cmd->name)); *tbuf = '\0'; if( (lastdelim() != ';') && (lastdelim() != '\n') ){ /* skip white space between command and params */ while( isspace((int)lbuf[lp]) ) lp++; /* here is where the params start */ savelp = lp; /* look for command delimiter -- the end of the params */ while( word(lbuf, tbuf1, &lp) ){ if( (lastdelim() == ';') || (lastdelim() == '\n') ){ break; } /* make sure a command-ending delim is not next */ while( isspace((int)lbuf[lp]) ) lp++; if( (lbuf[lp] == ';') || (lbuf[lp] == '\n') ){ break; } } /* get length of parameter list */ plen = lp - savelp; /* but skip final delim */ if( (plen>0) && ((lastdelim() == ';')||(lastdelim() == '\n')) ) plen--; /* copy the params up to the command delimiter */ if( plen > 0 ){ strncpy(tbuf, &(lbuf[savelp]), plen); tbuf[plen] = '\0'; } } /* execute the associated XPA callback */ if( cmd->receive_callback != NULL ){ /* get buf now, if its needed */ if( !gotbuf && (xpa_datafd(xpa) >= 0) && (cmd->receive_mode & XPA_MODE_FILLBUF) ){ /* read buf -- this buf will stay around for all commands */ FPRINTF((stderr, "%sXPAReceiveCommands: at XPAGetBuf\n", _sp)); bgot = XPAGetBuf(xpa, xpa_datafd(xpa), &buf, &len, -1); /* close the data channel */ XPACloseData(xpa, xpa->comm); if( bgot >= 0 ){ /* got the buffer */ gotbuf++; } /* error getting buf */ else{ XPAError(xpa, xpaMessbuf[XPA_RTN_NODATA]); got = -1; goto done; } } got = (cmd->receive_callback)(cmd->receive_data, call_data, tbuf, buf, len); /* if we don't want to free the buffer, mark it for saving */ if( (buf != NULL) && !(cmd->receive_mode & XPA_MODE_FREEBUF) ){ freebuf=0; } if( got != 0 ){ goto done; } } else{ XPAError(xpa, xpaMessbuf[XPA_RTN_NOREC]); got = -1; goto done; } } /* conditions for exiting the command loop: */ /* if we processed the END command, we are done */ if( xpa->comm->status & XPA_STATUS_ENDBUF ) break; /* if we are not reading the data buffer, we are done */ if( !(xpa->comm->status & XPA_STATUS_READBUF) ) break; /* if we got EOF or error reading the data buffer, we are done */ if( XPAGets(xpa, xpa_datafd(xpa), lbuf, SZ_LINE, XPALongTimeout()) <=0 ) break; } done: /* if no one wants buf, free it now */ if( freebuf ) xfree(buf); /* restore last delimiter table */ freedtable(); /* return error code */ return(got); } /* *---------------------------------------------------------------------------- * * Routine: XPASendCommands * * Purpose: process a list of commands from xpaget * * Results: number of commands processed (currently 0 or 1) * *---------------------------------------------------------------------------- */ #ifdef ANSI_FUNC int XPASendCommands (void *client_data, void *call_data, char *paramlist, char **buf, size_t *len) #else int XPASendCommands(client_data, call_data, paramlist, buf, len) void *client_data; void *call_data; char *paramlist; char **buf; size_t *len; #endif { XPA xpa = (XPA)call_data; XPACmd cmd; char tbuf[SZ_LINE]; int lp=0; int got=0; /* return help as default */ if( *paramlist == '\0' ){ paramlist = "-help"; } /* lookup the command and execute */ if( (cmd = XPACmdLookup(xpa, paramlist, &lp)) != NULL ){ /* reserved commands can only be called from the same host as the server, or from local (unix) sockets */ if( (cmd->xpa == rxpa) && strcmp(cmd->name, "-help") && strcmp(cmd->name, "-version") ){ if( XPAMtype() == XPA_INET ){ if( (!xpa->comm || !LOCALIP(xpa->comm->cmdip)) ){ FPRINTF((stderr, "%sXPAReceiveCommands: rejecting reserved: %s\n", _sp, cmd->name)); XPAError(xpa, xpaMessbuf[XPA_RTN_NOAUTH]); got = -1; goto done; } } } /* execute the associated XPA send callback, using the remaining command string as an argument */ strcpy(tbuf, ¶mlist[lp]); nocr(tbuf); if( !strcmp(tbuf, "-help") ){ if( cmd->help != NULL ) snprintf(tbuf, SZ_LINE, "%s\n", cmd->help); else snprintf(tbuf, SZ_LINE, "\n"); send(xpa_datafd(xpa), tbuf, strlen(tbuf), 0); got = 0; } else if( cmd->send_callback != NULL ){ got = (cmd->send_callback)(cmd->send_data, call_data, ¶mlist[lp], buf, len); } else{ XPAError(xpa, xpaMessbuf[XPA_RTN_NOSEND]); got = -1; goto done; } } else{ XPAError(xpa, xpaMessbuf[XPA_RTN_UNCMD]); got = -1; goto done; } done: /* return error code */ return(got); } /* *---------------------------------------------------------------------------- * * * Public Routines and Data * * *---------------------------------------------------------------------------- */ /* *---------------------------------------------------------------------------- * * Routine: XPACmdNew * * Purpose: define a named command access point * * Results: XPA struct or NULL * *---------------------------------------------------------------------------- */ #ifdef ANSI_FUNC XPA XPACmdNew (char *xclass, char *name) #else XPA XPACmdNew(xclass, name) char *xclass; char *name; #endif { XPA xpa; char tbuf[SZ_LINE]; /* we need a name */ if( (name == NULL) || (*name == '\0') ) return(NULL); /* we need some valid class */ if( (xclass == NULL) || (*xclass == '\0') ) xclass = "*"; /* help string */ snprintf(tbuf, SZ_LINE, "XPA commands for %s:%s\n\t\t options: see -help", xclass, name); /* create a new XPA with command callbacks */ xpa = XPANew(xclass, name, tbuf, XPASendCommands, NULL, NULL, XPAReceiveCommands, NULL, "fillbuf=false"); /* return the good news */ return(xpa); } /* *---------------------------------------------------------------------------- * * Routine: XPACmdAdd * * Purpose: add a command to a named command access point * * Results: 0 on success, -1 for failure * *---------------------------------------------------------------------------- */ #ifdef ANSI_FUNC XPACmd XPACmdAdd (XPA xpa, char *name, char *help, SendCb send_callback, void *send_data, char *send_mode, ReceiveCb rec_callback, void *rec_data, char *rec_mode) #else XPACmd XPACmdAdd(xpa, name, help, send_callback, send_data, send_mode, rec_callback, rec_data, rec_mode) XPA xpa; char *name; char *help; SendCb send_callback; void *send_data; char *send_mode; ReceiveCb rec_callback; void *rec_data; char *rec_mode; #endif { XPACmd xnew; XPACmd cur; XPACmd prev; /* make sure we have a valid command record */ if( !xpa || (xpa->send_callback != XPASendCommands) || (xpa->receive_callback != XPAReceiveCommands) ){ return(NULL); } /* we need either a send or a receive or both */ if( (send_callback == NULL) && (rec_callback == NULL ) ){ return(NULL); } /* limit the size of the cmd name designation */ if( strlen(name) > XPA_NAMELEN ){ return(NULL); } /* allocate space for a new record */ xnew = (XPACmd)xcalloc(1, sizeof(struct xpacmdrec)); /* backlink to xpa */ xnew->xpa = xpa; /* fill in the blanks */ xnew->name = XPACmdParseNames(name, &(xnew->ntokens)); xnew->help = xstrdup(help); /* receive callback */ xnew->send_callback = send_callback; xnew->send_data = send_data; xnew->send_mode = XPA_DEF_MODE_SEND; XPAMode(send_mode, &(xnew->send_mode), "freebuf", XPA_MODE_FREEBUF,1); /* acl is a global mode */ XPAMode(send_mode, &(xpa->send_mode), "acl", XPA_MODE_ACL, 1); /* receive callback */ xnew->receive_callback = rec_callback; xnew->receive_data = rec_data; /* process the mode string */ xnew->receive_mode = XPA_DEF_MODE_REC; XPAMode(rec_mode, &(xnew->receive_mode), "usebuf", XPA_MODE_BUF,1); XPAMode(rec_mode, &(xnew->receive_mode), "fillbuf", XPA_MODE_FILLBUF,1); XPAMode(rec_mode, &(xnew->receive_mode), "freebuf", XPA_MODE_FREEBUF,1); /* acl is a global mode */ XPAMode(rec_mode, &(xpa->receive_mode), "acl", XPA_MODE_ACL, 1); /* enter into list, in alphabetical order */ if( xpa->commands == NULL ){ xpa->commands = xnew; return(xnew); } else{ for(prev=NULL, cur=xpa->commands; cur!=NULL; prev=cur, cur=cur->next){ /* if new name is an existing name, add it before */ if( strcmp(xnew->name, cur->name) ==0 ) goto addname; /* if existing name is a subset of new name, add it before */ else if( !strncmp(xnew->name, cur->name, strlen(cur->name)) ) goto addname; /* if new name is a subset of existing name, add it after */ else if( !strncmp(xnew->name, cur->name, strlen(xnew->name)) ) continue; /* if new name is lexically greater than existing name, add it after */ else if( strcmp(xnew->name, cur->name) >0 ) continue; addname: /* add the new name here and return */ if( prev == NULL ){ xpa->commands = xnew; xnew->next = cur; return(xnew); } else{ prev->next = xnew; xnew->next = cur; return(xnew); } } /* if we are still here, we did not find a place to insert, i.e., we are at the end of the list */ prev->next = xnew; return(xnew); } } /* *---------------------------------------------------------------------------- * * Routine: XPACmdDel * * Purpose: free a named command access point * * Results: none * *---------------------------------------------------------------------------- */ #ifdef ANSI_FUNC int XPACmdDel (XPA xpa, XPACmd cmd) #else int XPACmdDel(xpa, cmd) XPA xpa; XPACmd cmd; #endif { XPACmd cur; int got=0; /* gotta have something to free */ if( cmd == NULL ) return(-1); /* remove from list of xpa's commands */ if( xpa && xpa->commands ){ if( xpa->commands == cmd ){ xpa->commands = cmd->next; got++; } else{ for(cur=xpa->commands; cur!=NULL; cur=cur->next){ if( cur->next == cmd ){ cur->next = cmd->next; got++; break; } } } } /* free up space */ if( got ){ if( cmd->name ) xfree(cmd->name); if( cmd->help ) xfree(cmd->help); xfree(cmd); return(0); } else{ return(-1); } } /* *---------------------------------------------------------------------------- * * Routine: XPACmdInternalReceive * * Purpose: internal execute of the receive callback for this command * * Results: number of commands processed * *---------------------------------------------------------------------------- */ #ifdef ANSI_FUNC int XPACmdInternalReceive (void *client_data, void *call_data, char *paramlist, char *buf, size_t len) #else int XPACmdInternalReceive(client_data, call_data, paramlist, buf, len) void *client_data; void *call_data; char *paramlist; char *buf; size_t len; #endif { XPA xpa = (XPA)call_data; /* make sure we have something */ if( xpa == NULL ) return(-1); /* make the call */ return(XPAReceiveCommands(client_data, xpa, paramlist, buf, len)); } /* *---------------------------------------------------------------------------- * * Routine: XPACmdInternalSend * * Purpose: internal execute of the send callback for this command * * Results: number of commands processed (currently 0 or 1) * *---------------------------------------------------------------------------- */ #ifdef ANSI_FUNC int XPACmdInternalSend (void *client_data, void *call_data, char *paramlist, char **buf, size_t *len) #else int XPACmdInternalSend(client_data, call_data, paramlist, buf, len) void *client_data; void *call_data; char *paramlist; char **buf; size_t *len; #endif { XPA xpa = (XPA)call_data; /* make sure we have something */ if( xpa == NULL ) return(-1); /* make the call */ return(XPASendCommands(client_data, xpa, paramlist, buf, len)); } /* *---------------------------------------------------------------------------- * * Routine: XPAGetReserved * * Purpose: return xpa handle for reserved xpa commands * * Return: xpa handle * *---------------------------------------------------------------------------- */ #ifdef ANSI_FUNC XPA XPAGetReserved (void) #else XPA XPAGetReserved() #endif { return(rxpa); }