#include "config.h" #include <math.h> #include <ctype.h> #include "params.h" #include "db.h" #include "tune.h" #include "mpi.h" #include "externs.h" #include "props.h" #include "match.h" #include "interp.h" #include "interface.h" #include "msgparse.h" /***** Insert MFUNs here *****/ const char * mfn_owner(MFUNARGS) { dbref obj; obj = mesg_dbref_raw(descr, player, what, perms, argv[0]); if (obj == AMBIGUOUS || obj == NOTHING || obj == UNKNOWN) ABORT_MPI("OWNER", "Failed match."); if (obj == PERMDENIED) ABORT_MPI("OWNER", "Permission denied."); if (obj == HOME) obj = PLAYER_HOME(player); return ref2str(OWNER(obj), buf, BUFFER_LEN); } const char * mfn_controls(MFUNARGS) { dbref obj; dbref obj2; obj = mesg_dbref_raw(descr, player, what, perms, argv[0]); if (obj == AMBIGUOUS || obj == NOTHING || obj == UNKNOWN) ABORT_MPI("CONTROLS", "Match failed. (arg1)"); if (obj == PERMDENIED) ABORT_MPI("CONTROLS", "Permission denied. (arg1)"); if (obj == HOME) obj = PLAYER_HOME(player); if (argc > 1) { obj2 = mesg_dbref_raw(descr, player, what, perms, argv[1]); if (obj2 == AMBIGUOUS || obj2 == NOTHING || obj2 == UNKNOWN) ABORT_MPI("CONTROLS", "Match failed. (arg2)"); if (obj2 == PERMDENIED) ABORT_MPI("CONTROLS", "Permission denied. (arg2)"); if (obj2 == HOME) obj2 = PLAYER_HOME(player); if (Typeof(obj2) != TYPE_PLAYER) obj2 = OWNER(obj2); } else { obj2 = OWNER(perms); } if (controls(obj2, obj)) { return "1"; } else { return "0"; } } const char * mfn_links(MFUNARGS) { char buf2[BUFFER_LEN]; dbref obj; int i, cnt; obj = mesg_dbref(descr, player, what, perms, argv[0], mesgtyp); if (obj == AMBIGUOUS || obj == UNKNOWN || obj == NOTHING || obj == HOME) ABORT_MPI("LINKS", "Match failed."); if (obj == PERMDENIED) ABORT_MPI("LINKS", "Permission denied."); switch (Typeof(obj)) { case TYPE_ROOM: obj = DBFETCH(obj)->sp.room.dropto; break; case TYPE_PLAYER: obj = PLAYER_HOME(obj); break; case TYPE_THING: obj = THING_HOME(obj); break; case TYPE_EXIT: *buf = '\0'; cnt = DBFETCH(obj)->sp.exit.ndest; if (cnt) { dbref obj2; for (i = 0; i < cnt; i++) { obj2 = DBFETCH(obj)->sp.exit.dest[i]; ref2str(obj2, buf2, sizeof(buf2)); if (strlen(buf) + strlen(buf2) + 2 < BUFFER_LEN) { if (*buf) strcatn(buf, BUFFER_LEN, "\r"); strcatn(buf, BUFFER_LEN, buf2); } } return buf; } else { return "#-1"; } break; case TYPE_PROGRAM: default: return "#-1"; break; } return ref2str(obj, buf, BUFFER_LEN); } const char * mfn_locked(MFUNARGS) { dbref who = mesg_dbref_local(descr, player, what, perms, argv[0], mesgtyp); dbref obj = mesg_dbref_local(descr, player, what, perms, argv[1], mesgtyp); if (who == AMBIGUOUS || who == UNKNOWN || who == NOTHING || who == HOME) ABORT_MPI("LOCKED", "Match failed. (arg1)"); if (who == PERMDENIED) ABORT_MPI("LOCKED", "Permission denied. (arg1)"); if (obj == AMBIGUOUS || obj == UNKNOWN || obj == NOTHING || obj == HOME) ABORT_MPI("LOCKED", "Match failed. (arg2)"); if (obj == PERMDENIED) ABORT_MPI("LOCKED", "Permission denied. (arg2)"); snprintf(buf, BUFFER_LEN, "%d", !could_doit(descr, who, obj)); return buf; } const char * mfn_testlock(MFUNARGS) { struct boolexp *lok; dbref who = player; dbref obj = mesg_dbref_local(descr, player, what, perms, argv[0], mesgtyp); if (argc > 2) who = mesg_dbref_local(descr, player, what, perms, argv[2], mesgtyp); if (who == AMBIGUOUS || who == UNKNOWN || who == NOTHING || who == HOME) ABORT_MPI("TESTLOCK", "Match failed. (arg1)"); if (who == PERMDENIED) ABORT_MPI("TESTLOCK", "Permission denied. (arg1)"); if (obj == AMBIGUOUS || obj == UNKNOWN || obj == NOTHING || obj == HOME) ABORT_MPI("TESTLOCK", "Match failed. (arg2)"); if (obj == PERMDENIED) ABORT_MPI("TESTLOCK", "Permission denied. (arg2)"); if (Prop_System(argv[1])) ABORT_MPI("TESTLOCK", "Permission denied. (arg2)"); if (!(mesgtyp & MPI_ISBLESSED)) { if (Prop_Hidden(argv[1])) ABORT_MPI("TESTLOCK", "Permission denied. (arg2)"); if (Prop_Private(argv[1]) && OWNER(perms) != OWNER(what)) ABORT_MPI("TESTLOCK", "Permission denied. (arg2)"); } lok = get_property_lock(obj, argv[1]); if (argc > 3 && lok == TRUE_BOOLEXP) return (argv[3]); if (eval_boolexp(descr, who, lok, obj)) { return "1"; } else { return "0"; } } const char * mfn_contents(MFUNARGS) { char buf2[50]; int list_limit = MAX_MFUN_LIST_LEN; dbref obj = mesg_dbref_local(descr, player, what, perms, argv[0], mesgtyp); int typchk, ownroom; int outlen, nextlen; if (obj == AMBIGUOUS || obj == UNKNOWN || obj == NOTHING || obj == HOME) ABORT_MPI("CONTENTS", "Match failed."); if (obj == PERMDENIED) ABORT_MPI("CONTENTS", "Permission denied."); typchk = NOTYPE; if (argc > 1) { if (!string_compare(argv[1], "Room")) { typchk = TYPE_ROOM; } else if (!string_compare(argv[1], "Exit")) { typchk = TYPE_EXIT; /* won't find any, though */ } else if (!string_compare(argv[1], "Player")) { typchk = TYPE_PLAYER; } else if (!string_compare(argv[1], "Program")) { typchk = TYPE_PROGRAM; } else if (!string_compare(argv[1], "Thing")) { typchk = TYPE_THING; } else { ABORT_MPI("CONTENTS", "Type must be 'player', 'room', 'thing', 'program', or 'exit'. (arg2)."); } } strcpy(buf, ""); outlen = 0; ownroom = controls(perms, obj); obj = DBFETCH(obj)->contents; while (obj != NOTHING && list_limit) { if ((typchk == NOTYPE || Typeof(obj) == typchk) && (ownroom || controls(perms, obj) || !((FLAGS(obj) & DARK) || (FLAGS(getloc(obj)) & DARK) || (Typeof(obj) == TYPE_PROGRAM && !(FLAGS(obj) & LINK_OK)))) && !(Typeof(obj) == TYPE_ROOM && typchk != TYPE_ROOM)) { ref2str(obj, buf2, sizeof(buf2)); nextlen = strlen(buf2); if ((outlen + nextlen) >= (BUFFER_LEN - 3)) break; if (outlen) { strcatn(buf + outlen, BUFFER_LEN - outlen, "\r"); outlen++; } strcatn((buf + outlen), BUFFER_LEN - outlen, buf2); outlen += nextlen; list_limit--; } obj = DBFETCH(obj)->next; } return buf; } const char * mfn_exits(MFUNARGS) { int outlen, nextlen; char buf2[50]; int list_limit = MAX_MFUN_LIST_LEN; dbref obj = mesg_dbref(descr, player, what, perms, argv[0], mesgtyp); if (obj == AMBIGUOUS || obj == UNKNOWN || obj == NOTHING || obj == HOME) ABORT_MPI("EXITS", "Match failed."); if (obj == PERMDENIED) ABORT_MPI("EXITS", "Permission denied."); switch (Typeof(obj)) { case TYPE_ROOM: case TYPE_THING: case TYPE_PLAYER: obj = DBFETCH(obj)->exits; break; default: obj = NOTHING; break; } *buf = '\0'; outlen = 0; while (obj != NOTHING && list_limit) { ref2str(obj, buf2, sizeof(buf2)); nextlen = strlen(buf2); if ((outlen + nextlen) >= (BUFFER_LEN - 3)) break; if (outlen) { strcatn(buf + outlen, BUFFER_LEN - outlen, "\r"); outlen++; } strcatn((buf + outlen), BUFFER_LEN - outlen, buf2); outlen += nextlen; list_limit--; obj = DBFETCH(obj)->next; } return buf; } const char * mfn_v(MFUNARGS) { char *ptr = get_mvar(argv[0]); if (!ptr) ABORT_MPI("V", "No such variable defined."); return ptr; } const char * mfn_set(MFUNARGS) { char *ptr = get_mvar(argv[0]); if (!ptr) ABORT_MPI("SET", "No such variable currently defined."); strcpy(ptr, argv[1]); return ptr; } const char * mfn_ref(MFUNARGS) { dbref obj; char *p; for (p = argv[0]; *p && isspace(*p); p++) ; if (*p == NUMBER_TOKEN && number(p + 1)) { obj = atoi(p + 1); } else { obj = mesg_dbref_local(descr, player, what, perms, argv[0], mesgtyp); if (obj == PERMDENIED) ABORT_MPI("REF", "Permission denied."); if (obj == UNKNOWN) obj = NOTHING; } snprintf(buf, BUFFER_LEN, "#%d", obj); return buf; } const char * mfn_name(MFUNARGS) { char *ptr; dbref obj = mesg_dbref_raw(descr, player, what, perms, argv[0]); if (obj == UNKNOWN) ABORT_MPI("NAME", "Match failed."); if (obj == PERMDENIED) ABORT_MPI("NAME", "Permission denied."); if (obj == NOTHING) { strcpy(buf, "#NOTHING#"); return buf; } if (obj == AMBIGUOUS) { strcpy(buf, "#AMBIGUOUS#"); return buf; } if (obj == HOME) { strcpy(buf, "#HOME#"); return buf; } strcpy(buf, RNAME(obj)); if (Typeof(obj) == TYPE_EXIT) { ptr = index(buf, ';'); if (ptr) *ptr = '\0'; } return buf; } const char * mfn_fullname(MFUNARGS) { dbref obj = mesg_dbref_raw(descr, player, what, perms, argv[0]); if (obj == UNKNOWN) ABORT_MPI("NAME", "Match failed."); if (obj == PERMDENIED) ABORT_MPI("NAME", "Permission denied."); if (obj == NOTHING) { strcpy(buf, "#NOTHING#"); return buf; } if (obj == AMBIGUOUS) { strcpy(buf, "#AMBIGUOUS#"); return buf; } if (obj == HOME) { strcpy(buf, "#HOME#"); return buf; } strcpy(buf, RNAME(obj)); return buf; } int countlitems(char *list, char *sep) { char *ptr; int seplen; int count = 1; if (!list || !*list) return 0; seplen = strlen(sep); ptr = list; while (*ptr) { while (*ptr && strncmp(ptr, sep, seplen)) ptr++; if (*ptr) { ptr += seplen; count++; } } return count; } /* buf is outbut buffer. list is list to take item from. * line is list line to take. */ char * getlitem(char *buf, char *list, char *sep, int line) { char *ptr, *ptr2; char tmpchr; int seplen; seplen = strlen(sep); ptr = ptr2 = list; while (*ptr && line--) { for (ptr2 = ptr; *ptr2 && strncmp(ptr2, sep, seplen); ptr2++) ; if (!line) break; if (*ptr2) { ptr2 += seplen; } ptr = ptr2; } tmpchr = *ptr2; *ptr2 = '\0'; strcpy(buf, ptr); *ptr2 = tmpchr; return buf; } const char * mfn_sublist(MFUNARGS) { char *ptr; char sepbuf[BUFFER_LEN]; char buf2[BUFFER_LEN]; int count = 1; int which; int end; int incr = 1; int i; int pflag; if (argc > 1) { which = atoi(argv[1]); } else { strcpy(buf, argv[0]); return buf; } strcpy(sepbuf, "\r"); if (argc > 3) { if (!*argv[3]) ABORT_MPI("SUBLIST", "Can't use null seperator string."); strcpy(sepbuf, argv[3]); } count = countlitems(argv[0], sepbuf); /* count of items in list */ if (which == 0) return ""; if (which > count) which = count; if (which < 0) which += count + 1; if (which < 1) which = 1; end = which; if (argc > 2) { end = atoi(argv[2]); } if (end == 0) return ""; if (end > count) end = count; if (end < 0) end += count + 1; if (end < 1) end = 1; if (end < which) { incr = -1; } *buf = '\0'; pflag = 0; for (i = which; ((i <= end) && (incr == 1)) || ((i >= end) && (incr == -1)); i += incr) { if (pflag) { strcatn(buf, BUFFER_LEN, sepbuf); } else { pflag++; } ptr = getlitem(buf2, argv[0], sepbuf, i); strcatn(buf, BUFFER_LEN, ptr); } return buf; } const char * mfn_lrand(MFUNARGS) { /* {lrand:list,sep} */ char sepbuf[BUFFER_LEN]; int count = 1; int which = 0; strcpy(sepbuf, "\r"); if (argc > 1) { if (!*argv[1]) ABORT_MPI("LRAND", "Can't use null seperator string."); strcpy(sepbuf, argv[1]); } count = countlitems(argv[0], sepbuf); if (count) { which = ((RANDOM() / 256) % count) + 1; getlitem(buf, argv[0], sepbuf, which); } else { *buf = '\0'; } return buf; } const char * mfn_count(MFUNARGS) { strcpy(buf, "\r"); if (argc > 1) { if (!*argv[1]) ABORT_MPI("COUNT", "Can't use null seperator string."); strcpy(buf, argv[1]); } snprintf(buf, BUFFER_LEN, "%d", countlitems(argv[0], buf)); return buf; } const char * mfn_with(MFUNARGS) { char namebuf[BUFFER_LEN]; char cmdbuf[BUFFER_LEN]; char vbuf[BUFFER_LEN]; char *ptr, *valptr; int v, cnt; ptr = MesgParse(argv[0], namebuf); CHECKRETURN(ptr, "WITH", "arg 1"); valptr = MesgParse(argv[1], vbuf); CHECKRETURN(valptr, "WITH", "arg 2"); v = new_mvar(ptr, vbuf); if (v == 1) ABORT_MPI("WITH", "Variable name too long."); if (v == 2) ABORT_MPI("WITH", "Too many variables already defined."); *buf = '\0'; for (cnt = 2; cnt < argc; cnt++) { ptr = MesgParse(argv[cnt], cmdbuf); if (!ptr) { snprintf(buf, BUFFER_LEN, "%s %cWITH%c (arg %d)", get_mvar("how"), MFUN_LEADCHAR, MFUN_ARGEND, cnt); notify(player, buf); return NULL; } } free_top_mvar(); return ptr; } const char * mfn_fold(MFUNARGS) { int iter_limit = MAX_MFUN_LIST_LEN; char varname[BUFFER_LEN]; char sepinbuf[BUFFER_LEN]; char listbuf[BUFFER_LEN]; char tmp[BUFFER_LEN]; char tmp2[BUFFER_LEN]; char *ptr, *ptr2; char *sepin = argv[4]; int seplen, v; ptr = MesgParse(argv[0], varname); CHECKRETURN(ptr, "FOLD", "arg 1"); v = new_mvar(ptr, tmp); if (v == 1) ABORT_MPI("FOLD", "Variable name too long."); if (v == 2) ABORT_MPI("FOLD", "Too many variables already defined."); ptr = MesgParse(argv[1], varname); CHECKRETURN(ptr, "FOLD", "arg 2"); v = new_mvar(ptr, tmp2); if (v == 1) ABORT_MPI("FOLD", "Variable name too long."); if (v == 2) ABORT_MPI("FOLD", "Too many variables already defined."); if (argc > 4) { ptr = MesgParse(sepin, sepinbuf); CHECKRETURN(ptr, "FOLD", "arg 5"); if (!*ptr) ABORT_MPI("FOLD", "Can't use Null seperator string"); sepin = sepinbuf; } else { sepin = sepinbuf; strcpy(sepin, "\r"); } seplen = strlen(sepin); ptr = MesgParse(argv[2], listbuf); CHECKRETURN(ptr, "FOLD", "arg 3"); for (ptr2 = ptr; *ptr2 && strncmp(ptr2, sepin, seplen); ptr2++) ; if (*ptr2) { *ptr2 = '\0'; ptr2 += seplen; } strcpy(buf, ptr); ptr = ptr2; while (*ptr) { for (ptr2 = ptr; *ptr2 && strncmp(ptr2, sepin, seplen); ptr2++) ; if (*ptr2) { *ptr2 = '\0'; ptr2 += seplen; } strcpy(tmp2, ptr); strcpy(tmp, buf); MesgParse(argv[3], buf); CHECKRETURN(ptr, "FOLD", "arg 4"); ptr = ptr2; if (!(--iter_limit)) ABORT_MPI("FOLD", "Iteration limit exceeded"); } free_top_mvar(); free_top_mvar(); return buf; } const char * mfn_for(MFUNARGS) { int iter_limit = MAX_MFUN_LIST_LEN; char scratch[BUFFER_LEN]; char tmp[BUFFER_LEN]; char *ptr, *dptr; int v, i, start, end, incr; ptr = MesgParse(argv[0], scratch); CHECKRETURN(ptr, "FOR", "arg 1 (varname)"); v = new_mvar(ptr, tmp); if (v == 1) ABORT_MPI("FOR", "Variable name too long."); if (v == 2) ABORT_MPI("FOR", "Too many variables already defined."); dptr = MesgParse(argv[1], scratch); CHECKRETURN(dptr, "FOR", "arg 2 (start num)"); start = atoi(dptr); dptr = MesgParse(argv[2], scratch); CHECKRETURN(dptr, "FOR", "arg 3 (end num)"); end = atoi(dptr); dptr = MesgParse(argv[3], scratch); CHECKRETURN(dptr, "FOR", "arg 4 (increment)"); incr = atoi(dptr); *buf = '\0'; for (i = start; ((incr >= 0 && i <= end) || (incr < 0 && i >= end)); i += incr) { snprintf(tmp, sizeof(tmp), "%d", i); dptr = MesgParse(argv[4], buf); CHECKRETURN(dptr, "FOR", "arg 5 (repeated command)"); if (!(--iter_limit)) ABORT_MPI("FOR", "Iteration limit exceeded"); } free_top_mvar(); return buf; } const char * mfn_foreach(MFUNARGS) { int iter_limit = MAX_MFUN_LIST_LEN; char scratch[BUFFER_LEN]; char listbuf[BUFFER_LEN]; char tmp[BUFFER_LEN]; char *ptr, *ptr2, *dptr; char *sepin; int seplen, v; ptr = MesgParse(argv[0], scratch); CHECKRETURN(ptr, "FOREACH", "arg 1"); v = new_mvar(ptr, tmp); if (v == 1) ABORT_MPI("FOREACH", "Variable name too long."); if (v == 2) ABORT_MPI("FOREACH", "Too many variables already defined."); dptr = MesgParse(argv[1], listbuf); CHECKRETURN(dptr, "FOREACH", "arg 2"); if (argc > 3) { ptr = MesgParse(argv[3], scratch); CHECKRETURN(ptr, "FOREACH", "arg 4"); if (!*ptr) ABORT_MPI("FOREACH", "Can't use Null seperator string"); sepin = ptr; } else { sepin = scratch; strcpy(sepin, "\r"); } seplen = strlen(sepin); ptr = dptr; *buf = '\0'; while (*ptr) { for (ptr2 = ptr; *ptr2 && strncmp(ptr2, sepin, seplen); ptr2++) ; if (*ptr2) { *ptr2 = '\0'; ptr2 += seplen; } strcpy(tmp, ptr); dptr = MesgParse(argv[2], buf); CHECKRETURN(dptr, "FOREACH", "arg 3"); ptr = ptr2; if (!(--iter_limit)) ABORT_MPI("FOREACH", "Iteration limit exceeded"); } free_top_mvar(); return buf; } const char * mfn_filter(MFUNARGS) { int iter_limit = MAX_MFUN_LIST_LEN; char scratch[BUFFER_LEN]; char listbuf[BUFFER_LEN]; char sepinbuf[BUFFER_LEN]; char sepoutbuf[BUFFER_LEN]; char buf2[BUFFER_LEN]; char tmp[BUFFER_LEN]; char *ptr, *ptr2, *dptr; char *sepin = argv[3]; char *sepbuf = argv[4]; int seplen, v; int outcount = 0; ptr = MesgParse(argv[0], scratch); CHECKRETURN(ptr, "FILTER", "arg 1"); v = new_mvar(ptr, tmp); if (v == 1) ABORT_MPI("FILTER", "Variable name too long."); if (v == 2) ABORT_MPI("FILTER", "Too many variables already defined."); dptr = MesgParse(argv[1], listbuf); CHECKRETURN(dptr, "FILTER", "arg 2"); if (argc > 3) { ptr = MesgParse(sepin, sepinbuf); CHECKRETURN(ptr, "FILTER", "arg 4"); if (!*ptr) ABORT_MPI("FILTER", "Can't use Null seperator string"); sepin = sepinbuf; } else { sepin = sepinbuf; strcpy(sepin, "\r"); } if (argc > 4) { ptr = MesgParse(sepbuf, sepoutbuf); CHECKRETURN(ptr, "FILTER", "arg 5"); sepbuf = sepoutbuf; } else { sepbuf = sepoutbuf; strcpy(sepbuf, sepin); } seplen = strlen(sepin); *buf = '\0'; ptr = dptr; while (*ptr) { for (ptr2 = ptr; *ptr2 && strncmp(ptr2, sepin, seplen); ptr2++) ; if (*ptr2) { *ptr2 = '\0'; ptr2 += seplen; } strcpy(tmp, ptr); dptr = MesgParse(argv[2], buf2); CHECKRETURN(dptr, "FILTER", "arg 3"); if (truestr(buf2)) { if (outcount++) strcatn(buf, BUFFER_LEN, sepbuf); strcatn(buf, BUFFER_LEN, ptr); } ptr = ptr2; if (!(--iter_limit)) ABORT_MPI("FILTER", "Iteration limit exceeded"); } free_top_mvar(); return buf; } int list_contains(char* word, int len, char* list) { char *w, *w2; w = w2 = list; do { for(; *w2 && *w2 != '\r'; w2++) {}; if(w2 - w == len && !strncmp(word, w, len)) return 1; if(*w2) w = ++w2; } while(*w2); return 0; } const char * mfn_lremove(MFUNARGS) { int iter_limit = MAX_MFUN_LIST_LEN; char *ptr, *ptr2, *endbuf; int len; int firstResult = 1; ptr = argv[0]; // the list we're removing from endbuf = buf; *buf = '\0'; // empty buf; this is what we're returning, I bet while (*ptr) { // while more of the first list // Find the next word. for (ptr2 = ptr; *ptr2 && *ptr2 != '\r'; ptr2++) {}; len = ptr2 - ptr; // If the second list contains the string, continue. if(!list_contains(ptr, len, argv[1]) && /* * If it's the first result, it already won't be in buf. * This wouldn't be a problem except buf already contains * the empty string, so if the first word to add is the * empty string, it won't be added. */ (firstResult || !list_contains(ptr, len, buf)) ) { if(firstResult) firstResult = 0; else *(endbuf++) = '\r'; strncpy(endbuf, ptr, len); endbuf += len; *endbuf = '\0'; } // Next word. if(*ptr2) ptr2++; ptr = ptr2; if (!(--iter_limit)) ABORT_MPI("LREMOVE", "Iteration limit exceeded"); } return buf; } const char * mfn_lcommon(MFUNARGS) { int iter_limit = MAX_MFUN_LIST_LEN; char *ptr, *ptr2, *p, *q; int len; int outcount = 0; ptr = argv[1]; *buf = '\0'; while (*ptr) { for (ptr2 = ptr; *ptr2 && *ptr2 != '\r'; ptr2++) ; if (*ptr2) *(ptr2++) = '\0'; len = strlen(ptr); p = argv[0]; do { if (string_prefix(p, ptr) && (!p[len] || p[len] == '\r')) break; while (*p && *p != '\r') p++; if (*p) p++; } while (*p); q = buf; do { if (string_prefix(q, ptr) && (!q[len] || q[len] == '\r')) break; while (*q && *q != '\r') q++; if (*q) q++; } while (*q); if (*p && !*q) { if (outcount++) strcatn(buf, BUFFER_LEN, "\r"); strcatn(buf, BUFFER_LEN, ptr); } ptr = ptr2; if (!(--iter_limit)) ABORT_MPI("LCOMMON", "Iteration limit exceeded"); } return buf; } const char * mfn_lunion(MFUNARGS) { int iter_limit = MAX_MFUN_LIST_LEN; char *ptr, *ptr2, *p; int len; int outlen, nextlen; int outcount = 0; *buf = '\0'; outlen = 0; ptr = argv[0]; while (*ptr) { for (ptr2 = ptr; *ptr2 && *ptr2 != '\r'; ptr2++) ; if (*ptr2) *(ptr2++) = '\0'; len = strlen(ptr); p = buf; do { if (string_prefix(p, ptr) && (!p[len] || p[len] == '\r')) break; while (*p && *p != '\r') p++; if (*p) p++; } while (*p); if (!*p) { nextlen = strlen(ptr); if (outlen + nextlen > BUFFER_LEN - 3) break; if (outcount++) { strcatn(buf + outlen, BUFFER_LEN - outlen, "\r"); outlen++; } strcatn((buf + outlen), BUFFER_LEN - outlen, ptr); outlen += nextlen; } ptr = ptr2; if (!(--iter_limit)) ABORT_MPI("LUNION", "Iteration limit exceeded"); } ptr = argv[1]; while (*ptr) { for (ptr2 = ptr; *ptr2 && *ptr2 != '\r'; ptr2++) ; if (*ptr2) *(ptr2++) = '\0'; len = strlen(ptr); p = buf; do { if (string_prefix(p, ptr) && (!p[len] || p[len] == '\r')) break; while (*p && *p != '\r') p++; if (*p) p++; } while (*p); if (!*p) { nextlen = strlen(ptr); if (outlen + nextlen > BUFFER_LEN - 3) break; if (outcount++) { strcatn(buf + outlen, BUFFER_LEN - outlen, "\r"); outlen++; } strcatn((buf + outlen), BUFFER_LEN - outlen, ptr); outlen += nextlen; } ptr = ptr2; if (!(--iter_limit)) ABORT_MPI("LUNION", "Iteration limit exceeded"); } return buf; } const char * mfn_lsort(MFUNARGS) { char *litem[MAX_MFUN_LIST_LEN]; char listbuf[BUFFER_LEN]; char scratch[BUFFER_LEN]; char vbuf[BUFFER_LEN]; char vbuf2[BUFFER_LEN]; char *ptr, *ptr2, *tmp; int i, j, count; int outcount = 0; if (argc > 1 && argc < 4) ABORT_MPI("LSORT", "Takes 1 or 4 arguments."); for (i = 0; i < MAX_MFUN_LIST_LEN; i++) litem[i] = NULL; ptr = MesgParse(argv[0], listbuf); CHECKRETURN(ptr, "LSORT", "arg 1"); if (argc > 1) { ptr2 = MesgParse(argv[1], scratch); CHECKRETURN(ptr2, "LSORT", "arg 2"); j = new_mvar(ptr2, vbuf); if (j == 1) ABORT_MPI("LSORT", "Variable name too long."); if (j == 2) ABORT_MPI("LSORT", "Too many variables already defined."); ptr2 = MesgParse(argv[2], scratch); CHECKRETURN(ptr2, "LSORT", "arg 3"); j = new_mvar(ptr2, vbuf2); if (j == 1) ABORT_MPI("LSORT", "Variable name too long."); if (j == 2) ABORT_MPI("LSORT", "Too many variables already defined."); } count = 0; while (*ptr) { for (ptr2 = ptr; *ptr2 && *ptr2 != '\r'; ptr2++) ; if (*ptr2 == '\r') *(ptr2++) = '\0'; litem[count++] = ptr; ptr = ptr2; if (count >= MAX_MFUN_LIST_LEN) ABORT_MPI("LSORT", "Iteration limit exceeded"); } for (i = 0; i < count; i++) { for (j = i + 1; j < count; j++) { if (argc > 1) { strcpy(vbuf, litem[i]); strcpy(vbuf2, litem[j]); ptr = MesgParse(argv[3], buf); CHECKRETURN(ptr, "LSORT", "arg 4"); if (truestr(buf)) { tmp = litem[i]; litem[i] = litem[j]; litem[j] = tmp; } } else { if (alphanum_compare(litem[i], litem[j]) > 0) { tmp = litem[i]; litem[i] = litem[j]; litem[j] = tmp; } } } } *buf = '\0'; for (i = 0; i < count; i++) { if (outcount++) strcatn(buf, BUFFER_LEN, "\r"); strcatn(buf, BUFFER_LEN, litem[i]); } if (argc > 1) { free_top_mvar(); free_top_mvar(); } return buf; } const char * mfn_lunique(MFUNARGS) { int iter_limit = MAX_MFUN_LIST_LEN; char *ptr, *ptr2, *p; int len; int outlen, nextlen; int outcount = 0; *buf = '\0'; outlen = 0; ptr = argv[0]; while (*ptr) { for (ptr2 = ptr; *ptr2 && *ptr2 != '\r'; ptr2++) ; if (*ptr2) *(ptr2++) = '\0'; len = strlen(ptr); p = buf; do { if (string_prefix(p, ptr) && (!p[len] || p[len] == '\r')) break; while (*p && *p != '\r') p++; if (*p) p++; } while (*p); if (!*p) { nextlen = strlen(ptr); if (outcount++) { strcatn(buf + outlen, BUFFER_LEN - outlen,"\r"); outlen++; } strcatn((buf + outlen), BUFFER_LEN - outlen, ptr); outlen += nextlen; } ptr = ptr2; if (!(--iter_limit)) ABORT_MPI("LUNIQUE", "Iteration limit exceeded"); } return buf; } const char * mfn_parse(MFUNARGS) { int iter_limit = MAX_MFUN_LIST_LEN; char listbuf[BUFFER_LEN]; char sepinbuf[BUFFER_LEN]; char sepoutbuf[BUFFER_LEN]; char buf2[BUFFER_LEN]; char tmp[BUFFER_LEN]; char *ptr, *ptr2, *dptr; char *sepin = argv[3]; char *sepbuf = argv[4]; int outcount = 0; int seplen, oseplen, v; int outlen, nextlen; ptr = MesgParse(argv[0], buf2); CHECKRETURN(ptr, "PARSE", "arg 1"); v = new_mvar(ptr, tmp); if (v == 1) ABORT_MPI("PARSE", "Variable name too long."); if (v == 2) ABORT_MPI("PARSE", "Too many variables already defined."); dptr = MesgParse(argv[1], listbuf); CHECKRETURN(dptr, "PARSE", "arg 2"); if (argc > 3) { ptr = MesgParse(sepin, sepinbuf); CHECKRETURN(ptr, "PARSE", "arg 4"); if (!*ptr) ABORT_MPI("PARSE", "Can't use Null seperator string"); sepin = sepinbuf; } else { sepin = sepinbuf; strcpy(sepin, "\r"); } if (argc > 4) { ptr = MesgParse(sepbuf, sepoutbuf); CHECKRETURN(ptr, "PARSE", "arg 5"); sepbuf = sepoutbuf; } else { sepbuf = sepoutbuf; strcpy(sepbuf, sepin); } seplen = strlen(sepin); oseplen = strlen(sepbuf); *buf = '\0'; outlen = 0; ptr = dptr; while (*ptr) { for (ptr2 = ptr; *ptr2 && strncmp(ptr2, sepin, seplen); ptr2++) ; if (*ptr2) { *ptr2 = '\0'; ptr2 += seplen; } strcpy(tmp, ptr); dptr = MesgParse(argv[2], buf2); CHECKRETURN(dptr, "PARSE", "arg 3"); nextlen = strlen(buf2); if (outlen + nextlen + oseplen > BUFFER_LEN - 3) break; if (outcount++) { strcatn(buf + outlen, BUFFER_LEN - outlen, sepbuf); outlen += oseplen; } strcatn((buf + outlen), BUFFER_LEN - outlen, buf2); outlen += nextlen; ptr = ptr2; if (!(--iter_limit)) ABORT_MPI("PARSE", "Iteration limit exceeded"); } free_top_mvar(); return buf; } const char * mfn_smatch(MFUNARGS) { if (equalstr(argv[1], argv[0])) { return "1"; } else { return "0"; } } const char * mfn_strlen(MFUNARGS) { snprintf(buf, BUFFER_LEN, "%d", strlen(argv[0])); return buf; } const char * mfn_subst(MFUNARGS) { return string_substitute(argv[0], argv[1], argv[2], buf, BUFFER_LEN); } const char * mfn_awake(MFUNARGS) { dbref obj = mesg_dbref_local(descr, player, what, perms, argv[0], mesgtyp); if (obj == PERMDENIED || obj == AMBIGUOUS || obj == UNKNOWN || obj == NOTHING || obj == HOME) return ("0"); if (Typeof(obj) == TYPE_THING && (FLAGS(obj) & ZOMBIE)) { obj = OWNER(obj); } else if (Typeof(obj) != TYPE_PLAYER) { return ("0"); } snprintf(buf, BUFFER_LEN, "%d", online(obj)); return (buf); } const char * mfn_type(MFUNARGS) { dbref obj = mesg_dbref_local(descr, player, what, perms, argv[0], mesgtyp); if (obj == NOTHING || obj == AMBIGUOUS || obj == UNKNOWN) return ("Bad"); if (obj == HOME) return ("Room"); if (obj == PERMDENIED) ABORT_MPI("TYPE", "Permission Denied."); switch (Typeof(obj)) { case TYPE_PLAYER: return "Player"; break; case TYPE_ROOM: return "Room"; break; case TYPE_EXIT: return "Exit"; break; case TYPE_THING: return "Thing"; break; case TYPE_PROGRAM: return "Program"; break; default: return "Bad"; break; } return "Bad"; } const char * mfn_istype(MFUNARGS) { dbref obj; if (tp_lazy_mpi_istype_perm) { obj = mesg_dbref_raw(descr, player, what, perms, argv[0]); } else { obj = mesg_dbref_local(descr, player, what, perms, argv[0], mesgtyp); } if (obj == NOTHING || obj == AMBIGUOUS || obj == UNKNOWN) return (string_compare(argv[1], "Bad") ? "0" : "1"); if ((string_compare(argv[1], "Bad") == 0) && (obj == NOTHING || obj == AMBIGUOUS || obj == UNKNOWN || obj == PERMDENIED )) return "1"; if (obj == PERMDENIED) ABORT_MPI("TYPE", "Permission Denied."); if (obj == HOME) return (string_compare(argv[1], "Room") ? "0" : "1"); switch (Typeof(obj)) { case TYPE_PLAYER: return (string_compare(argv[1], "Player") ? "0" : "1"); break; case TYPE_ROOM: return (string_compare(argv[1], "Room") ? "0" : "1"); break; case TYPE_EXIT: return (string_compare(argv[1], "Exit") ? "0" : "1"); break; case TYPE_THING: return (string_compare(argv[1], "Thing") ? "0" : "1"); break; case TYPE_PROGRAM: return (string_compare(argv[1], "Program") ? "0" : "1"); break; default: return (string_compare(argv[1], "Bad") ? "0" : "1"); break; } return (string_compare(argv[1], "Bad") ? "0" : "1"); } const char * mfn_fox(MFUNARGS) { return "YARF!"; } const char * mfn_debugif(MFUNARGS) { char *ptr = MesgParse(argv[0], argv[0]); CHECKRETURN(ptr, "DEBUGIF", "arg 1"); if (truestr(argv[0])) { ptr = mesg_parse(descr, player, what, perms, argv[1], buf, BUFFER_LEN, (mesgtyp | MPI_ISDEBUG)); } else { ptr = MesgParse(argv[1], buf); } CHECKRETURN(ptr, "DEBUGIF", "arg 2"); return buf; } const char * mfn_debug(MFUNARGS) { char *ptr = mesg_parse(descr, player, what, perms, argv[0], buf, BUFFER_LEN, (mesgtyp | MPI_ISDEBUG)); CHECKRETURN(ptr, "DEBUG", "arg 1"); return buf; } const char * mfn_revoke(MFUNARGS) { char *ptr = mesg_parse(descr, player, what, perms, argv[0], buf, BUFFER_LEN, (mesgtyp & ~MPI_ISBLESSED)); CHECKRETURN(ptr, "REVOKE", "arg 1"); return buf; } const char * mfn_timing(MFUNARGS) { char buf2[128]; char *ptr; struct timeval start_time, end_time; int secs; int usecs; double timelen; gettimeofday(&start_time, (struct timezone *) 0); ptr = mesg_parse(descr, player, what, perms, argv[0], buf, BUFFER_LEN, mesgtyp); CHECKRETURN(ptr, "TIMING", "arg 1"); gettimeofday(&end_time, (struct timezone *) 0); secs = end_time.tv_sec - start_time.tv_sec; usecs = end_time.tv_usec - start_time.tv_usec; if (usecs > 1000000) { secs += 1; usecs -= 1000000; } timelen = ((double)secs) + (((double)usecs) / 1000000); snprintf(buf2, sizeof(buf2), "Time elapsed: %.6f seconds", timelen); notify_nolisten(player, buf2, 1); return buf; } const char * mfn_delay(MFUNARGS) { char *argchr, *cmdchr; int i = atoi(argv[0]); if (i < 1) i = 1; #ifdef WIZZED_DELAY if (!(mesgtyp & MPI_ISBLESSED)) ABORT_MPI("DELAY", "Permission denied."); #endif cmdchr = get_mvar("cmd"); argchr = get_mvar("arg"); i = add_mpi_event(i, descr, player, getloc(player), perms, argv[1], cmdchr, argchr, (mesgtyp & MPI_ISLISTENER), (!(mesgtyp & MPI_ISPRIVATE)), (mesgtyp & MPI_ISBLESSED)); snprintf(buf, BUFFER_LEN, "%d", i); return buf; } const char * mfn_kill(MFUNARGS) { int i = atoi(argv[0]); if (i > 0) { if (in_timequeue(i)) { if (!control_process(perms, i)) { ABORT_MPI("KILL", "Permission denied."); } i = dequeue_process(i); } else { i = 0; } } else if (i == 0) { i = dequeue_prog(perms, 0); } else { ABORT_MPI("KILL", "Invalid process ID."); } snprintf(buf, BUFFER_LEN, "%d", i); return buf; } static int mpi_muf_call_levels = 0; const char * mfn_muf(MFUNARGS) { char *ptr; struct inst *rv = NULL; struct frame *tmpfr; dbref obj = mesg_dbref_raw(descr, player, what, perms, argv[0]); if (obj == UNKNOWN) ABORT_MPI("MUF", "Match failed."); if (obj <= NOTHING || Typeof(obj) != TYPE_PROGRAM) ABORT_MPI("MUF", "Bad program reference."); if (!(FLAGS(obj) & LINK_OK) && !controls(perms, obj)) ABORT_MPI("MUF", "Permission denied."); if ((mesgtyp & (MPI_ISLISTENER | MPI_ISLOCK)) && (MLevel(obj) < 3)) ABORT_MPI("MUF", "Permission denied."); if (++mpi_muf_call_levels > 18) ABORT_MPI("MUF", "Too many call levels."); strcpyn(match_args, sizeof(match_args), argv[1]); ptr = get_mvar("how"); snprintf(match_cmdname, sizeof(match_cmdname), "%s(MPI)", ptr); tmpfr = interp(descr, player, DBFETCH(player)->location, obj, perms, PREEMPT, STD_HARDUID, 0); if (tmpfr) { rv = interp_loop(player, obj, tmpfr, 1); } mpi_muf_call_levels--; if (!rv) return ""; switch (rv->type) { case PROG_STRING: if (rv->data.string) { strcpy(buf, rv->data.string->data); CLEAR(rv); return buf; } else { CLEAR(rv); return ""; } break; case PROG_INTEGER: snprintf(buf, BUFFER_LEN, "%d", rv->data.number); CLEAR(rv); return buf; break; case PROG_FLOAT: snprintf(buf, BUFFER_LEN, "%.15lg", rv->data.fnumber); CLEAR(rv); return buf; break; case PROG_OBJECT: ptr = ref2str(rv->data.objref, buf, BUFFER_LEN); CLEAR(rv); return ptr; break; default: CLEAR(rv); return ""; break; } } const char * mfn_force(MFUNARGS) { char *nxt, *ptr; dbref obj = mesg_dbref_raw(descr, player, what, perms, argv[0]); if (obj == AMBIGUOUS || obj == UNKNOWN || obj == NOTHING || obj == HOME) ABORT_MPI("FORCE", "Failed match. (arg1)"); if (obj == PERMDENIED) ABORT_MPI("FORCE", "Permission denied. (arg1)"); if (Typeof(obj) != TYPE_THING && Typeof(obj) != TYPE_PLAYER) ABORT_MPI("FORCE", "Bad object reference. (arg1)"); if (!*argv[1]) ABORT_MPI("FORCE", "Null command string. (arg2)"); if (!tp_zombies && !(mesgtyp & MPI_ISBLESSED)) ABORT_MPI("FORCE", "Permission Denied."); if (!(mesgtyp & MPI_ISBLESSED)) { const char *ptr = RNAME(obj); char objname[BUFFER_LEN], *ptr2; dbref loc = getloc(obj); if (Typeof(obj) == TYPE_THING) { if (FLAGS(obj) & DARK) ABORT_MPI("FORCE", "Cannot force a dark puppet."); if ((FLAGS(OWNER(obj)) & ZOMBIE)) ABORT_MPI("FORCE", "Permission denied."); if (loc != NOTHING && (FLAGS(loc) & ZOMBIE) && Typeof(loc) == TYPE_ROOM) ABORT_MPI("FORCE", "Cannot force a Puppet in a no-puppets room."); for (ptr2 = objname; *ptr && !isspace(*ptr);) *(ptr2++) = *(ptr++); *ptr2 = '\0'; if (lookup_player(objname) != NOTHING) ABORT_MPI("FORCE", "Cannot force a thing named after a player."); } if (!(FLAGS(obj) & XFORCIBLE)) { ABORT_MPI("FORCE", "Permission denied: forced object not @set Xforcible."); } if (!test_lock_false_default(descr, perms, obj, "@/flk")) { ABORT_MPI("FORCE", "Permission denied: Object not force-locked to trigger."); } } #ifdef GOD_PRIV if (God(obj)) ABORT_MPI("FORCE", "Permission denied: You can't force God."); #endif if (force_level) ABORT_MPI("FORCE", "Permission denied: You can't force recursively."); strcpy(buf, argv[1]); ptr = buf; do { nxt = index(ptr, '\r'); if (nxt) *nxt++ = '\0'; force_prog = what; force_level++; if (*ptr) process_command(dbref_first_descr(obj), obj, ptr); force_level--; force_prog = NOTHING; ptr = nxt; } while (ptr); *buf = '\0'; return ""; } const char * mfn_midstr(MFUNARGS) { int i, len = strlen(argv[0]); int pos1 = atoi(argv[1]); int pos2 = pos1; char *ptr = buf; if (argc > 2) pos2 = atoi(argv[2]); if (pos1 == 0) return ""; if (pos1 > len) pos1 = len; if (pos1 < 0) pos1 += len + 1; if (pos1 < 1) pos1 = 1; if (pos2 == 0) return ""; if (pos2 > len) pos2 = len; if (pos2 < 0) pos2 += len + 1; if (pos2 < 1) pos2 = 1; if (pos2 >= pos1) { for (i = pos1; i <= pos2; i++) *(ptr++) = argv[0][i - 1]; } else { for (i = pos1; i >= pos2; i--) *(ptr++) = argv[0][i - 1]; } *ptr = '\0'; return buf; } const char * mfn_instr(MFUNARGS) { char *ptr; if (!*argv[1]) ABORT_MPI("INSTR", "Can't search for a null string."); for (ptr = argv[0]; *ptr && !string_prefix(ptr, argv[1]); ptr++) ; if (!*ptr) return "0"; snprintf(buf, BUFFER_LEN, "%d", (ptr - argv[0] + 1)); return buf; } const char * mfn_lmember(MFUNARGS) { /* {lmember:list,item,delim} */ int i = 1; char *ptr = argv[0]; char *delim = NULL; int len; int len2 = strlen(argv[1]); if (argc < 3) delim = "\r"; else delim = argv[2]; if (!*delim) ABORT_MPI("LMEMBER", "List delimiter cannot be a null string."); len = strlen(delim); while (*ptr && !(string_prefix(ptr, argv[1]) && (!ptr[len2] || string_prefix(ptr + len2, delim)))) { while (*ptr && !string_prefix(ptr, delim)) ptr++; if (*ptr) ptr += len; i++; } if (!*ptr) return "0"; snprintf(buf, BUFFER_LEN, "%d", i); return buf; } const char * mfn_tolower(MFUNARGS) { char *ptr = argv[0]; char *ptr2 = buf; while (*ptr) { if (isupper(*ptr)) { *ptr2++ = tolower(*ptr++); } else { *ptr2++ = *ptr++; } } *ptr2++ = '\0'; return buf; } const char * mfn_toupper(MFUNARGS) { char *ptr = argv[0]; char *ptr2 = buf; while (*ptr) { if (islower(*ptr)) { *ptr2++ = toupper(*ptr++); } else { *ptr2++ = *ptr++; } } *ptr2++ = '\0'; return buf; } const char * mfn_commas(MFUNARGS) { int v, i, count, itemlen; char *ptr; char *out; char listbuf[BUFFER_LEN]; char sepbuf[BUFFER_LEN]; char buf2[BUFFER_LEN]; char tmp[BUFFER_LEN]; if (argc == 3) ABORT_MPI("COMMAS", "Takes 1, 2, or 4 arguments."); ptr = MesgParse(argv[0], listbuf); CHECKRETURN(ptr, "COMMAS", "arg 1"); count = countlitems(listbuf, "\r"); if (count == 0) return ""; if (argc > 1) { ptr = MesgParse(argv[1], sepbuf); CHECKRETURN(ptr, "COMMAS", "arg 2"); } else { strcpy(sepbuf, " and "); } if (argc > 2) { ptr = MesgParse(argv[2], buf2); CHECKRETURN(ptr, "COMMAS", "arg 3"); v = new_mvar(ptr, tmp); if (v == 1) ABORT_MPI("COMMAS", "Variable name too long."); if (v == 2) ABORT_MPI("COMMAS", "Too many variables already defined."); } *buf = '\0'; out = buf; for (i = 1; i <= count; i++) { ptr = getlitem(buf2, listbuf, "\r", i); if (argc > 2) { strcpy(tmp, ptr); ptr = MesgParse(argv[3], buf2); CHECKRETURN(ptr, "COMMAS", "arg 3"); } itemlen = strlen(ptr); if ((out - buf) + itemlen >= BUFFER_LEN) { if (argc > 2) free_top_mvar(); return buf; } strcatn(out, BUFFER_LEN - (out - buf), ptr); out += itemlen; switch (count - i) { case 0: if (argc > 2) free_top_mvar(); return buf; break; case 1: itemlen = strlen(sepbuf); if ((out - buf) + itemlen >= BUFFER_LEN) { if (argc > 2) free_top_mvar(); return buf; } strcatn(out, BUFFER_LEN - (out - buf), sepbuf); out += itemlen; break; default: if ((out - buf) + 2 >= BUFFER_LEN) { if (argc > 2) free_top_mvar(); return buf; } strcatn(out, BUFFER_LEN - (out - buf), ", "); out += strlen(out); break; } } if (argc > 2) free_top_mvar(); return buf; } const char * mfn_attr(MFUNARGS) { int i; int exlen; buf[0] = '\0'; for (i = 0; i < argc - 1; i++) { if (!string_compare(argv[i], "reset") || !string_compare(argv[i], "normal")) { strcatn(buf, BUFFER_LEN, ANSI_RESET); } else if (!string_compare(argv[i], "bold")) { strcatn(buf, BUFFER_LEN, ANSI_BOLD); } else if (!string_compare(argv[i], "dim")) { strcatn(buf, BUFFER_LEN, ANSI_DIM); } else if (!string_compare(argv[i], "italic")) { strcatn(buf, BUFFER_LEN, ANSI_ITALIC); } else if (!string_compare(argv[i], "uline") || !string_compare(argv[i], "underline")) { strcatn(buf, BUFFER_LEN, ANSI_UNDERLINE); } else if (!string_compare(argv[i], "flash")) { strcatn(buf, BUFFER_LEN, ANSI_FLASH); } else if (!string_compare(argv[i], "reverse")) { strcatn(buf, BUFFER_LEN, ANSI_REVERSE); } else if (!string_compare(argv[i], "ostrike") || !string_compare(argv[i], "overstrike")) { strcatn(buf, BUFFER_LEN, ANSI_OSTRIKE); } else if (!string_compare(argv[i], "black")) { strcatn(buf, BUFFER_LEN, ANSI_FG_BLACK); } else if (!string_compare(argv[i], "red")) { strcatn(buf, BUFFER_LEN, ANSI_FG_RED); } else if (!string_compare(argv[i], "yellow")) { strcatn(buf, BUFFER_LEN, ANSI_FG_YELLOW); } else if (!string_compare(argv[i], "green")) { strcatn(buf, BUFFER_LEN, ANSI_FG_GREEN); } else if (!string_compare(argv[i], "cyan")) { strcatn(buf, BUFFER_LEN, ANSI_FG_CYAN); } else if (!string_compare(argv[i], "blue")) { strcatn(buf, BUFFER_LEN, ANSI_FG_BLUE); } else if (!string_compare(argv[i], "magenta")) { strcatn(buf, BUFFER_LEN, ANSI_FG_MAGENTA); } else if (!string_compare(argv[i], "white")) { strcatn(buf, BUFFER_LEN, ANSI_FG_WHITE); } else if (!string_compare(argv[i], "bg_black")) { strcatn(buf, BUFFER_LEN, ANSI_BG_BLACK); } else if (!string_compare(argv[i], "bg_red")) { strcatn(buf, BUFFER_LEN, ANSI_BG_RED); } else if (!string_compare(argv[i], "bg_yellow")) { strcatn(buf, BUFFER_LEN, ANSI_BG_YELLOW); } else if (!string_compare(argv[i], "bg_green")) { strcatn(buf, BUFFER_LEN, ANSI_BG_GREEN); } else if (!string_compare(argv[i], "bg_cyan")) { strcatn(buf, BUFFER_LEN, ANSI_BG_CYAN); } else if (!string_compare(argv[i], "bg_blue")) { strcatn(buf, BUFFER_LEN, ANSI_BG_BLUE); } else if (!string_compare(argv[i], "bg_magenta")) { strcatn(buf, BUFFER_LEN, ANSI_BG_MAGENTA); } else if (!string_compare(argv[i], "bg_white")) { strcatn(buf, BUFFER_LEN, ANSI_BG_WHITE); } else if (!string_compare(argv[i], "")) { } else { ABORT_MPI("ATTR", "Unrecognized ansi tag. Try one of reset, bold, dim, italic, underline, reverse, overstrike, black, red, yellow, green, cyan, blue, magenta, white, bg_black, bg_red, bg_yellow, bg_green, bg_cyan, bg_blue, bg_magenta, or bg_white."); } } exlen = strlen(buf) + strlen(ANSI_RESET) + 1; strncat(buf, argv[argc - 1], (BUFFER_LEN - exlen)); strcatn(buf, BUFFER_LEN, ANSI_RESET); return buf; } const char * mfn_escape(MFUNARGS) { char *out; const char *in; int done = 0; in = argv[0]; out = buf; *out++ = '`'; while (*in && !done) { switch (*in) { case '\\': case '`': if (out - buf >= BUFFER_LEN - 2) { done = 1; break; } *out++ = '\\'; *out++ = *in++; break; default: if (out - buf >= BUFFER_LEN - 1) { done = 1; break; } *out++ = *in++; } } *out++ = '`'; *out = '\0'; return buf; }