#include "prims.h" #include "externs.h" #include "version.h" #include "mush.h" #include <fcntl.h> #include <sys/stat.h> /* private globals */ extern inst *p_oper1, *p_oper2, *p_oper3, *p_oper4; static inst temp1, temp2; extern int p_result; extern char p_buf[BUFFER_LEN]; static char *string; extern int p_nargs; void prims_stringcmp (__P_PROTO) { CHECKOP(2); p_oper1 = POP(); p_oper2 = POP(); if (p_oper1->type != PROG_STRING || p_oper2->type != PROG_STRING) abort_interp("Non-string argument."); p_result = string_compare(p_oper2->data.string ? p_oper2->data.string : "", p_oper1->data.string ? p_oper1->data.string : ""); CLEAR(p_oper1); CLEAR(p_oper2); push(arg, top, PROG_INTEGER, MIPSCAST &p_result); } void prims_stringncmp (__P_PROTO) { CHECKOP(3); p_oper1 = POP(); p_oper2 = POP(); p_oper3 = POP(); if (p_oper1->type != PROG_INTEGER) abort_interp("Non-integer argument."); if (p_oper2->type != PROG_STRING || p_oper3->type != PROG_STRING) abort_interp("Non-string argument."); p_result = stringn_compare(p_oper3->data.string ? p_oper3->data.string : "", p_oper2->data.string ? p_oper2->data.string : "", p_oper1->data.number); CLEAR(p_oper1); CLEAR(p_oper2); CLEAR(p_oper3); push(arg, top, PROG_INTEGER, MIPSCAST &p_result); } void prims_strcmp(__P_PROTO) { p_oper1 = POP(); p_oper2 = POP(); if (p_oper1->type != PROG_STRING || p_oper2->type != PROG_STRING) abort_interp("Non-string argument."); p_result = strcmp(p_oper2->data.string ? p_oper2->data.string : "", p_oper1->data.string ? p_oper1->data.string : ""); CLEAR(p_oper1); CLEAR(p_oper2); push(arg, top, PROG_INTEGER, MIPSCAST &p_result); } void prims_strncmp(__P_PROTO) { p_oper1 = POP(); p_oper2 = POP(); p_oper3 = POP(); if (p_oper1->type != PROG_INTEGER) abort_interp("Non-integer argument."); if (p_oper2->type != PROG_STRING || p_oper3->type != PROG_STRING) abort_interp("Non-string argument."); p_result = strncmp(p_oper3->data.string ? p_oper3->data.string : "", p_oper2->data.string ? p_oper2->data.string : "", p_oper1->data.number); CLEAR(p_oper1); CLEAR(p_oper2); CLEAR(p_oper3); push(arg, top, PROG_INTEGER, MIPSCAST &p_result); } void prims_strcut (__P_PROTO) { CHECKOP(2); temp1 = *(p_oper1 = POP()); temp2 = *(p_oper2 = POP()); if (temp1.type != PROG_INTEGER) abort_interp("Non-integer argument (2)"); if (temp1.data.number < 0) abort_interp("Argument must be a positive integer."); if (temp2.type != PROG_STRING) abort_interp("Non-string argument (1)"); if (!temp2.data.string) { push(arg, top, PROG_STRING, 0); push(arg, top, PROG_STRING, 0); } else { if (temp1.data.number > strlen(temp2.data.string)) { push(arg, top, PROG_STRING, MIPSCAST dup_string(temp2.data.string)); push(arg, top, PROG_STRING, 0); } else { strncpy(p_buf, temp2.data.string, temp1.data.number); p_buf[temp1.data.number] = '\0'; push(arg, top, PROG_STRING, MIPSCAST dup_string(p_buf)); if (strlen(temp2.data.string) > temp1.data.number) { strncpy(p_buf, temp2.data.string + temp1.data.number, strlen(temp2.data.string) - temp1.data.number + 1); push(arg, top, PROG_STRING, MIPSCAST dup_string(p_buf)); } else { push(arg, top, PROG_STRING, 0); } } } CLEAR(&temp2); } void prims_strlen (__P_PROTO) { CHECKOP(1); p_oper1 = POP(); if (p_oper1->type != PROG_STRING) abort_interp("Non-string argument."); if (!p_oper1->data.string) p_result = 0; else p_result = strlen(p_oper1->data.string); CLEAR(p_oper1); push(arg, top, PROG_INTEGER, MIPSCAST &p_result); } void prims_strcat (__P_PROTO) { CHECKOP(2); p_oper1 = POP(); p_oper2 = POP(); if (p_oper1->type != PROG_STRING || p_oper2->type != PROG_STRING) abort_interp("Non-string argument."); if (!p_oper1->data.string && !p_oper2->data.string) string = NULL; else if (!p_oper2->data.string) string = dup_string(p_oper1->data.string); else if (!p_oper1->data.string) string = dup_string(p_oper2->data.string); else if (strlen(p_oper1->data.string) + strlen(p_oper2->data.string) > (BUFFER_LEN) - 1) { abort_interp("Operation would p_result in overflow."); } else { strncpy(p_buf, p_oper2->data.string, strlen(p_oper2->data.string)); strncpy(p_buf + strlen(p_oper2->data.string), p_oper1->data.string, strlen(p_oper1->data.string) + 1); string = dup_string(p_buf); } CLEAR(p_oper1); CLEAR(p_oper2); push(arg, top, PROG_STRING, MIPSCAST string); } void prims_explode (__P_PROTO) { int i; char *delimit; CHECKOP(2); temp1 = *(p_oper1 = POP()); temp2 = *(p_oper2 = POP()); if (temp1.type != PROG_STRING) abort_interp("Non-string argument (2)"); if (temp2.type != PROG_STRING) abort_interp("Non-string argument (1)"); if (!temp1.data.string) abort_interp("Empty string argument (2)"); delimit = temp1.data.string; if (!temp2.data.string) { p_result = 1; CLEAR(&temp1); CLEAR(&temp2); push(arg, top, PROG_STRING, 0); push(arg, top, PROG_INTEGER, MIPSCAST &p_result); return; } else { p_result = 0; strncpy(p_buf, temp2.data.string, strlen(temp2.data.string) + 1); for (i = strlen(temp2.data.string) - 1; i >= 0; i--) { if (!strncmp(p_buf + i, delimit, strlen(temp1.data.string))) { p_buf[i] = '\0'; if (*top >= STACK_SIZE) abort_interp("Stack Overflow."); push(arg, top, PROG_STRING, MIPSCAST dup_string(p_buf + i + strlen(temp1.data.string))); p_result++; } } if (*top >= STACK_SIZE) abort_interp("Stack Overflow."); push(arg, top, PROG_STRING, MIPSCAST dup_string(p_buf)); p_result++; } if (*top >= STACK_SIZE) abort_interp("Stack Overflow."); CLEAR(&temp1); CLEAR(&temp2); push(arg, top, PROG_INTEGER, MIPSCAST &p_result); } void prims_subst (__P_PROTO) { int i = 0, j = 0; char *match, *replacement; char xp_buf[BUFFER_LEN]; CHECKOP(3); p_oper1 = POP(); p_oper2 = POP(); p_oper3 = POP(); if (!p_oper1->data.string) abort_interp("Empty string argument (3)"); if (p_oper1->type != PROG_STRING) abort_interp("Non-string argument (3)"); if (p_oper2->type != PROG_STRING) abort_interp("Non-string argument (2)"); if (p_oper3->type != PROG_STRING) abort_interp("Non-string argument (1)"); p_buf[0] = '\0'; if (p_oper3->data.string) { strncpy(xp_buf, p_oper3->data.string, strlen(p_oper3->data.string) + 1); match = p_oper1->data.string; replacement = DoNullInd(p_oper2->data.string); while (xp_buf[i]) { if (!strncmp(xp_buf + i, match, strlen(p_oper1->data.string))) { strcat(p_buf, replacement); i += strlen(p_oper1->data.string); j += *replacement ? strlen(p_oper2->data.string) : 0; } else { p_buf[j++] = xp_buf[i++]; p_buf[j] = '\0'; } } } CLEAR(p_oper1); CLEAR(p_oper2); CLEAR(p_oper3); push(arg, top, PROG_STRING, MIPSCAST dup_string(p_buf)); } void prims_instr (__P_PROTO) { char *remaining, *match; CHECKOP(2); p_oper1 = POP(); p_oper2 = POP(); if (p_oper1->type != PROG_STRING) abort_interp("Invalid argument type (2)"); if(!(p_oper1->data.string)) abort_interp("Empty string argument (2)"); if (p_oper2->type != PROG_STRING) abort_interp("Non-string argument (1)"); if (!p_oper2->data.string) p_result = 0; else { remaining = p_oper2->data.string; match = p_oper1->data.string; p_result = 0; do { if (!strncmp(remaining, match, strlen(p_oper1->data.string))) { p_result = remaining - p_oper2->data.string + 1; break; } remaining++; } while (remaining >= p_oper2->data.string && *remaining); } CLEAR(p_oper1); CLEAR(p_oper2); push(arg, top, PROG_INTEGER, MIPSCAST &p_result); } void prims_rinstr (__P_PROTO) { char *remaining, *match; CHECKOP(2); p_oper1 = POP(); p_oper2 = POP(); if (p_oper1->type != PROG_STRING) abort_interp("Invalid argument type (2)"); if(!(p_oper1->data.string)) abort_interp("Empty string argument (2)"); if (p_oper2->type != PROG_STRING) abort_interp("Non-string argument (1)"); if (!p_oper2->data.string) p_result = 0; else { remaining = p_oper2->data.string + strlen(p_oper2->data.string) - 1; match = p_oper1->data.string; p_result = 0; do { if (!strncmp(remaining, match, strlen(p_oper1->data.string))) { p_result = remaining - p_oper2->data.string + 1; break; } remaining--; } while (remaining >= p_oper2->data.string && *remaining); } CLEAR(p_oper1); CLEAR(p_oper2); push(arg, top, PROG_INTEGER, MIPSCAST &p_result); } void prims_pronoun_sub (__P_PROTO) { CHECKOP(2); p_oper1 = POP(); p_oper2 = POP(); /* p_oper1 is a string, p_oper2 a dbref */ if (!valid_object(p_oper2)) abort_interp("Invalid argument (1)"); if (p_oper1->type != PROG_STRING) abort_interp("Invalid argument (2)"); if(p_oper1->data.string) strcpy(p_buf, p_oper1->data.string); CLEAR(p_oper1); CLEAR(p_oper2); push(arg, top, PROG_STRING, (p_oper1->data.string) ? MIPSCAST dup_string(pronoun_substitute(p_oper2->data.objref, p_buf)) : 0); } void prims_toupper (__P_PROTO) { CHECKOP(1); p_oper1 = POP(); if (p_oper1->type != PROG_STRING) abort_interp("Non-string argument."); if (p_oper1->data.string) { strncpy(p_buf, p_oper1->data.string, strlen(p_oper1->data.string) + 1); upperstring(p_buf); } else { p_buf[0] = '\0'; } CLEAR(p_oper1); push(arg, top, PROG_STRING, MIPSCAST dup_string(p_buf)); } void prims_tolower (__P_PROTO) { CHECKOP(1); p_oper1 = POP(); if (p_oper1->type != PROG_STRING) abort_interp("Non-string argument."); if (p_oper1->data.string) { strncpy(p_buf, p_oper1->data.string, strlen(p_oper1->data.string) + 1); lowerstring(p_buf); } else { p_buf[0] = '\0'; } CLEAR(p_oper1); push(arg, top, PROG_STRING, MIPSCAST dup_string(p_buf)); } void prims_flagstr (__P_PROTO) { dbref object; CHECKOP(1); p_oper1 = POP(); if (!valid_object(p_oper1)) abort_interp("Non-object argument."); object = p_oper1->data.objref; strcpy(p_buf, (unparse_flags(object))); CLEAR(p_oper1); push(arg, top, PROG_STRING, MIPSCAST dup_string(p_buf)); } void prims_caps (__P_PROTO) { CHECKOP(1); p_oper1 = POP(); if (p_oper1->type != PROG_STRING) abort_interp("Non-string argument."); if (!p_oper1->data.string) abort_interp("NULL string argument."); strncpy(p_buf, p_oper1->data.string, strlen(p_oper1->data.string) + 1); lowerstring(p_buf); p_buf[0]= toupper(p_buf[0]); CLEAR(p_oper1); push(arg, top, PROG_STRING, MIPSCAST dup_string(p_buf)); } void prims_unparse_lock(__P_PROTO) { CHECKOP(1); p_oper1 = POP(); if (!valid_object(p_oper1)) abort_interp("Non-object argument."); sprintf(p_buf, "%s", unparse_boolexp(player, DBFETCH(p_oper1->data.objref)->key)); CLEAR(p_oper1); push(arg, top, PROG_STRING, MIPSCAST dup_string(p_buf)); } void prims_unparse_flags(__P_PROTO) { dbref object; CHECKOP(1); p_oper1 = POP(); if (!valid_object(p_oper1)) abort_interp("Non-object argument."); object = p_oper1->data.objref; strcpy(p_buf, (flag_description(object))); CLEAR(p_oper1); push(arg, top, PROG_STRING, MIPSCAST dup_string(p_buf)); } void prims_wstrcmp(__P_PROTO) { char buf2[BUFFER_LEN]; CHECKOP(2); p_oper1 = POP(); p_oper2 = POP(); if (p_oper1->type != PROG_STRING) abort_interp("Non-string argument."); if (p_oper2->type != PROG_STRING) abort_interp("Non-string argument."); if((!p_oper1->data.string) || (!p_oper2->data.string)) abort_interp("NULL string argument."); strncpy(p_buf, p_oper2->data.string, strlen(p_oper2->data.string) + 1); strncpy(buf2, p_oper1->data.string, strlen(p_oper1->data.string) + 1); p_result=(wild_match(buf2,p_buf)); CLEAR(p_oper1); CLEAR(p_oper2); push(arg, top, PROG_INTEGER, MIPSCAST &p_result); } void prims_spitfile(__P_PROTO) { FILE *f; /* OK, this one is easy. Taken from spitfile in help.c */ char buf2[BUFFER_LEN], filename[BUFFER_LEN];; CHECKOP(1); p_oper1 = POP(); if (p_oper1->type != PROG_STRING) abort_interp("Non-string argument."); if (!p_oper1->data.string) abort_interp("NULL string argument."); strncpy(filename, p_oper1->data.string, strlen(p_oper1->data.string) + 1); if(file_ok(filename)==0) abort_interp("Sorry, you may not access MUF text files with a '.' or '~'."); sprintf(buf2, "%s%s", MUF_DIR, filename); if((f = fopen(buf2, "r")) == NULL) { fclose(f); abort_interp("Non-existant text file."); } if((filesize_ok(buf2)) == 0) { fclose(f); abort_interp("File size is larger then MAX_OUTPUT"); } while(fgets(p_buf, sizeof p_buf, f)) { p_buf[(strlen(p_buf)-1)] = '\0'; notify(player, player, p_buf); } fclose(f); CLEAR(p_oper1); } void prims_notifyfile(__P_PROTO) { FILE *f; char buf2[BUFFER_LEN], filename[BUFFER_LEN]; CHECKOP(3); p_oper1 = POP(); p_oper2 = POP(); p_oper3 = POP(); if (!valid_object(p_oper3) || Typeof(p_oper3->data.number) != TYPE_ROOM) abort_interp("Non-room argument (1)"); if (p_oper2->type != PROG_OBJECT) abort_interp("Invalid object argument (2)"); if (p_oper1->type != PROG_STRING) abort_interp("Non-string argument (3)"); if (!p_oper1->data.string) abort_interp("NULL string argument."); strncpy(filename, p_oper1->data.string, strlen(p_oper1->data.string) + 1); if(file_ok(filename)==0) abort_interp("Sorry, you may not access MUF text files with a '.' or '~'."); sprintf(buf2, "%s%s", MUF_DIR, filename); if((f = fopen(buf2, "r")) == NULL) { fclose(f); abort_interp("Non-existant text file."); } if((filesize_ok(buf2)) == 0) { fclose(f); abort_interp("File size is larger then MAX_OUTPUT"); } while(fgets(p_buf, sizeof p_buf, f)) { p_buf[(strlen(p_buf)-1)] = '\0'; notify_except(player, p_oper3->data.objref, p_oper2->data.objref, p_buf); } fclose(f); CLEAR(p_oper1); CLEAR(p_oper2); CLEAR(p_oper3); } void prims_touchfile(__P_PROTO) { FILE *f; char filename[BUFFER_LEN]; CHECKOP(1); p_oper1 = POP(); if (p_oper1->type != PROG_STRING) abort_interp("Non-string argument."); if (!p_oper1->data.string) abort_interp("NULL string argument."); strncpy(filename, p_oper1->data.string, strlen(p_oper1->data.string) + 1); if(file_ok(filename)==0) abort_interp("Sorry, you may not access MUF text files with a '.' or '~'."); sprintf(p_buf, "%s%s", MUF_DIR, filename); if((f = fopen(p_buf, "r")) != NULL) p_result=1; else p_result=0; push(arg, top, PROG_INTEGER, MIPSCAST &p_result); fclose(f); CLEAR(p_oper1); } int file_ok(char *string) { if (index(string,'.') == NULL && index(string,'~') == NULL) return (1); else return (0); } int filesize_ok(char *filename) { int desn; struct stat stats; if((desn = open(filename, O_RDONLY )) < 0) { close(desn); return (0); } fstat(desn,&stats); close(desn); if(stats.st_size > (MAX_OUTPUT - 350)) return (0); else return (1); } void prims_mushfunctions(__P_PROTO) { #ifdef MUSH char tbuf[BUFFER_LEN]; char *t; CHECKOP(1); p_oper1 = POP(); if (p_oper1->type != PROG_STRING) abort_interp("Non-string argument."); if(!p_oper1->data.string) abort_interp("NULL string argument."); strncpy(tbuf, p_oper1->data.string, strlen(p_oper1->data.string) + 1); t = exec(fr->euid, tbuf, player, EV_STRIP | EV_FCHECK); strcpy(p_buf, t); CLEAR(p_oper1); if(t) free(t); push(arg, top, PROG_STRING, MIPSCAST dup_string(p_buf)); #else abort_interp("THIS FUNCTION WAS NOT ENABLED BY YOUR GAME ADMIN."); #endif } void prims_re_compile (__P_PROTO) { #ifndef REGEXP abort_interp("This prim not enabled."); #else regexp *re; CHECKOP(1); p_oper1 = POP(); if (p_oper1->type != PROG_STRING) abort_interp("Non-string argument."); re = m_regcomp(DoNullInd(p_oper1->data.string)); if (! re) abort_interp(m_regerror()); CLEAR(p_oper1); push(arg, top, PROG_RE,MIPSCAST re); #endif } void prims_re_match (__P_PROTO) { #ifndef REGEXP abort_interp("This prim not enabled."); #else regexp *re; char *str; int rv; char *err; int i; CHECKOP(2); temp2 = *(p_oper2 = POP()); temp1 = *(p_oper1 = POP()); if (temp1.type != PROG_STRING) abort_interp("Non-string argument (1)."); if (temp2.type != PROG_RE) abort_interp("Non-regexp argument (2)."); str = (char *) DoNullInd(temp1.data.string); re = temp2.data.re; rv = m_regexec(re,str); err = m_regerror(); if (err) abort_interp(err); if (rv) { for (i=0;i<re->nsubexp;i++) { if (re->startp[i]) { rv = re->endp[i] - re->startp[i]; if (rv == 0) push(arg, top, PROG_STRING, 0); else { bcopy(re->startp[i],&buf[0],rv); buf[rv] = '\0'; push(arg, top, PROG_STRING, dup_string(&buf[0])); } } else { rv = 0; push(arg, top, PROG_INTEGER, MIPSCAST &rv); } } rv = re->nsubexp; push(arg, top, PROG_INTEGER, MIPSCAST &rv); } else { rv = 0; push(arg, top, PROG_INTEGER, MIPSCAST &rv); } CLEAR(&temp1); CLEAR(&temp2); #endif } void prims_stringpfx(__P_PROTO) { CHECKOP(2); p_oper1 = POP(); p_oper2 = POP(); if (p_oper1->type != PROG_STRING || p_oper2->type != PROG_STRING) abort_interp("Non-string argument."); if (!p_oper1->data.string || !p_oper2->data.string) abort_interp("NULL string argument."); if (p_oper1->data.string == p_oper2->data.string) p_result = 0; else if (!(p_oper2->data.string && p_oper1->data.string)) p_result = p_oper1->data.string ? -1 : 1; else p_result = string_prefix(p_oper2->data.string, p_oper1->data.string); CLEAR(p_oper1); CLEAR(p_oper2); push(arg, top, PROG_INTEGER, MIPSCAST &p_result); } void prims_striplead(__P_PROTO) { /* string -- string' */ CHECKOP(1); p_oper1 = POP(); if (p_oper1->type != PROG_STRING) abort_interp("Not a string argument."); if (*top >= STACK_SIZE) abort_interp("Stack Overflow."); strcpy(p_buf, DoNullInd(p_oper1->data.string)); for (string = p_buf; *string && isspace(*string); string++); CLEAR(p_oper1); push(arg, top, PROG_STRING, MIPSCAST dup_string(string)); } void prims_striptail(__P_PROTO) { /* string -- string' */ CHECKOP(1); p_oper1 = POP(); if (p_oper1->type != PROG_STRING) abort_interp("Not a string argument."); if (*top >= STACK_SIZE) abort_interp("Stack Overflow."); strcpy(p_buf, DoNullInd(p_oper1->data.string)); p_result = strlen(p_buf); while ((p_result-- > 0) && isspace(p_buf[p_result])) p_buf[p_result] = '\0'; CLEAR(p_oper1); push(arg, top, PROG_STRING, MIPSCAST dup_string(p_buf)); } void prims_smatch(__P_PROTO) { char xbuf[BUFFER_LEN]; CHECKOP(2); p_oper1 = POP(); p_oper2 = POP(); if (p_oper1->type != PROG_STRING || p_oper2->type != PROG_STRING) abort_interp("Non-string argument."); if (!p_oper1->data.string || !p_oper2->data.string) abort_interp("Null string argument."); strcpy(p_buf, p_oper1->data.string); strcpy(xbuf, p_oper2->data.string); CLEAR(p_oper1); CLEAR(p_oper2); p_result = equalstr(p_buf, xbuf); push(arg, top, PROG_INTEGER, MIPSCAST &p_result); } void prims_version(__P_PROTO) { push(arg, top, PROG_STRING, MIPSCAST dup_string(VERSION)); if (*top >= STACK_SIZE) abort_interp("Stack Overflow."); } void prims_unparseobj(__P_PROTO) { CHECKOP(1); p_oper1 = POP(); if (p_oper1->type != PROG_OBJECT) abort_interp("Non-object argument."); p_result = p_oper1->data.objref; switch (p_result) { case NOTHING: sprintf(p_buf, "*NOTHING*"); break; case HOME: sprintf(p_buf, "*HOME*"); break; default: if (p_result < 0 || p_result > db_top) sprintf(p_buf, "*INVALID*"); else sprintf(p_buf, "%s", unparse_object(fr->euid, p_result)); } CLEAR(p_oper1); push(arg, top, PROG_STRING, MIPSCAST dup_string(p_buf)); } void prims_spitline(__P_PROTO) { FILE *f; char buf2[BUFFER_LEN], filename[BUFFER_LEN]; int i = 1; CHECKOP(2); p_oper1 = POP(); p_oper2 = POP(); if (p_oper1->type != PROG_INTEGER) abort_interp("Non-integer argument."); if (p_oper1->data.number < 1) abort_interp("Invalid line number."); if (p_oper2->type != PROG_STRING) abort_interp("Non-string argument."); if (!p_oper2->data.string) abort_interp("NULL argument."); strncpy(filename, p_oper2->data.string, strlen(p_oper2->data.string) + 1); if(file_ok(filename)==0) abort_interp("Sorry, you may not access MUF text files with a '.' or '~'."); sprintf(buf2, "%s%s", MUF_DIR, filename); if((f = fopen(buf2, "r")) == NULL) { fclose(f); abort_interp("Non-existant text file."); } while(fgets(p_buf, sizeof p_buf, f)) { fprintf(stderr, "TOKE:%s", p_buf); if( p_oper1->data.number == i) { fprintf(stderr, "STRING:%s", p_buf); p_buf[(strlen(p_buf)-1)] = '\0'; i = 0; break; } i++; } fclose(f); fprintf(stderr, "PRE:%s\n", p_buf); if (i) string = NULL; else string = dup_string(p_buf); fprintf(stderr, "POST:%s\n", p_buf); push(arg, top, PROG_STRING, MIPSCAST string); CLEAR(p_oper2); }