/* Autoconf patching by David Hedbor, neotron@lysator.liu.se */ /*********************************************************************/ /* file: action.c - funtions related to the action command */ /* TINTIN III */ /* (T)he K(I)cki(N) (T)ickin D(I)kumud Clie(N)t */ /* coded by peter unold 1992 */ /*********************************************************************/ #include <ctype.h> #ifdef HAVE_STRING_H #include <string.h> #else #ifdef HAVE_STRINGS_H #include <strings.h> #endif #endif #include "tintin.h" #include <readline/readline.h> extern struct session *activesession; extern struct listnode *common_actions; extern char vars[10][BUFFER_SIZE]; /* the &0, %1, %2,....%9 variables */ extern int term_echoing; extern int readline_echoing_p; extern int echo; extern char tintin_char; extern int acnum; extern int mesvar[6]; extern char *get_arg_in_braces(); extern struct listnode *search_node_with_wild(); extern struct listnode *searchnode_list(); extern struct listnode *deletenode_list(); extern int case_insensitive; /* @@@added -- perry */ void substitute_vars(); int var_len[10]; char *var_ptr[10]; /***********************/ /* the #action command */ /***********************/ /* Priority code added by Joann Ellsworth 2/2/94 */ void action_command(arg, ses) char *arg; struct session *ses; { char left[BUFFER_SIZE], right[BUFFER_SIZE], result[BUFFER_SIZE]; char pr[BUFFER_SIZE]; struct listnode *myactions, *ln; myactions = (ses) ? ses->actions : common_actions; arg = get_arg_in_braces(arg, left, 0); arg = get_arg_in_braces(arg, right, 1); arg = get_arg_in_braces(arg, pr, 1); if (!*pr) strcpy(pr, "5"); /* defaults priority to 5 if no value given */ if (!*left) { tintin_puts2("#Defined actions:", ses); show_list_action(myactions); prompt(ses); } else if (*left && !*right) { if ((ln = search_node_with_wild(myactions, left)) != NULL) { do { shownode_list(ln); } while ((ln = search_node_with_wild(ln->next, left))); prompt(ses); } else if (mesvar[1]) tintin_puts("#That action is not defined.", ses); } else { if ((ln = searchnode_list(myactions, left)) != NULL) deletenode_list(myactions, ln); insertnode_list(myactions, left, right, pr, PRIORITY); if (mesvar[1]) { sprintf(result, "#Ok. {%s} now triggers {%s} @ {%s}", left, right, pr); tintin_puts2(result, ses); } acnum++; } } /*************************/ /* the #unaction command */ /*************************/ void unaction_command(arg, ses) char *arg; struct session *ses; { char left[BUFFER_SIZE], result[BUFFER_SIZE], buf[8192]; struct listnode *myactions, *ln, *temp; int flag; flag = FALSE; myactions = (ses) ? ses->actions : common_actions; temp = myactions; arg = get_arg_in_braces(arg, left, 1); while ((ln = search_node_with_wild(temp, left)) != NULL) { if (mesvar[1]) { sprintf(result, "#Ok. {%s} is no longer a trigger.", ln->left); tintin_puts2(result, ses); } /* @@@changed -- perry (ln is deleted and free'd by deletenode!!!) deletenode_list(myactions, ln); temp = ln; */ temp = deletenode_list(myactions, ln); flag = TRUE; } if (!flag && mesvar[1]) { sprintf(result, "#No match(es) found for {%s}", left); tintin_puts2(result, ses); } } /**************************************************************************/ /* run throught each of the commands on the right side of an alias/action */ /* expression, call substitute_text() for all commands but #alias/#action */ /**************************************************************************/ void prepare_actionalias(string, result, ses) char *string; char *result; struct session *ses; { char arg[BUFFER_SIZE]; *result = '\0'; substitute_vars(string, arg); substitute_myvars(arg, result, ses); } /*************************************************************************/ /* copy the arg text into the result-space, but substitute the variables */ /* %0..%9 with the real variables */ /*************************************************************************/ void substitute_vars(arg, result) char *arg; char *result; { int nest = 0; int numands, n; char *ptr; while (*arg) { if (*arg == '%') { /* substitute variable */ numands = 0; while (*(arg + numands) == '%') numands++; if (isdigit(*(arg + numands)) && numands == (nest + 1)) { n = *(arg + numands) - '0'; strcpy(result, vars[n]); arg = arg + numands + 1; result += strlen(vars[n]); } else { strncpy(result, arg, numands + 1); arg += numands + 1; result += numands + 1; } } if (*arg == '$') { /* substitute variable */ numands = 0; while (*(arg + numands) == '$') numands++; if (isdigit(*(arg + numands)) && numands == (nest + 1)) { n = *(arg + numands) - '0'; ptr = vars[n]; while (*ptr) { if (*ptr == ';') ptr++; else *result++ = *ptr++; } arg = arg + numands + 1; } else { strncpy(result, arg, numands); arg += numands; result += numands; } } else if (*arg == DEFAULT_OPEN) { nest++; *result++ = *arg++; } else if (*arg == DEFAULT_CLOSE) { nest--; *result++ = *arg++; } else if (*arg == '\\' && nest == 0) { while (*arg == '\\') *result++ = *arg++; if (*arg == '%') { result--; *result++ = *arg++; *result++ = *arg++; } } else *result++ = *arg++; } *result = '\0'; } /**********************************************/ /* check actions from a sessions against line */ /**********************************************/ void check_all_actions(line, ses) char *line; struct session *ses; { struct listnode *ln; static char temp[BUFFER_SIZE] = PROMPT_FOR_PW_TEXT; char strng[BUFFER_SIZE]; if (check_one_action(line, temp, ses) && ses == activesession) { term_echoing = FALSE; readline_echoing_p = 0; /* this tells readline to quit echoing */ } ln = (ses) ? ses->actions : common_actions; while ((ln = ln->next)) { if (check_one_action(line, ln->left, ses)) { char buffer[BUFFER_SIZE]; prepare_actionalias(ln->right, buffer, ses); if (echo && activesession == ses) { sprintf(strng, "[ACTION: %s]", buffer); tintin_puts2(strng, activesession); } parse_input(buffer, ses); return; } } } int match_a_string(line, mask) char *line; char *mask; { char *lptr, *mptr; lptr = line; mptr = mask; while (*lptr && *mptr && !(*mptr == '%' && isdigit(*(mptr + 1)))) { /* @@@changed -- perry */ if (case_insensitive && tolower(*lptr) != tolower(*mptr)) return -1; else if (!case_insensitive && *lptr != *mptr) return -1; lptr++, mptr++; } if (!*mptr || (*mptr == '%' && isdigit(*(mptr + 1)))) return ((int)(lptr - line)); return -1; } int check_one_action(line, action, ses) char *line; char *action; struct session *ses; { int i; if (check_a_action(line, action, ses)) { for (i = 0; i < 10; i++) { if (var_len[i] != -1) { strncpy(vars[i], var_ptr[i], var_len[i]); *(vars[i] + var_len[i]) = '\0'; } } return TRUE; } else return FALSE; } /******************************************************************/ /* check if a text triggers an action and fill into the variables */ /* return TRUE if triggered */ /******************************************************************/ int check_a_action(line, action, ses) char *line; char *action; struct session *ses; { char result[BUFFER_SIZE]; char *temp2, *tptr, *lptr, *lptr2; int i, flag_anchor, count, len, flag; for (i = 0; i < 10; i++) var_len[i] = -1; flag_anchor = FALSE; lptr = line; substitute_myvars(action, result, ses); tptr = result; if (*tptr == '^') { tptr++; flag_anchor = TRUE; /* CHANGED to fix a bug with #action {^%0 foo} * Thanks to Spencer Sun for the bug report (AND fix!) if (*tptr!=*line) return FALSE; */ } if (flag_anchor) { if ((len = match_a_string(lptr, tptr)) == -1) return FALSE; lptr += len; tptr += len; } else { flag = TRUE; len = -1; while (*lptr && flag) { if ((len = match_a_string(lptr, tptr)) != -1) { flag = FALSE; } else lptr++; } if (len != -1) { lptr += len; tptr += len; } else return FALSE; } while (*lptr && *tptr) { temp2 = tptr + 2; if (!*temp2) { var_len[*(tptr + 1) - 48] = strlen(lptr); var_ptr[*(tptr + 1) - 48] = lptr; return TRUE; } lptr2 = lptr; flag = TRUE; len = -1; while (*lptr2 && flag) { if ((len = match_a_string(lptr2, temp2)) != -1) { flag = FALSE; } else lptr2++; } if (len != -1) { var_len[*(tptr + 1) - 48] = lptr2 - lptr; var_ptr[*(tptr + 1) - 48] = lptr; lptr = lptr2 + len; tptr = temp2 + len; } else { return FALSE; } } if (*tptr) return FALSE; else return TRUE; }