void delete_hashlist(struct session *ses, struct hashtable *h, const char *pat, const char *msg_ok, const char *msg_none) { struct listnode *templist; if (is_literal(pat)) { if (delete_hash(h, pat)) { if (msg_ok) tintin_printf(ses, msg_ok, pat); } else { if (msg_none) tintin_printf(ses, msg_none, pat); } return; } templist=hash2list(h, pat); for (struct listnode *ln=templist->next; ln; ln=ln->next) { if (msg_ok) tintin_printf(ses, msg_ok, ln->left); delete_hash(h, ln->left); } if (msg_none && !templist->next) tintin_printf(ses, msg_none, pat); zap_list(templist); }
void alias_command(const char *arg, struct session *ses) { char left[BUFFER_SIZE], right[BUFFER_SIZE], *ch; arg = get_arg_in_braces(arg, left, 0); arg = get_arg_in_braces(arg, right, 1); if (*left && *right) { if ((ch=strchr(left, ' '))) { tintin_eprintf(ses, "#ERROR: aliases cannot contain spaces! Bad alias: {%s}", left); if (ch==left) return; *ch=0; tintin_printf(ses, "#Converted offending alias to {%s}.", left); } set_hash(ses->aliases, left, right); if (ses->mesvar[MSG_ALIAS]) tintin_printf(ses, "#Ok. {%s} aliases {%s}.", left, right); alnum++; return; } show_hashlist(ses, ses->aliases, left, "#Defined aliases:", "#No match(es) found for {%s}."); }
void ticksize_command(const char *arg, struct session *ses) { int x; char left[BUFFER_SIZE], *err; get_arg(arg, left, 1, ses); if (!ses) { tintin_printf(ses, "#NO SESSION ACTIVE => NO TICKER!"); return; } if (!*left || !isadigit(*left)) { tintin_eprintf(ses, "#SYNTAX: #ticksize <number>"); return; } x=strtol(left, &err, 10); if (*err || x<1 || x>=0x7fffffff) { tintin_eprintf(ses, "#TICKSIZE OUT OF RANGE (1..%d)", 0x7fffffff); return; } ses->tick_size = x; ses->time0 = time(NULL); tintin_printf(ses, "#OK. NEW TICKSIZE SET"); }
void pretick_command(const char *arg, struct session *ses) { int x; char left[BUFFER_SIZE], *err; get_arg(arg, left, 1, ses); if (!ses) { tintin_printf(ses, "#NO SESSION ACTIVE => NO TICKER!"); return; } if (!*left) x=ses->pretick? 0 : 10; else { x=strtol(left, &err, 10); if (*err || x<0 || x>=0x7fffffff) { tintin_eprintf(ses, "#PRETICK VALUE OUT OF RANGE (0..%d)", 0x7fffffff); return; } } if (x>=ses->tick_size) { tintin_eprintf(ses, "#PRETICK (%d) has to be smaller than #TICKSIZE (%d)", x, ses->tick_size); return; } ses->pretick = x; ses->time10 = time(NULL); if (x) tintin_printf(ses, "#OK. PRETICK SET TO %d", x); else tintin_printf(ses, "#OK. PRETICK TURNED OFF"); }
void read_complete(const char *arg, struct session *ses) { FILE *myfile; char buffer[BUFFER_SIZE]; bool flag = true; struct completenode *tcomplete, *tcomp2; if (!(complete_head = (struct completenode *)(malloc(sizeof(struct completenode))))) { fprintf(stderr, "couldn't alloc completehead\n"); user_done(); exit(1); } tcomplete = complete_head; if (!(myfile = fopen("tab.txt", "r"))) { if (const char *cptr = getenv("HOME")) { snprintf(buffer, BUFFER_SIZE, "%s/.tab.txt", cptr); myfile = fopen(buffer, "r"); } } if (!myfile) { tintin_eprintf(0, "no tab.txt file, no completion list"); return; } while (fgets(buffer, sizeof(buffer), myfile)) { char *cptr; for (cptr = buffer; *cptr && *cptr != '\n'; cptr++) ; *cptr = '\0'; if (!(tcomp2 = (struct completenode *)(malloc(sizeof(struct completenode))))) { fprintf(stderr, "couldn't alloc completehead\n"); user_done(); exit(1); } if (!(cptr = (char *)(malloc(strlen(buffer) + 1)))) { fprintf(stderr, "couldn't alloc memory for string in complete\n"); user_done(); exit(1); } strcpy(cptr, buffer); tcomp2->strng = cptr; tcomplete->next = tcomp2; tcomplete = tcomp2; } tcomplete->next = NULL; fclose(myfile); tintin_printf(0, "tab.txt file loaded."); tintin_printf(0, ""); }
struct session *connect_session(struct session *ses) { int sock; push_call("connection_session(%p)",ses); ses->connect_retry = utime() + gts->connect_retry; reconnect: sock = connect_mud(ses, ses->host, ses->port); if (sock == -1) { cleanup_session(ses); pop_call(); return NULL; } if (sock) { gtd->ses = ses; ses->socket = sock; ses->connect_retry = 0; SET_BIT(ses->flags, SES_FLAG_CONNECTED); tintin_printf2(ses, ""); tintin_printf(ses, "#SESSION '%s' CONNECTED TO '%s' PORT '%s'", ses->name, ses->host, ses->port); check_all_events(ses, SUB_ARG|SUB_SEC, 0, 4, "SESSION CONNECTED", ses->name, ses->host, ses->ip, ses->port); pop_call(); return ses; } if (ses->connect_retry > utime()) { goto reconnect; } if (ses->connect_error) { tintin_printf(ses, "#SESSION '%s' FAILED TO CONNECT.", ses->name); } cleanup_session(ses); pop_call(); return NULL; }
void show_hashlist(struct session *ses, struct hashtable *h, const char *pat, const char *msg_all, const char *msg_none) { struct listnode *templist; if (!*pat) { tintin_printf(ses, msg_all); templist=hash2list(h, "*"); } else templist=hash2list(h, pat); show_list(templist); if (*pat && !templist->next) tintin_printf(ses, msg_none, pat); zap_list(templist); }
static void telnet_send_naws(struct session *ses) { unsigned char nego[128], *np; #define PUTBYTE(b) if ((b)==255) *np++=255; *np++=(b); np=nego; *np++=IAC; *np++=SB; *np++=NAWS; PUTBYTE(COLS/256); PUTBYTE(COLS%256); PUTBYTE((LINES-1-!!isstatus)/256); PUTBYTE((LINES-1-!!isstatus)%256); *np++=IAC; *np++=SE; write_socket(ses, (char*)nego, np-nego); #ifdef TELNET_DEBUG { char buf[BUFFER_SIZE], *b=buf; int neb=np-nego-2; np=nego+3; b=buf+sprintf(buf, "IAC SB NAWS "); while (np-nego<neb) b+=sprintf(b, "<%u> ", *np++); b+=sprintf(b, "IAC SE"); tintin_printf(ses, "~8~[telnet] sent: %s~-1~", buf); } #endif }
static void show_route(struct session *ses, int a, struct routenode *r) { if (*r->cond) tintin_printf(ses, "~7~{%s~7~}->{%s~7~}: {%s~7~} d=%i if {%s~7~}", ses->locations[a], ses->locations[r->dest], r->path, r->distance, r->cond); else tintin_printf(ses, "~7~{%s~7~}->{%s~7~}: {%s~7~} d=%i", ses->locations[a], ses->locations[r->dest], r->path, r->distance); }
static void telnet_send_ttype(struct session *ses) { char nego[128]; const char *ttype; switch (ses->last_term_type++) { case 0: ttype=TERM; break; case 1: ttype="hardcopy"; break; case 2: ttype="unknown"; break; /* contrary to what zMud does, we cannot claim we're "vt100" or "ansi", */ /* as we obviously lack an addressable cursor */ default: ses->last_term_type=0; case 3: ttype="KBtin-"VERSION; } write_socket(ses, nego, sprintf(nego, "%c%c%c%c%s%c%c", IAC, SB, TERMINAL_TYPE, IS, ttype, IAC, SE)); #ifdef TELNET_DEBUG tintin_printf(ses, "~8~[telnet] sent: IAC SB TERMINAL-TYPE IS \"%s\" IAC SE~-1~", ttype); #endif }
void unantisubstitute_command(const char *arg, struct session *ses) { char left[BUFFER_SIZE]; struct listnode *myantisubs, *ln, *temp; bool flag = false; myantisubs = ses->antisubs; temp = myantisubs; arg = get_arg_in_braces(arg, left, 1); while ((ln = search_node_with_wild(temp, left)) != NULL) { if (ses->mesvar[MSG_SUBSTITUTE]) tintin_printf(ses, "#Ok. Lines with {%s} will now be subbed.", ln->left); deletenode_list(myantisubs, ln); flag = true; } if (!flag && ses->mesvar[MSG_SUBSTITUTE]) tintin_printf(ses, "#THAT ANTISUBSTITUTE (%s) IS NOT DEFINED.", left); }
void pipe_handler(int signal) { restore_terminal(); clean_screen(gtd->ses); tintin_printf(NULL, "broken_pipe: dumping stack"); dump_stack(); }
int connect_mud(struct session *ses, char *host, char *port) { int sock, error; struct addrinfo *address; static struct addrinfo hints; char ip[100]; if (!is_number(port)) { tintin_puts(ses, "#THE PORT SHOULD BE A NUMBER."); return -1; } hints.ai_family = AF_UNSPEC; hints.ai_protocol = IPPROTO_TCP; hints.ai_socktype = SOCK_STREAM; error = getaddrinfo(host, port, &hints, &address); if (error) { tintin_printf(ses, "#SESSION '%s' COULD NOT CONNECT - UNKNOWN HOST.", ses->name); return -1; } sock = socket(address->ai_family, address->ai_socktype, address->ai_protocol); if (sock < 0) { syserr("socket"); } ses->connect_error = connect(sock, address->ai_addr, address->ai_addrlen); if (ses->connect_error) { close(sock); freeaddrinfo(address); return 0; } if (fcntl(sock, F_SETFL, O_NDELAY|O_NONBLOCK) == -1) { perror("connect_mud: fcntl O_NDELAY|O_NONBLOCK"); } getnameinfo(address->ai_addr, address->ai_addrlen, ip, 100, NULL, 0, NI_NUMERICHOST); RESTRING(ses->ip, ip); freeaddrinfo(address); return sock; }
void unroute_command(const char *arg, struct session *ses) { char a[BUFFER_SIZE], b[BUFFER_SIZE]; bool found=false; arg=get_arg(arg, a, 0, ses); arg=get_arg(arg, b, 1, ses); if ((!*a)||(!*b)) { tintin_eprintf(ses, "#SYNTAX: #unroute <from> <to>"); return; } for (int i=0;i<MAX_LOCATIONS;i++) if (ses->locations[i]&&match(a, ses->locations[i])) for (struct routenode**r=&ses->routes[i];*r;) { if (match(b, ses->locations[(*r)->dest])) { struct routenode *p=*r; if (ses->mesvar[MSG_ROUTE]) { tintin_printf(ses, "#Ok. There is no longer a route from {%s~-1~} to {%s~-1~}.", ses->locations[i], ses->locations[p->dest]); } found=true; *r=(*r)->next; SFREE(p->path); SFREE(p->cond); TFREE(p, struct routenode); } else r=&((*r)->next); } if (found) kill_unused_locations(ses); else if (ses->mesvar[MSG_ROUTE]) tintin_printf(ses, "#THAT ROUTE (%s) IS NOT DEFINED.", b); }
void tintin_puts(const char *cptr, struct session *ses) { char line[BUFFER_SIZE]; strcpy(line, cptr); if (ses) { _=line; check_all_actions(line, ses); _=0; } tintin_printf(ses, line); }
struct session *activate_session(struct session *ses) { check_all_events(gtd->ses, SUB_ARG|SUB_SEC, 0, 1, "SESSION DEACTIVATED", gtd->ses->name); gtd->ses = ses; dirty_screen(ses); tintin_printf(ses, "#SESSION '%s' ACTIVATED.", ses->name); check_all_events(ses, SUB_ARG|SUB_SEC, 0, 1, "SESSION ACTIVATED", ses->name); return ses; }
struct session *parse_tintin_command(struct session *ses, char *input) { char line[BUFFER_SIZE]; struct session *sesptr; input = get_arg_stop_spaces(ses, input, line, 0); substitute(ses, line, line, SUB_VAR|SUB_FUN); if (is_number(line)) { int cnt = atoi(line); input = get_arg_in_braces(ses, input, line, TRUE); while (cnt-- > 0) { ses = script_driver(ses, -1, line); } return ses; } for (sesptr = gts ; sesptr ; sesptr = sesptr->next) { if (!strcmp(sesptr->name, line)) { if (*input) { input = get_arg_in_braces(ses, input, line, TRUE); substitute(ses, line, line, SUB_VAR|SUB_FUN); script_driver(sesptr, -1, line); return ses; } else { return activate_session(sesptr); } } } tintin_printf(ses, "#ERROR: #UNKNOWN TINTIN-COMMAND '%s'.", line); return ses; }
void antisubstitute_command(const char *arg, struct session *ses) { char left[BUFFER_SIZE]; struct listnode *myantisubs, *ln; myantisubs = ses->antisubs; arg = get_arg_in_braces(arg, left, 1); if (!*left) { tintin_puts("#THESE ANTISUBSTITUTES HAS BEEN DEFINED:", ses); show_list(myantisubs); } else { if ((ln = searchnode_list(myantisubs, left)) != NULL) deletenode_list(myantisubs, ln); insertnode_list(myantisubs, left, left, 0, ALPHA); antisubnum++; if (ses->mesvar[MSG_SUBSTITUTE]) tintin_printf(ses, "Ok. Any line with {%s} will not be subbed.", left); } }
void cleanup_session(struct session *ses) { push_call("cleanup_session(%p)",ses); if (HAS_BIT(ses->flags, SES_FLAG_CLOSED)) { tintin_printf2(NULL, "\n#SESSION '%s' IS ALREADY CLOSED.", ses->name); dump_stack(); pop_call(); return; } if (ses == gtd->update) { gtd->update = ses->next; } UNLINK(ses, gts->next, gts->prev); if (ses->socket) { if (close(ses->socket) == -1) { syserr("close in cleanup"); } // the PID is stored in the session's port. if (HAS_BIT(ses->flags, SES_FLAG_RUN)) { kill(atoi(ses->port), SIGKILL); } } SET_BIT(ses->flags, SES_FLAG_CLOSED); if (HAS_BIT(ses->flags, SES_FLAG_CONNECTED)) { check_all_events(ses, SUB_ARG|SUB_SEC, 0, 4, "SESSION DISCONNECTED", ses->name, ses->host, ses->ip, ses->port); tintin_printf(gtd->ses, "#SESSION '%s' DIED.", ses->name); } else { check_all_events(ses, SUB_ARG|SUB_SEC, 0, 4, "SESSION TIMED OUT", ses->name, ses->host, ses->ip, ses->port); tintin_printf(gtd->ses, "#SESSION '%s' TIMED OUT.", ses->name); } if (ses == gtd->ses) { gtd->ses = newactive_session(); } if (ses->logfile) { fclose(ses->logfile); } if (ses->logline) { fclose(ses->logline); } LINK(ses, gtd->dispose_next, gtd->dispose_prev); pop_call(); return; }
void goto_command(const char *arg, struct session *ses) { char A[BUFFER_SIZE], B[BUFFER_SIZE], tmp[BUFFER_SIZE], cond[BUFFER_SIZE]; int a, b, i, j, s; int d[MAX_LOCATIONS], ok[MAX_LOCATIONS], way[MAX_LOCATIONS]; char *path[MAX_LOCATIONS], *locs[MAX_LOCATIONS]; arg=get_arg(arg, A, 0, ses); arg=get_arg(arg, B, 1, ses); if ((!*A)||(!*B)) { tintin_eprintf(ses, "#SYNTAX: #goto <from> <to>"); return; } for (a=0;a<MAX_LOCATIONS;a++) if (ses->locations[a]&&!strcmp(ses->locations[a], A)) break; if (a==MAX_LOCATIONS) { tintin_eprintf(ses, "#Location not found: [%s]", A); return; } for (b=0;b<MAX_LOCATIONS;b++) if (ses->locations[b]&&!strcmp(ses->locations[b], B)) break; if (b==MAX_LOCATIONS) { tintin_eprintf(ses, "#Location not found: [%s]", B); return; } for (i=0;i<MAX_LOCATIONS;i++) { d[i]=INF; ok[i]=0; } d[a]=0; do { s=INF; for (j=0;j<MAX_LOCATIONS;j++) if (!ok[j]&&(d[j]<s)) s=d[i=j]; if (s==INF) { tintin_eprintf(ses, "#No route from %s to %s!", A, B); return; } ok[i]=1; for (struct routenode *r=ses->routes[i];r;r=r->next) if (d[r->dest]>s+r->distance) { if (!*(r->cond)) goto good; substitute_vars(r->cond, tmp); substitute_myvars(tmp, cond, ses); if (eval_expression(cond, ses)) { good: d[r->dest]=s+r->distance; way[r->dest]=i; } } } while (!ok[b]); j=0; for (i=b;i!=a;i=way[i]) d[j++]=i; for (d[i=j]=a;i>0;i--) { locs[i]=mystrdup(ses->locations[d[i]]); for (struct routenode *r=ses->routes[d[i]];r;r=r->next) if (r->dest==d[i-1]) path[i]=mystrdup(r->path); } /* we need to copy all used route data (paths and location names) because of ugly bad users who can use #unroute in the middle of a #go command */ locs[0]=mystrdup(ses->locations[b]); for (i=j;i>0;i--) { if (ses->mesvar[MSG_GOTO]) { tintin_printf(ses, "#going from %s to %s", locs[i], locs[i-1]); } parse_input(path[i], true, ses); } for (i=j;i>=0;i--) SFREE(locs[i]); for (i=j;i>0;i--) SFREE(path[i]); set_variable("loc", B, ses); }
struct session *new_session(struct session *ses, char *name, char *arg, int desc) { int cnt = 0; char host[BUFFER_SIZE], port[BUFFER_SIZE], file[BUFFER_SIZE]; struct session *newsession; push_call("new_session(%p,%p,%p,%d)",ses,name,arg,desc); if (HAS_BIT(gtd->flags, TINTIN_FLAG_TERMINATE)) { pop_call(); return ses; } arg = sub_arg_in_braces(ses, arg, host, GET_ONE, SUB_VAR|SUB_FUN); arg = sub_arg_in_braces(ses, arg, port, GET_ONE, SUB_VAR|SUB_FUN); arg = sub_arg_in_braces(ses, arg, file, GET_ONE, SUB_VAR|SUB_FUN); if (desc == 0) { if (*host == 0) { tintin_puts(ses, "#HEY! SPECIFY AN ADDRESS WILL YOU?"); pop_call(); return ses; } if (*port == 0) { tintin_puts(ses, "#HEY! SPECIFY A PORT NUMBER WILL YOU?"); pop_call(); return ses; } } for (newsession = gts ; newsession ; newsession = newsession->next) { if (!strcmp(newsession->name, name)) { tintin_puts(ses, "THERE'S A SESSION WITH THAT NAME ALREADY."); pop_call(); return ses; } } newsession = (struct session *) calloc(1, sizeof(struct session)); newsession->name = strdup(name); newsession->host = strdup(host); newsession->ip = strdup(""); newsession->port = strdup(port); newsession->group = strdup(gts->group); newsession->flags = gts->flags; newsession->telopts = gts->telopts; newsession->auto_tab = gts->auto_tab; newsession->cmd_color = strdup(gts->cmd_color); newsession->read_max = gts->read_max; newsession->read_buf = (unsigned char *) calloc(1, gts->read_max); LINK(newsession, gts->next, gts->prev); for (cnt = 0 ; cnt < LIST_MAX ; cnt++) { newsession->list[cnt] = copy_list(newsession, gts->list[cnt], cnt); } newsession->rows = gts->rows; newsession->cols = gts->cols; newsession->top_row = gts->top_row; newsession->bot_row = gts->bot_row; init_buffer(newsession, gts->scroll_max); if (desc) { tintin_printf(ses, "#TRYING TO LAUNCH '%s' RUNNING '%s'.", newsession->name, newsession->host); } else { tintin_printf(ses, "#TRYING TO CONNECT '%s' TO '%s' PORT '%s'.", newsession->name, newsession->host, newsession->port); } gtd->ses = newsession; dirty_screen(newsession); if (desc == 0) { newsession = connect_session(newsession); } else { SET_BIT(newsession->flags, SES_FLAG_CONNECTED|SES_FLAG_RUN); SET_BIT(newsession->telopts, TELOPT_FLAG_SGA); DEL_BIT(newsession->telopts, TELOPT_FLAG_ECHO); gtd->ses = newsession; gtd->ses->socket = desc; } if (newsession) { if (*file) { do_read(newsession, file); } } pop_call(); return gtd->ses; }
void help_command(const char *arg, struct session *ses) { FILE *myfile=NULL; char text[BUFFER_SIZE], line[BUFFER_SIZE], filestring[BUFFER_SIZE]; if (strcmp(DEFAULT_FILE_DIR, "HOME")) { sprintf(filestring, "%s/KBtin_help", DEFAULT_FILE_DIR); myfile = check_file(filestring); } #ifdef DATA_PATH if (!myfile) { sprintf(filestring, "%s/KBtin_help", DATA_PATH); myfile = check_file(filestring); } #endif if (!myfile) { sprintf(filestring, "%s_help", tintin_exec); myfile = check_file(filestring); } if (!myfile) { sprintf(filestring, "%s/KBtin_help", getenv("HOME")); myfile = check_file(filestring); } if (!myfile) { tintin_eprintf(0, "#Help file not found - no help available."); tintin_eprintf(0, "#Locations checked:"); if (strcmp(DEFAULT_FILE_DIR, "HOME")) tintin_eprintf(0, "# %s/KBtin_help%s", DEFAULT_FILE_DIR, COMPRESSION_EXT); #ifdef DATA_PATH tintin_eprintf(0, "# %s/KBtin_help%s", DATA_PATH, COMPRESSION_EXT); #endif tintin_eprintf(0, "# %s_help%s", tintin_exec, COMPRESSION_EXT); tintin_eprintf(0, "# %s/KBtin_help%s", getenv("HOME"), COMPRESSION_EXT); return; } if (*arg==tintin_char) arg++; if (*arg) { sprintf(text, "~%s", arg); while (fgets(line, sizeof(line), myfile)) { if (*line == '~') { if (*(line + 1) == '*') break; if (is_abrev(text, line)) { while (fgets(line, sizeof(line), myfile)) { if ((*line == '~')&&(*(line+1)=='~')) goto end; else { *(line + strlen(line) - 1) = '\0'; if (*line!='~') tintin_printf(0, "%s", line); } } } } } } else { while (fgets(line, sizeof(line), myfile)) { if ((*line == '~')&&(*(line+1)=='~')) goto end; else { *(line + strlen(line) - 1) = '\0'; if (*line!='~') tintin_printf(0, "%s", line); } } } tintin_printf(0, "#Sorry, no help on that word."); end: fclose(myfile); }
static void apply_options(void) { char temp[BUFFER_SIZE], sname[BUFFER_SIZE]; char ustr[BUFFER_SIZE]; const char *home; FILE *f; # define DO_INPUT(str,iv) local_to_utf8(ustr, str, BUFFER_SIZE, 0);\ activesession=parse_input(str, iv, activesession); for (struct listnode *opt=options->next; opt; opt=opt->next) { switch (*opt->left) { case '#': *opt->left=tintin_char; activesession=parse_input(opt->left, true, activesession); break; case 'c': DO_INPUT(opt->right, false); break; case 'r': set_magic_hook(activesession); make_name(sname, opt->right); snprintf(temp, BUFFER_SIZE, "%crun %.*s {%s}", tintin_char, MAX_SESNAME_LENGTH, sname, opt->right); DO_INPUT(temp, true); break; case 's': set_magic_hook(activesession); make_name(sname, opt->right); snprintf(temp, BUFFER_SIZE, "%cses %.*s {%s %s}", tintin_char, MAX_SESNAME_LENGTH, sname, opt->right, opt->pr); DO_INPUT(temp, true); break; case 'S': set_magic_hook(activesession); make_name(sname, opt->right); snprintf(temp, BUFFER_SIZE, "%csslses %.*s {%s %s}", tintin_char, MAX_SESNAME_LENGTH, sname, opt->right, opt->pr); DO_INPUT(temp, true); break; case ' ': local_to_utf8(ustr, opt->right, BUFFER_SIZE, 0); if ((f=fopen(opt->right, "r"))) { if (activesession->verbose || !real_quiet) tintin_printf(0, "#READING {%s}", ustr); activesession = do_read(f, ustr, activesession); } else tintin_eprintf(0, "#FILE NOT FOUND: {%s}", ustr); break; case '-': if (!strcmp(DEFAULT_FILE_DIR, "HOME")) if ((home = getenv("HOME"))) strcpy(temp, home); else *temp = '\0'; else strcpy(temp, DEFAULT_FILE_DIR); strcat(temp, "/.tintinrc"); local_to_utf8(ustr, temp, BUFFER_SIZE, 0); if ((f=fopen(temp, "r"))) activesession = do_read(f, ustr, activesession); else if ((home = getenv("HOME"))) { strcpy(temp, home); strcat(temp, "/.tintinrc"); local_to_utf8(ustr, temp, BUFFER_SIZE, 0); if ((f=fopen(temp, "r"))) activesession = do_read(f, ustr, activesession); } } } kill_list(options); }
void dogoto_command(const char *arg, struct session *ses) { char A[BUFFER_SIZE], B[BUFFER_SIZE], distvar[BUFFER_SIZE], locvar[BUFFER_SIZE], pathvar[BUFFER_SIZE]; char left[BUFFER_SIZE], right[BUFFER_SIZE], tmp[BUFFER_SIZE], cond[BUFFER_SIZE]; int a, b, i, j, s; int d[MAX_LOCATIONS], ok[MAX_LOCATIONS], way[MAX_LOCATIONS]; char path[BUFFER_SIZE], *pptr; arg=get_arg(arg, A, 0, ses); arg=get_arg(arg, B, 0, ses); arg=get_arg(arg, distvar, 0, ses); arg=get_arg(arg, locvar, 0, ses); arg=get_arg(arg, pathvar, 0, ses); if ((!*A)||(!*B)) { tintin_eprintf(ses, "#SYNTAX: #dogoto <from> <to> [<distvar> [<locvar> [<pathvar>]]] [#else ...]"); return; } bool flag=*distvar||*locvar||*pathvar; for (a=0;a<MAX_LOCATIONS;a++) if (ses->locations[a]&&!strcmp(ses->locations[a], A)) break; if (a==MAX_LOCATIONS) goto not_found; for (b=0;b<MAX_LOCATIONS;b++) if (ses->locations[b]&&!strcmp(ses->locations[b], B)) break; if (b==MAX_LOCATIONS) goto not_found; for (i=0;i<MAX_LOCATIONS;i++) { d[i]=INF; ok[i]=0; } d[a]=0; do { s=INF; for (j=0;j<MAX_LOCATIONS;j++) if (!ok[j]&&(d[j]<s)) s=d[i=j]; if (s==INF) goto not_found; ok[i]=1; for (struct routenode *r=ses->routes[i];r;r=r->next) if (d[r->dest]>s+r->distance) { if (!*(r->cond)) goto good; substitute_vars(r->cond, tmp); substitute_myvars(tmp, cond, ses); if (eval_expression(cond, ses)) { good: d[r->dest]=s+r->distance; way[r->dest]=i; } } } while (!ok[b]); sprintf(tmp, "%d", d[b]); if (*distvar) set_variable(distvar, tmp, ses); j=0; for (i=b;i!=a;i=way[i]) d[j++]=i; d[j]=a; pptr=path; for (i=j;i>=0;i--) pptr+=snprintf(pptr, path-pptr+BUFFER_SIZE, " %s", ses->locations[d[i]]); pptr=path+(pptr!=path); if (*locvar) set_variable(locvar, pptr, ses); pptr=path; for (i=j;i>0;i--) { for (struct routenode *r=ses->routes[d[i]];r;r=r->next) if (r->dest==d[i-1]) { if (flag) pptr+=snprintf(pptr, path-pptr+BUFFER_SIZE, " {%s}", r->path); else { tintin_printf(ses, "%-10s>%-10s {%s}", ses->locations[d[i]], ses->locations[d[i-1]], r->path); } } } pptr=path+(pptr!=path); if (*pathvar) set_variable(pathvar, pptr, ses); return; not_found: arg=get_arg_in_braces(arg, left, 0); if (*left == tintin_char) { if (is_abrev(left + 1, "else")) { get_arg_in_braces(arg, right, 1); parse_input(right, true, ses); return; } if (is_abrev(left + 1, "elif")) { if_command(arg, ses); return; } } if (*left) tintin_eprintf(ses, "#ERROR: cruft after #dogoto: {%s}", left); if (!flag) tintin_printf(ses, "No paths from %s to %s found.", A, B); }
void route_command(const char *arg, struct session *ses) { char a[BUFFER_SIZE], b[BUFFER_SIZE], way[BUFFER_SIZE], dist[BUFFER_SIZE], cond[BUFFER_SIZE]; int j, d; arg=get_arg(arg, a, 0, ses); arg=get_arg(arg, b, 0, ses); arg=get_arg_in_braces(arg, way, 0); arg=get_arg(arg, dist, 0, ses); arg=get_arg_in_braces(arg, cond, 1); if (!*a) { tintin_printf(ses, "#THESE ROUTES HAVE BEEN DEFINED:"); for (int i=0;i<MAX_LOCATIONS;i++) for (struct routenode *r=ses->routes[i];r;r=r->next) show_route(ses, i, r); return; } if (!*way) { bool first=true; if (!*b) strcpy(b, "*"); for (int i=0;i<MAX_LOCATIONS;i++) if (ses->locations[i]&&match(a, ses->locations[i])) for (struct routenode *r=ses->routes[i];r;r=r->next) if (ses->locations[i]&& match(b, ses->locations[r->dest])) { if (first) { tintin_printf(ses, "#THESE ROUTES HAVE BEEN DEFINED:"); first=false; } show_route(ses, i, r); } if (first) tintin_printf(ses, "#THAT ROUTE (%s) IS NOT DEFINED.", b); return; } int i; for (i=0;i<MAX_LOCATIONS;i++) if (ses->locations[i]&&!strcmp(ses->locations[i], a)) goto found_i; if (i==MAX_LOCATIONS) { for (i=0;i<MAX_LOCATIONS;i++) if (!ses->locations[i]) { ses->locations[i]=mystrdup(a); goto found_i; } tintin_eprintf(ses, "#TOO MANY LOCATIONS!"); return; } found_i: for (j=0;j<MAX_LOCATIONS;j++) if (ses->locations[j]&&!strcmp(ses->locations[j], b)) goto found_j; if (j==MAX_LOCATIONS) { for (j=0;j<MAX_LOCATIONS;j++) if (!ses->locations[j]) { ses->locations[j]=mystrdup(b); goto found_j; } tintin_eprintf(ses, "#TOO MANY LOCATIONS!"); kill_unused_locations(ses); return; } found_j: if (*dist) { char *err; d=strtol(dist, &err, 0); if (*err) { tintin_eprintf(ses, "#Hey! Route length has to be a number! Got {%s}.", arg); kill_unused_locations(ses); return; } if ((d<0)&&(ses->mesvar[MSG_ROUTE]||ses->mesvar[MSG_ERROR])) tintin_eprintf(ses, "#Error: distance cannot be negative!"); } else d=DEFAULT_ROUTE_DISTANCE; addroute(ses, i, j, way, d, cond); if (ses->mesvar[MSG_ROUTE]) { if (*cond) tintin_printf(ses, "#Ok. Way from {%s} to {%s} is now set to {%s} (distance=%i) condition:{%s}", ses->locations[i], ses->locations[j], way, d, cond); else tintin_printf(ses, "#Ok. Way from {%s} to {%s} is now set to {%s} (distance=%i)", ses->locations[i], ses->locations[j], way, d); } routnum++; }
int do_telnet_protocol(const char *data, int nb, struct session *ses) { const unsigned char *cp = (const unsigned char*)data+1; unsigned char wt; unsigned char answer[3]; unsigned char nego[128], *np; #define NEXTCH cp++; \ if (cp-(unsigned char*)data>=nb) \ return -1; if (nb<2) return -1; switch (*cp) { case WILL: case WONT: case DO: case DONT: if (nb<3) return -1; wt=*(cp++); #ifdef TELNET_DEBUG tintin_printf(ses, "~8~[telnet] received: IAC %s <%u> (%s)~-1~", will_names[wt-251], *cp, (*cp<sizeof(option_names)/sizeof(char*))? option_names[*cp]:"?"); #endif answer[0]=IAC; answer[2]=*cp; switch (*cp) { case ECHO: switch (wt) { case WILL: answer[1]=DO; ses->server_echo=1; break; case DO: answer[1]=WONT; break; case WONT: answer[1]=DONT; ses->server_echo=2; break; case DONT: answer[1]=WONT; break; } break; case TERMINAL_TYPE: switch (wt) { case WILL: answer[1]=DONT; break; case DO: answer[1]=WILL; break; case WONT: answer[1]=DONT; break; case DONT: answer[1]=WONT; break; } break; case NAWS: switch (wt) { case WILL: answer[1]=DO; ses->naws=false; break; case DO: answer[1]=WILL; ses->naws=(LINES>1 && COLS>0); break; case WONT: answer[1]=DONT; ses->naws=false; break; case DONT: answer[1]=WONT; ses->naws=false; break; } break; case END_OF_RECORD: switch (wt) { case WILL: answer[1]=DO; break; case DO: answer[1]=WONT; break; case WONT: answer[1]=DONT; break; case DONT: answer[1]=WONT; break; } break; #ifdef HAVE_ZLIB case COMPRESS2: switch (wt) { case WILL: answer[1]=DO; ses->can_mccp=time(0)-ses->sessionstart<60; break; case DO: answer[1]=WONT; break; case WONT: answer[1]=DONT; ses->can_mccp=false; break; case DONT: answer[1]=WONT; break; } break; #endif default: switch (wt) { case WILL: answer[1]=DONT; break; case DO: answer[1]=WONT; break; case WONT: answer[1]=DONT; break; case DONT: answer[1]=WONT; break; } } write_socket(ses, (char*)answer, 3); #ifdef TELNET_DEBUG tintin_printf(ses, "~8~[telnet] sent: IAC %s <%u> (%s)~-1~", will_names[answer[1]-251], *cp, (*cp<sizeof(option_names)/sizeof(char*))? option_names[*cp]:"?"); #endif if (*cp==NAWS) telnet_send_naws(ses); return 3; case SB: np=nego; sbloop: NEXTCH; while (*cp!=IAC) { if (np-nego>MAX_SUBNEGO_LENGTH) goto nego_too_long; *np++=*cp; NEXTCH; } NEXTCH; if (*cp==IAC) { if (np-nego>MAX_SUBNEGO_LENGTH) goto nego_too_long; *np++=IAC; goto sbloop; } if (*cp!=SE) { if (np-nego>MAX_SUBNEGO_LENGTH) goto nego_too_long; *np++=*cp; goto sbloop; } nb=cp-(unsigned char*)data; #ifdef TELNET_DEBUG { char buf[BUFFER_SIZE], *b=buf; unsigned int neb=np-nego; np=nego; b=buf+sprintf(buf, "IAC SB "); switch (*np) { case TERMINAL_TYPE: b+=sprintf(b, "TERMINAL-TYPE "); if (*++np==SEND) { b+=sprintf(b, "SEND "); ++np; } break; case COMPRESS2: b+=sprintf(b, "COMPRESS2 "); np++; } while (np-nego<neb) b+=sprintf(b, "<%u> ", *np++); b+=sprintf(b, "IAC SE"); tintin_printf(ses, "~8~[telnet] received: %s~-1~", buf); } #endif switch (*(np=nego)) { case TERMINAL_TYPE: if (*(np+1)==SEND) telnet_send_ttype(ses); break; #ifdef HAVE_ZLIB case COMPRESS2: if (ses->can_mccp) return -4; /* compressed data immediately follows, we need to return */ #endif } return nb+1; case GA: case EOR: #ifdef TELNET_DEBUG tintin_printf(ses, "~8~[telnet] received: IAC %s~-1~", (*cp==GA)?"GA":"EOR"); #endif ses->gas=true; return -2; case IAC: /* IAC IAC is the escape for literal 255 byte */ return -3; default: /* other 2-byte command, ignore */ #ifdef TELNET_DEBUG tintin_printf(ses, "~8~[telnet] received: IAC <%u>~-1~", *cp&255); #endif return 2; } /* not reached */ return cp-(unsigned char*)data; nego_too_long: tintin_eprintf(ses, "#error: unterminated TELNET subnegotiation received."); return 2; /* we leave everything but IAC SB */ }
int main(int argc, char **argv) { tintin_exec=argv[0]; init_locale(); user_setdriver(isatty(0)?1:0); parse_options(argc, argv); init_bind(); hist_num=-1; init_parse(); strcpy(status, EMPTY_LINE); user_init(); /* read_complete(); no tab-completion */ srand((getpid()*0x10001)^time0); lastdraft=0; if (ui_own_output || tty) { /* Legal crap does _not_ belong here. Anyone interested in the license can check the files accompanying KBtin, without any need of being spammed every time. It is not GNU bc or something similar, we don't want half a screenful of all-uppercase (cAPS kEY IS STUCK AGAIN?) text that no one ever wants to read -- that is what docs are for. */ tintin_printf(0, "~2~##########################################################"); tintin_printf(0, "#~7~ ~12~K B ~3~t i n~7~ v %-25s ~2~#", VERSION); tintin_printf(0, "# #"); tintin_printf(0, "#~7~ current developer: ~9~Adam Borowski ([email protected]~7~) ~2~#"); tintin_printf(0, "# #"); tintin_printf(0, "#~7~ based on ~12~tintin++~7~ v 2.1.9 by Peter Unold, Bill Reiss, ~2~#"); tintin_printf(0, "#~7~ David A. Wagner, Joann Ellsworth, Jeremy C. Jack, ~2~#"); tintin_printf(0, "#~7~ Ulan@GrimneMUD and Jakub Narębski ~2~#"); tintin_printf(0, "##########################################################~7~"); tintin_printf(0, "~15~#session <name> <host> <port> ~7~to connect to a remote server"); tintin_printf(0, " ~8~#ses t2t t2tmud.org 9999"); tintin_printf(0, "~15~#run <name> <command> ~7~to run a local command"); tintin_printf(0, " ~8~#run advent adventure"); tintin_printf(0, " ~8~#run sql mysql"); tintin_printf(0, "~15~#help ~7~to get the help index"); } user_mark_greeting(); setup_signals(); #ifdef PROFILING setup_prof(); #endif PROF("initializing"); setup_ulimit(); init_nullses(); PROF("other"); apply_options(); tintin(); return 0; }
int main(int argc, char **argv) { int greeting = TRUE; #ifdef SOCKS SOCKSinit(argv[0]); #endif if (signal(SIGTERM, trap_handler) == BADSIG) { syserr("signal SIGTERM"); } if (signal(SIGSEGV, trap_handler) == BADSIG) { syserr("signal SIGSEGV"); } if (signal(SIGHUP, trap_handler) == BADSIG) { syserr("signal SIGHUP"); } if (signal(SIGABRT, abort_handler) == BADSIG) { syserr("signal SIGTERM"); } if (signal(SIGINT, abort_handler) == BADSIG) { syserr("signal SIGINT"); } if (signal(SIGTSTP, suspend_handler) == BADSIG) { syserr("signal SIGSTOP"); } if (signal(SIGPIPE, pipe_handler) == BADSIG) { syserr("signal SIGPIPE"); } if (signal(SIGWINCH, winch_handler) == BADSIG) { syserr("signal SIGWINCH"); } /* if (getenv("HOME") != NULL) { char filename[256]; sprintf(filename, "%s/%s", getenv("HOME"), HISTORY_FILE); read_history(gts, filename); } */ srand(time(NULL)); if (argc > 1) { int c; while ((c = getopt(argc, argv, "e: G h r: s: t: v")) != EOF) { if (c == 'G') { greeting = FALSE; } } optind = 1; } init_tintin(greeting); if (argc > 1) { int c; optind = 1; while ((c = getopt(argc, argv, "e: G h r: s: t: v")) != EOF) { switch (c) { case 'e': gtd->ses = script_driver(gtd->ses, -1, optarg); break; case 'G': break; case 'h': tintin_printf(NULL, "Usage: %s [OPTION]... [FILE]...", argv[0]); tintin_printf(NULL, ""); tintin_printf(NULL, " -e Execute given command."); tintin_printf(NULL, " -G Don't show the greeting screen."); tintin_printf(NULL, " -h This help section."); tintin_printf(NULL, " -r Read given file."); tintin_printf(NULL, " -t Set given title."); tintin_printf(NULL, " -v Enable verbose mode."); restore_terminal(); exit(1); break; case 'r': gtd->ses = do_read(gtd->ses, optarg); break; case 't': printf("\033]0;%s\007", optarg); break; case 's': srand((unsigned int) atoll(optarg)); break; case 'v': do_configure(gtd->ses, "{VERBOSE} {ON}"); break; default: tintin_printf(NULL, "Unknown option '%c'.", c); break; } } if (argv[optind] != NULL) { gtd->ses = do_read(gtd->ses, argv[optind]); } } check_all_events(gts, SUB_ARG|SUB_SEC, 0, 2, "PROGRAM START", CLIENT_NAME, CLIENT_VERSION); check_all_events(gts, SUB_ARG|SUB_SEC, 0, 2, "SCREEN RESIZE", ntos(gts->cols), ntos(gts->rows)); mainloop(); return 0; }