#define __KERNEL__ #include #undef __KERNEL__ #include #include #include #include #include "language.h" #include "lex.h" #include "runtime.h" #include "constable.h" #include "cmds.h" #include "events.h" struct keyword_s { char *keyword; sym_t sym; udata u; }; struct keyword_s *findkeyword(char *keyword, struct keyword_s *keywords, sym_t wanted) { struct keyword_s *p; for (p = keywords; p->keyword; p++) if (!strcmp(p->keyword, keyword) && ((wanted == END) || (wanted == p->sym))) return p; return NULL; } udata relop1(var_t * pu1, var_t * pu2) { /* == */ if ((pu1->typ != pu2->typ) || (pu1->typ == VT_UNDEF)) { runtime_error = RT_ERR_BADTYPE; return 0; } switch (pu1->typ) { case VT_INT: return pu1->d == pu2->d; case VT_STR: return !strcmp((char *) (pu1->d), (char *) (pu2->d)); } runtime_error = RT_ERR_UFO; return 0; } udata relop2(var_t * pu1, var_t * pu2) { /* >= */ if ((pu1->typ != pu2->typ) || (pu1->typ == VT_UNDEF)) { runtime_error = RT_ERR_BADTYPE; return 0; } switch (pu1->typ) { case VT_INT: return pu1->d >= pu2->d; case VT_STR: return strcmp((char *) (pu1->d), (char *) (pu2->d)) >= 0; } runtime_error = RT_ERR_UFO; return 0; } udata relop3(var_t * pu1, var_t * pu2) { /* <= */ if ((pu1->typ != pu2->typ) || (pu1->typ == VT_UNDEF)) { runtime_error = RT_ERR_BADTYPE; return 0; } switch (pu1->typ) { case VT_INT: return pu1->d >= pu2->d; case VT_STR: return strcmp((char *) (pu1->d), (char *) (pu2->d)) <= 0; } runtime_error = RT_ERR_UFO; return 0; } udata relop4(var_t * pu1, var_t * pu2) { /* != */ if ((pu1->typ != pu2->typ) || (pu1->typ == VT_UNDEF)) { runtime_error = RT_ERR_BADASSIGN; return 0; } switch (pu1->typ) { case VT_INT: return pu1->d != pu2->d; case VT_STR: return strcmp((char *) (pu1->d), (char *) (pu2->d)) != 0; } runtime_error = RT_ERR_UFO; return 0; } udata relop5(var_t * pu1, var_t * pu2) { /* ?= */ if ((pu1->typ != pu2->typ) || (pu1->typ == VT_UNDEF)) { runtime_error = RT_ERR_BADASSIGN; return 0; } switch (pu1->typ) { case VT_INT: return (pu1->d & pu2->d) == pu2->d; case VT_STR: runtime_error = RT_ERR_BADASSIGN; return 0; } runtime_error = RT_ERR_UFO; return 0; } udata relop6(var_t * pu1, var_t * pu2) { /* ?& */ if ((pu1->typ != pu2->typ) || (pu1->typ == VT_UNDEF)) { runtime_error = RT_ERR_BADASSIGN; return 0; } switch (pu1->typ) { case VT_INT: return pu1->d & pu2->d; case VT_STR: runtime_error = RT_ERR_BADASSIGN; return 0; } runtime_error = RT_ERR_UFO; return 0; } udata relop7(var_t * pu1, var_t * pu2) { /* ?! */ if ((pu1->typ != pu2->typ) || (pu1->typ == VT_UNDEF)) { runtime_error = RT_ERR_BADASSIGN; return 0; } switch (pu1->typ) { case VT_INT: return !(pu1->d & pu2->d); case VT_STR: runtime_error = RT_ERR_BADASSIGN; return 0; } runtime_error = RT_ERR_UFO; return 0; } udata relop8(var_t * pu1, var_t * pu2) { /* > */ if ((pu1->typ != pu2->typ) || (pu1->typ == VT_UNDEF)) { runtime_error = RT_ERR_BADTYPE; return 0; } switch (pu1->typ) { case VT_INT: return pu1->d > pu2->d; case VT_STR: return strcmp((char *) (pu1->d), (char *) (pu2->d)) > 0; } runtime_error = RT_ERR_UFO; return 0; } udata relop9(var_t * pu1, var_t * pu2) { /* < */ if ((pu1->typ != pu2->typ) || (pu1->typ == VT_UNDEF)) { runtime_error = RT_ERR_BADTYPE; return 0; } switch (pu1->typ) { case VT_INT: return pu1->d < pu2->d; case VT_STR: return strcmp((char *) (pu1->d), (char *) (pu2->d)) < 0; } runtime_error = RT_ERR_UFO; return 0; } void clean_var_t(var_t * p) { switch (p->typ) { case VT_STR: free((void *) (p->d)); } p->typ = VT_UNDEF; p->d = 0; } udata setop1(var_t * pu1, var_t * pu2) { /* a = b */ clean_var_t(pu1); pu1->typ = pu2->typ; switch (pu2->typ) { case VT_STR: pu1->typ = VT_STR; pu1->d = (udata) malloc(strlen((char *) (pu2->d)) + 1); if (!pu1->d) { runtime_error = RT_ERR_ENOMEM; pu1->typ = VT_UNDEF; } else strcpy((char *) (pu1->d), (char *) (pu2->d)); return pu1->d; case VT_UNDEF: runtime_error = RT_ERR_BADASSIGN; return 0; default: pu1->typ = pu2->typ; return pu1->d = pu2->d; } } udata setop2(var_t * pu1, var_t * pu2) { /* a += b */ char *p; if ((pu1->typ != pu2->typ) || (pu1->typ == VT_UNDEF)) { runtime_error = RT_ERR_BADASSIGN; return 0; } switch (pu1->typ) { case VT_INT: return pu1->d += pu2->d; case VT_STR: p = realloc((void *) (pu1->d), strlen((char *) (pu1->d)) + strlen((char *) (pu2->d)) + 1); if (!p) { runtime_error = RT_ERR_ENOMEM; return 0; } strcat(p, (char *) (pu2->d)); pu1->d = (udata) p; return pu1->d; } runtime_error = RT_ERR_UFO; return 0; } udata setop3(var_t * pu1, var_t * pu2) { /* a -= b */ if ((pu1->typ != pu2->typ) || (pu1->typ == VT_UNDEF)) { runtime_error = RT_ERR_BADASSIGN; return 0; } switch (pu1->typ) { case VT_INT: return pu1->d -= pu2->d; case VT_STR: runtime_error = RT_ERR_BADASSIGN; return 0; } runtime_error = RT_ERR_UFO; return 0; } udata setop4(var_t * pu1, var_t * pu2) { /* a |= b */ if ((pu1->typ != pu2->typ) || (pu1->typ == VT_UNDEF)) { runtime_error = RT_ERR_BADASSIGN; return 0; } switch (pu1->typ) { case VT_INT: return pu1->d |= pu2->d; case VT_STR: runtime_error = RT_ERR_BADASSIGN; return 0; } runtime_error = RT_ERR_UFO; return 0; } udata setop5(var_t * pu1, var_t * pu2) { /* a &= ~b */ if ((pu1->typ != pu2->typ) || (pu1->typ == VT_UNDEF)) { runtime_error = RT_ERR_BADASSIGN; return 0; } switch (pu1->typ) { case VT_INT: return pu1->d &= ~pu2->d; case VT_STR: runtime_error = RT_ERR_BADASSIGN; return 0; } runtime_error = RT_ERR_UFO; return 0; } udata setop6(var_t * pu1, var_t * pu2) { /* a ^= b */ if ((pu1->typ != pu2->typ) || (pu1->typ == VT_UNDEF)) { runtime_error = RT_ERR_BADASSIGN; return 0; } switch (pu1->typ) { case VT_INT: return pu1->d ^= pu2->d; case VT_STR: runtime_error = RT_ERR_BADASSIGN; return 0; } runtime_error = RT_ERR_UFO; return 0; } udata setop7(var_t * pu1, var_t * pu2) { /* a >>= b */ if ((pu1->typ != pu2->typ) || (pu1->typ == VT_UNDEF)) { runtime_error = RT_ERR_BADASSIGN; return 0; } switch (pu1->typ) { case VT_INT: return pu1->d <<= pu2->d; case VT_STR: runtime_error = RT_ERR_BADASSIGN; return 0; } runtime_error = RT_ERR_UFO; return 0; } udata setop8(var_t * pu1, var_t * pu2) { /* a <<= b */ if ((pu1->typ != pu2->typ) || (pu1->typ == VT_UNDEF)) { runtime_error = RT_ERR_BADASSIGN; return 0; } switch (pu1->typ) { case VT_INT: return pu1->d >>= pu2->d; case VT_STR: runtime_error = RT_ERR_BADASSIGN; return 0; } runtime_error = RT_ERR_UFO; return 0; } /* this runs only at compilation */ udata op1(udata u1, udata u2) { return u1 + u2; } udata op2(udata u1, udata u2) { return u1 - u2; } udata op3(udata u1, udata u2) { return u1 | u2; } udata op4(udata u1, udata u2) { return u1 & u2; } udata op5(udata u1, udata u2) { return u1 ^ u2; } struct keyword_s keywords1[] = { {"function", Lfunction, 0}, {"return", Lreturn, 0}, {"recursive", Lrecursive, 0}, {"recur", Lrecursive, 0}, {"on", Lon, 0}, {"for", Lfor, 0}, {"if", Lif, 0}, {"else", Lelse, 0}, {"not", Lnot, 0}, {"and", Land, 0}, {"or", Lor, 0}, {"force", Lforce, 0}, {NULL, 0, 0}, }; struct keyword_s keywords2[] = { {"&&", Land, 0}, {"||", Lor, 0}, {"==", lRELOP, (udata) relop1}, {">=", lRELOP, (udata) relop2}, {"<=", lRELOP, (udata) relop3}, {"!=", lRELOP, (udata) relop4}, {"?=", lRELOP, (udata) relop5}, {"?&", lRELOP, (udata) relop6}, {"?!", lRELOP, (udata) relop7}, {">", lRELOP, (udata) relop8}, {"<", lRELOP, (udata) relop9}, {"=", lSETOP, (udata) setop1}, {"+=", lSETOP, (udata) setop2}, {"-=", lSETOP, (udata) setop3}, {"|=", lSETOP, (udata) setop4}, {"/=", lSETOP, (udata) setop5}, {"~=", lSETOP, (udata) setop6}, {">>=", lSETOP, (udata) setop7}, {"<<=", lSETOP, (udata) setop8}, {"+", lOP, (udata) op1}, {"-", lOP, (udata) op2}, {"|", lOP, (udata) op3}, {"&", lOP, (udata) op4}, {"^", lOP, (udata) op5}, {"/*", lCOMMENT, 1}, {"//", lCOMMENT, 2}, {NULL, 0, 0}, }; struct globvar_s { char name[32]; var_t val; struct globvar_s *next; } *globvars = NULL; var_t *globvar(char *name) { struct globvar_s *p; for (p = globvars; p; p = p->next) if (!strcmp(p->name, name)) return &(p->val); p = (struct globvar_s *) malloc(sizeof(struct globvar_s)); if (!p) fatal(OUTMEM); strncpy(p->name, name, sizeof(p->name)); p->name[sizeof(p->name) - 1] = '\0'; p->val.typ = VT_UNDEF; p->val.d = 0; p->next = globvars; globvars = p; return &(p->val); } struct globnam_s { char name[LEX_MAX_FNNAME]; struct globnam_s *next; } *globnams = NULL; char *globnam(char *name) { struct globnam_s *p; for (p = globnams; p; p = p->next) if (!strcmp(p->name, name)) return p->name; p = (struct globnam_s *) malloc(sizeof(struct globnam_s)); if (!p) fatal(OUTMEM); strncpy(p->name, name, sizeof(p->name)); p->name[sizeof(p->name) - 1] = '\0'; p->next = globnams; globnams = p; return p->name; } char *alloc_string(char *what) { char *p; p = malloc(strlen(what) + 1); if (!p) fatal(OUTMEM); strcpy(p, what); return p; } struct keyword_s keywords3[] = { /* these tell what to do with file */ {"redirect", lPRIKAZ, (udata) cmd_redirect}, #ifdef CONFIG_MEDUSA_SYSCALL {"trace_on", lPRIKAZ, (udata) cmd_trace_on}, {"trace_off", lPRIKAZ, (udata) cmd_trace_off}, #endif {"lpeek", lPRIKAZ, (udata) cmd_lpeek}, {"lpoke", lPRIKAZ, (udata) cmd_lpoke}, {"log_inode", lPRIKAZ, (udata) cmd_log_iget}, {"log_proc", lPRIKAZ, (udata) cmd_log_proc}, {"log", lPRIKAZ, (udata) cmd_log_print}, /* access to Medusa structure */ {"pid", lPREMENNA, (udata) psg_pid}, {"uid", lPREMENNA, (udata) psg_uid}, {"euid", lPREMENNA, (udata) psg_euid}, {"suid", lPREMENNA, (udata) psg_suid}, {"fsuid", lPREMENNA, (udata) psg_fsuid}, {"gid", lPREMENNA, (udata) psg_gid}, {"egid", lPREMENNA, (udata) psg_egid}, {"sgid", lPREMENNA, (udata) psg_sgid}, {"fsgid", lPREMENNA, (udata) psg_fsgid}, {"luid", lPREMENNA, (udata) psg_luid}, {"vs", lPREMENNA, (udata) psg_med_vs}, {"vss", lPREMENNA, (udata) psg_med_vs_s}, {"vsr", lPREMENNA, (udata) psg_med_vs_r}, {"vsw", lPREMENNA, (udata) psg_med_vs_w}, {"flags", lPREMENNA, (udata) psg_med_user}, {"procact", lPREMENNA, (udata) psg_med_act}, {"fsact", lPREMENNA, (udata) psg_med_iact}, {"ecap", lPREMENNA, (udata) psg_cap_effective}, {"icap", lPREMENNA, (udata) psg_cap_inheritable}, {"pcap", lPREMENNA, (udata) psg_cap_permitted}, #ifdef CONFIG_MEDUSA_FILE_CAPABILITIES {"acap", lPREMENNA, (udata) psg_cap_inheritable}, {"fcap", lPREMENNA, (udata) psg_cap_permitted}, #endif /* {"redirect", lPREMENNA, (udata)psg_redirect}, */ {"data", lPREMENNA, (udata) psg_data}, {"answer", lPREMENNA, (udata) psg_answer}, {"apply", lPREMENNA, (udata) psg_apply_mode}, {"action", lPREMENNA, (udata) psg_action}, {"info1", lPREMENNA, (udata) psg_info1}, {"info2", lPREMENNA, (udata) psg_info2}, {"trace1", lPREMENNA, (udata) psg_trace1}, {"trace2", lPREMENNA, (udata) psg_trace2}, {"trace3", lPREMENNA, (udata) psg_trace3}, {"trace4", lPREMENNA, (udata) psg_trace4}, {"trace5", lPREMENNA, (udata) psg_trace5}, {"target_pid", lPREMENNA, (udata) psg_target_pid}, {"target_uid", lPREMENNA, (udata) psg_target_uid}, {"target_euid", lPREMENNA, (udata) psg_target_euid}, {"target_suid", lPREMENNA, (udata) psg_target_suid}, {"target_fsuid", lPREMENNA, (udata) psg_target_fsuid}, {"target_gid", lPREMENNA, (udata) psg_target_gid}, {"target_egid", lPREMENNA, (udata) psg_target_egid}, {"target_luid", lPREMENNA, (udata) psg_target_luid}, {"target_ecap", lPREMENNA, (udata) psg_target_cap_effective}, {"target_icap", lPREMENNA, (udata) psg_target_cap_inheritable}, {"target_pcap", lPREMENNA, (udata) psg_target_cap_permitted}, {"target_vs", lPREMENNA, (udata) psg_target_med_vs}, {"target_vss", lPREMENNA, (udata) psg_target_med_vs_s}, {"target_vsr", lPREMENNA, (udata) psg_target_med_vs_r}, {"target_vsw", lPREMENNA, (udata) psg_target_med_vs_w}, {"target_flags", lPREMENNA, (udata) psg_target_med_user}, {"target_procact", lPREMENNA, (udata) psg_target_med_act}, {"target_fsact", lPREMENNA, (udata) psg_target_med_iact}, {"inode_uid", lPREMENNA, (udata) psg_inode_uid}, {"inode_gid", lPREMENNA, (udata) psg_inode_gid}, {"inode_mode", lPREMENNA, (udata) psg_inode_mode}, {"inode_vs", lPREMENNA, (udata) psg_inode_med_vs}, {"inode_fsact", lPREMENNA, (udata) psg_inode_med_act}, /* {"inode_cinfo", lPREMENNA, (udata)psg_inode_cinfo}, */ {"constable_pid", lPREMENNA, (udata) psg_constable_pid}, /* capability constants */ {"CAP_CHOWN", lKONSTANT, (udata) (1 << CAP_CHOWN)}, {"CAP_DAC_OVERRIDE", lKONSTANT, (udata) (1 << CAP_DAC_OVERRIDE)}, {"CAP_DAC_READ_SEARCH", lKONSTANT, (udata) (1 << CAP_DAC_READ_SEARCH)}, {"CAP_FOWNER", lKONSTANT, (udata) (1 << CAP_FOWNER)}, {"CAP_FSETID", lKONSTANT, (udata) (1 << CAP_FSETID)}, {"CAP_FS_MASK", lKONSTANT, (udata) (CAP_FS_MASK)}, {"CAP_KILL", lKONSTANT, (udata) (1 << CAP_KILL)}, {"CAP_SETGID", lKONSTANT, (udata) (1 << CAP_SETGID)}, {"CAP_SETUID", lKONSTANT, (udata) (1 << CAP_SETUID)}, {"CAP_SETPCAP", lKONSTANT, (udata) (1 << CAP_SETPCAP)}, {"CAP_LINUX_IMMUTABLE", lKONSTANT, (udata) (1 << CAP_LINUX_IMMUTABLE)}, {"CAP_NET_BIND_SERVICE", lKONSTANT, (udata) (1 << CAP_NET_BIND_SERVICE)}, {"CAP_NET_BROADCAST", lKONSTANT, (udata) (1 << CAP_NET_BROADCAST)}, {"CAP_NET_ADMIN", lKONSTANT, (udata) (1 << CAP_NET_ADMIN)}, {"CAP_NET_RAW", lKONSTANT, (udata) (1 << CAP_NET_RAW)}, {"CAP_IPC_LOCK", lKONSTANT, (udata) (1 << CAP_IPC_LOCK)}, {"CAP_IPC_OWNER", lKONSTANT, (udata) (1 << CAP_IPC_OWNER)}, {"CAP_SYS_MODULE", lKONSTANT, (udata) (1 << CAP_SYS_MODULE)}, {"CAP_SYS_RAWIO", lKONSTANT, (udata) (1 << CAP_SYS_RAWIO)}, {"CAP_SYS_CHROOT", lKONSTANT, (udata) (1 << CAP_SYS_CHROOT)}, {"CAP_SYS_PTRACE", lKONSTANT, (udata) (1 << CAP_SYS_PTRACE)}, {"CAP_SYS_PACCT", lKONSTANT, (udata) (1 << CAP_SYS_PACCT)}, {"CAP_SYS_ADMIN", lKONSTANT, (udata) (1 << CAP_SYS_ADMIN)}, {"CAP_SYS_BOOT", lKONSTANT, (udata) (1 << CAP_SYS_BOOT)}, {"CAP_SYS_NICE", lKONSTANT, (udata) (1 << CAP_SYS_NICE)}, {"CAP_SYS_RESOURCE", lKONSTANT, (udata) (1 << CAP_SYS_RESOURCE)}, {"CAP_SYS_TIME", lKONSTANT, (udata) (1 << CAP_SYS_TIME)}, {"CAP_SYS_TTY_CONFIG", lKONSTANT, (udata) (1 << CAP_SYS_TTY_CONFIG)}, /* procact constants */ {"P_FORK", lKONSTANT, (udata) MPACT_FORK}, {"P_EXEC", lKONSTANT, (udata) MPACT_EXEC}, {"P_SEXEC", lKONSTANT, (udata) MPACT_SEXEC}, {"P_EXIT", lKONSTANT, (udata) MPACT_EXIT}, {"P_SETUID", lKONSTANT, (udata) MPACT_SETUID}, {"P_KILL", lKONSTANT, (udata) MPACT_KILL}, // {"P_SOCKET", lKONSTANT, (udata)MPACT_SOCKET}, // {"P_PERM", lKONSTANT, (udata)MPACT_PERM}, // {"P_CHANGE", lKONSTANT, (udata)MPACT_CH}, {"P_FSACT", lKONSTANT, (udata) MPACT_IOP}, {"P_CAP", lKONSTANT, (udata) MPACT_CAP}, {"P_PTRACE", lKONSTANT, (udata) MPACT_PTRACE}, // {"P_MODULE", lKONSTANT, (udata)MPACT_MODULE}, /* fsact constants */ {"FS_ACCESS", lKONSTANT, MIACT_ACCESS}, {"FS_CREATE", lKONSTANT, MIACT_CREATE}, {"FS_LINK", lKONSTANT, MIACT_LINK}, {"FS_UNLINK", lKONSTANT, MIACT_UNLINK}, {"FS_SYMLINK", lKONSTANT, MIACT_SYMLINK}, {"FS_MKDIR", lKONSTANT, MIACT_MKDIR}, {"FS_RMDIR", lKONSTANT, MIACT_RMDIR}, {"FS_MKNOD", lKONSTANT, MIACT_MKNOD}, {"FS_RENAME", lKONSTANT, MIACT_RENAME}, {"FS_READLINK", lKONSTANT, MIACT_READLINK}, {"FS_FOLLOW", lKONSTANT, MIACT_FOLLOW}, {"FS_TRUNCATE", lKONSTANT, MIACT_TRUNCATE}, {"FS_PERMISSION", lKONSTANT, MIACT_PERMISSION}, {"FS_EXEC", lKONSTANT, MIACT_EXEC}, /* file mode constants */ {"S_IFMT", lKONSTANT, 00170000}, {"S_IFSOCK", lKONSTANT, 0140000}, {"S_IFLNK", lKONSTANT, 0120000}, {"S_IFREG", lKONSTANT, 0100000}, {"S_IFBLK", lKONSTANT, 0060000}, {"S_IFDIR", lKONSTANT, 0040000}, {"S_IFCHR", lKONSTANT, 0020000}, {"S_IFIFO", lKONSTANT, 0010000}, {"S_ISUID", lKONSTANT, 0004000}, {"S_ISGID", lKONSTANT, 0002000}, {"S_ISVTX", lKONSTANT, 0001000}, {"S_IRWXU", lKONSTANT, 00700}, {"S_IRUSR", lKONSTANT, 00400}, {"S_IWUSR", lKONSTANT, 00200}, {"S_IXUSR", lKONSTANT, 00100}, {"S_IRWXG", lKONSTANT, 00070}, {"S_IRGRP", lKONSTANT, 00040}, {"S_IWGRP", lKONSTANT, 00020}, {"S_IXGRP", lKONSTANT, 00010}, {"S_IRWXO", lKONSTANT, 00007}, {"S_IROTH", lKONSTANT, 00004}, {"S_IWOTH", lKONSTANT, 00002}, {"S_IXOTH", lKONSTANT, 00001}, /* apply constants */ {"A_CURRENT", lKONSTANT, (udata) APPLY_CURRENT}, {"A_PARENT", lKONSTANT, (udata) APPLY_PARENT}, {"A_FOR_PARENT", lKONSTANT, (udata) APPLY_FOR_PARENT}, {"A_FOR_LOGIN", lKONSTANT, (udata) APPLY_FOR_LOGIN}, /* answer constants */ {"OK", lKONSTANT, (udata) MED_OK}, {"YES", lKONSTANT, (udata) MED_YES}, {"NO", lKONSTANT, (udata) MED_NO}, {"SKIP", lKONSTANT, (udata) MED_SKIP}, {"NONE", lKONSTANT, (udata) MED_NONE}, /* old answer constants - for backward compatibility - will be removed soon */ {"MED_OK", lKONSTANT, (udata) MED_OK}, {"MED_YES", lKONSTANT, (udata) MED_SKIP}, {"MED_NOT", lKONSTANT, (udata) MED_NO}, {"MED_ERR", lKONSTANT, (udata) MED_ERR}, {"MED_NONE", lKONSTANT, (udata) MED_NONE}, /* filesystem commands */ {"set", lFSENTRY, MIACT_IGET}, {"access", lFSENTRY, MIACT_ACCESS}, {"create", lFSENTRY, MIACT_CREATE}, {"link", lFSENTRY, MIACT_LINK}, {"unlink", lFSENTRY, MIACT_UNLINK}, {"symlink", lFSENTRY, MIACT_SYMLINK}, {"mkdir", lFSENTRY, MIACT_MKDIR}, {"rmdir", lFSENTRY, MIACT_RMDIR}, {"mknod", lFSENTRY, MIACT_MKNOD}, {"rename", lFSENTRY, MIACT_RENAME}, /* {"readlink", lFSENTRY, MIACT_READLINK}, {"follow", lFSENTRY, MIACT_FOLLOW}, */ {"truncate", lFSENTRY, MIACT_TRUNCATE}, {"permission", lFSENTRY, MIACT_PERMISSION}, {"exec", lFSENTRY, MIACT_EXEC}, /* events */ {"init", lEVENT, (udata) evadd_init}, {"fork", lEVENT, (udata) evadd_fork}, {"exec", lEVENT, (udata) evadd_exec}, {"sexec", lEVENT, (udata) evadd_sexec}, {"exit", lEVENT, (udata) evadd_exit}, {"setuid", lEVENT, (udata) evadd_setuid}, {"kill", lEVENT, (udata) evadd_kill}, {"fsact", lEVENT, (udata) evadd_fsact}, {"capable", lEVENT, (udata) evadd_capable}, {"ptrace", lEVENT, (udata) evadd_ptrace}, #ifdef CONFIG_MEDUSA_SYSCALL {"syscall", lEVENT, (udata) evadd_syscall}, #endif #if 0 {"timer", lEVENT, (udata) event_timer}, #endif {NULL, 0, 0}, }; /* character management */ int lex_line = 1; int lex_char = 0; char *linebuf = NULL; int linebuflen = 0; int charpos = 0; char c, saved; #define NUMBER(x) (((x)>='0') && ((x)<='9')) #define ALPHA(x) ((((x)>='A') && ((x)<='Z')) || (((x)>='a') && ((x)<='z')) || ((x)=='_')) #define WHITE(x) (((x)==' ') || ((x)=='\t') || ((x)=='\n') || ((x)=='\r')) #define FIELDMOUSE(x) (((x)=='{') || ((x)=='}') || ((x)==';') || ((x)=='(') || ((x)==')')) #define HUMUS(x) (!(NUMBER(x)) && !(ALPHA(x)) && !(WHITE(x)) && !(FIELDMOUSE(x))) #define DELTABUFF 80 void char_realloc(void) { linebuf = realloc(linebuf, linebuflen + DELTABUFF); if (!linebuf) fatal(OUTMEM); linebuflen += DELTABUFF; } void eat_line(int fd) { char c; while (read(fd, &c, 1) == 1) if (c == '\n') break; lex_line++; lex_char = 0; } void macropreprocessor(int fd) { char buf[LEX_MAX_MACRO]; int i; for (i = 0; i < LEX_MAX_MACRO; i++) { if (read(fd, buf + i, 1) != 1) return; if (buf[i] == '\n') break; } if (i == LEX_MAX_MACRO) eat_line(fd); buf[LEX_MAX_MACRO - 1] = '\0'; /* ignore all #defines this time */ } int char_get(int fd) { int nothingread; if (charpos >= linebuflen) char_realloc(); do { nothingread = 0; if (read(fd, linebuf + charpos, 1) != 1) { c = linebuf[charpos] = '\0'; return 0; } c = linebuf[charpos]; if ((c == '#') && !lex_char) { macropreprocessor(fd); lex_line++; nothingread = 1; continue; } } while (nothingread); if (c == '\n') { lex_line++; lex_char = 0; } else lex_char++; charpos++; return 1; } void char_terminate(void) { if (!charpos) return; saved = linebuf[charpos - 1]; linebuf[charpos - 1] = '\0'; } void char_fix(void) { linebuf[charpos - 1] = saved; } void char_strip(void) { linebuf[0] = saved; charpos = 1; } void char_init(void) { charpos = 0; } void char_backspace(void) { charpos--; } void char_zeroafter(void) { if ((charpos + 1) >= linebuflen) char_realloc(); linebuf[charpos] = '\0'; } /* main code */ sym_t getlex_core(lex_t * lex, long d, sym_t wanted); sym_t getlex_variable(lex_t * lex, int d); sym_t getlex_string(lex_t * lex, int d); sym_t getlex_alphanum(lex_t * lex, int d, sym_t wanted); sym_t getlex_number(lex_t * lex, int d); sym_t getlex_operator(lex_t * lex, int d); sym_t getlex(lex_t * lex, long d, sym_t wanted) { sym_t retval; int tmp; while (1) { retval = getlex_core(lex, d, wanted); if (retval == lCOMMENT) { tmp = 0; if (lex->num == 1) /* slash asterisk comment */ while (1) { if (!charpos) if (!char_get(d)) { lex->sym = END; lex->num = 0; return END; } c = *linebuf; char_init(); if (tmp && (c == '/')) /* end of comment */ break; tmp = (c == '*'); } else if (lex->num == 2) { /* two slashes comment */ if (!charpos || (*linebuf != '\n')) eat_line(d); char_init(); } } else break; } return retval; } sym_t getlex_core(lex_t * lex, long d, sym_t wanted) { if (charpos && WHITE(*linebuf)) char_init(); while (!charpos) { if (!char_get(d)) { lex->sym = END; lex->num = 0; return END; } c = *linebuf; if (WHITE(c)) char_init(); } if (ALPHA(c)) return getlex_alphanum(lex, d, wanted); if (FIELDMOUSE(c)) { lex->sym = T | c; lex->num = 0; char_init(); return lex->sym; } if (NUMBER(c)) return getlex_number(lex, d); if (c == '$') /* variable */ return getlex_variable(lex, d); if (c == '"') /* string */ return getlex_string(lex, d); return getlex_operator(lex, d); } sym_t getlex_variable(lex_t * lex, int d) { char_init(); /* forget "$" */ if (!char_get(d)) { /* at least one character after $ */ lex->sym = E | 0; return lex->sym; } if (!ALPHA(c)) { /* have to be letter */ lex->sym = E | 1; return lex->sym; } do if (!char_get(d)) break; while (ALPHA(c) || NUMBER(c)); /* we have whole string */ char_terminate(); lex->sym = lGLOBPREM; lex->num = (udata) globvar(linebuf); char_strip(); return lex->sym; } sym_t getlex_string(lex_t * lex, int d) { char *str; int flag = 1; char_init(); /* forget " */ do { if (!char_get(d)) break; switch (c) { case '"': flag = 0; break; case '\\': char_backspace(); if (!char_get(d)) { flag = 0; break; } switch (c) { case 'n': c = '\n'; break; case 'r': c = '\r'; break; case 't': c = '\t'; break; } /* fallthrough */ default: } } while (flag); if (c != '"') { lex->sym = E | 2; return lex->sym; } /* we have whole string */ char_terminate(); str = alloc_string(linebuf); char_init(); lex->sym = lRETAZEC; lex->num = (udata) str; return lex->sym; } sym_t getlex_alphanum(lex_t * lex, int d, sym_t wanted) { struct keyword_s *p = NULL; do if (!char_get(d)) break; while (ALPHA(c) || NUMBER(c)); /* we have whole string */ char_terminate(); p = findkeyword(linebuf, keywords1, wanted); if (!p && (wanted != END)) p = findkeyword(linebuf, keywords3, wanted); if (!p) p = findkeyword(linebuf, keywords3, END); if (p) { lex->sym = p->sym; lex->num = p->u; char_strip(); return lex->sym; } lex->sym = lID; lex->num = (udata) globnam(linebuf); char_strip(); return lex->sym; } sym_t getlex_number(lex_t * lex, int d) { int base = 10; udata tmp; udata u = 0; char *num = linebuf; do if (!char_get(d)) break; while (NUMBER(c) || ALPHA(c)); /* we have whole string */ char_terminate(); if (*num == '0') { /* base change */ num++; switch (*num) { case '\0': break; case 'x': case 'X': base = 16; num++; break; case 'b': case 'B': base = 2; num++; break; case 'o': case 'O': base = 8; num++; break; default: base = 8; } } while (*num) { u *= base; /* This is ASCII optimized :( */ tmp = (*num <= '9') ? (*num - '0') : ( (*num <= 'F') ? (*num - 'A' + 10) : (*num - 'a' + 10) ); if (tmp < base) u += tmp; else { lex->sym = E | 7; char_strip(); return lex->sym; } num++; } char_strip(); lex->sym = lCISLO; lex->num = u; return lex->sym; } sym_t getlex_operator(lex_t * lex, int d) { struct keyword_s *p, *lastp; int flag = 1; char_zeroafter(); lastp = NULL; while (1) { p = findkeyword(linebuf, keywords2, END); if (lastp && !p) break; lastp = p; if (!char_get(d)) break; flag = 0; char_zeroafter(); if (!HUMUS(c)) break; } char_terminate(); char_strip(); if (!lastp) { if (flag) char_init(); lex->sym = E | 65; return lex->sym; } lex->sym = lastp->sym; lex->num = lastp->u; return lex->sym; } char *lex2str(lex_t * lex) { struct keyword_s *p; static char buf[1024]; if (lex->sym == END) return "END"; if ((lex->sym == (T | ';')) || (lex->sym == (T | '{')) || (lex->sym == (T | '}')) || (lex->sym == (T | '(')) || (lex->sym == (T | ')')) ) { sprintf(buf, "'%c'", (lex->sym) & 255); return buf; } if ((lex->sym & ~255) == E) { sprintf(buf, "E|%d", (lex->sym) & 255); return buf; } for (p = keywords1; p->keyword; p++) if ((p->sym == lex->sym) && (p->u == lex->num)) { sprintf(buf, "%s", p->keyword); return buf; } for (p = keywords2; p->keyword; p++) if ((p->sym == lex->sym) && (p->u == lex->num)) { sprintf(buf, "%s", p->keyword); return buf; } for (p = keywords3; p->keyword; p++) if ((p->sym == lex->sym) && (p->u == lex->num)) { sprintf(buf, "%s", p->keyword); return buf; } if (lex->sym == lCISLO) { sprintf(buf, "number (%ld)", lex->num); return buf; } if (lex->sym == lRETAZEC) { /*sprintf (buf, "string \"%s\"", (char *)lex->num); */ sprintf(buf, "string"); return buf; } if (lex->sym == lID) { sprintf(buf, "identifier \"%s\"", (char *) lex->num); return buf; } if (lex->sym == lGLOBPREM) { struct globvar_s *p; for (p = globvars; p; p = p->next) if (((var_t *) (lex->num)) == &(p->val)) break; if (!p) { sprintf(buf, "BAD GLOB"); return buf; } sprintf(buf, "predefined variable $%s", p->name); return buf; } sprintf(buf, "", lex->sym); return buf; }