#pragma save_binary // File : /adm/daemons/event.c // Creator : Glenn Ferguson (Watcher@TMI) 12/12/92 // // System time manager // - Allows events to be triggered at preset time settings // // Patched check_* and perform_event to the correct type, Leto 120194 // Patched a bit more and fixed security hole in query_stack, Leto 16121994 // And a bit more. It seems the event cmd needs the original // array, don't ask me why. So, we give it. Leto 221294 #include <mudlib.h> #include <uid.h> #include <commands.h> #include <logs.h> #include <driver/origin.h> inherit DAEMON ; #define SAVE_FILE "/data/adm/daemons/event" // Save data file #define INTERVAL 60 // Time check interval in sec. #define IGNORE 900 // Remove event after X seconds #define HOUR_DIFF 3600 // Seconds in an hour #define DAY_DIFF (24 * HOUR_DIFF) // Seconds in a day #define WEEK_DIFF (7 * DAY_DIFF) // Seconds in a week #define SETUP_ARRAY ({ }) // Base storage array static void load_events(); static void save_events(); static void ERROR(string mesg, string err); static void check_once(); static void check_hourly(); static void check_daily(); static void check_weekly(); static void perform_event(string access, string file, string func, string arg); static int sort_stack(mixed *event1, mixed *event2); int add_event(string type, mixed *event); int remove_event(string type, mixed *event); static int initiate_sweep(); mixed *query_stack(string type); mixed *HOURLY, *DAILY, *WEEKLY, *ONCE; create() { seteuid(getuid(this_object())); // Setup save permissions HOURLY = SETUP_ARRAY; DAILY = SETUP_ARRAY; // Setup event arrays WEEKLY = SETUP_ARRAY; ONCE = SETUP_ARRAY; load_events(); // Load previous saved events initiate_sweep(); // Start time check loop } // Load preset event stacks from save file static void load_events() { string err; err = catch( restore_object(SAVE_FILE) ); if(err) { ERROR("Could not load data file", err); return; } } // Save present event stacks into save file static void save_events() { string err; err = catch ( save_object(SAVE_FILE) ); if(err) { ERROR("Could not save data file", err); return; } } // Stack accessing error output to error file with time stamp static void ERROR(string mesg, string err) { write_file(EVENT_LOG, mesg + "\t[" + extract(ctime(time()),4,15) + "]\n"); if(err && err != "") write_file(EVENT_LOG, " " + err + "\n\n"); else write_file(EVENT_LOG, "\n"); return; } // Cycling stack check function at INTERVAL intervals static int initiate_sweep() { remove_call_out("initiate_sweep"); call_out("initiate_sweep", INTERVAL); // Set next time check check_once(); // Perform once stack check check_hourly(); // Perform hourly stack check check_daily(); // Perform daily stack check check_weekly(); // Perform weekly stack check return 1; } // Event stack processing functions - Called by initiate_sweep() static void check_daily() { mixed *tmp; int loop; if(DAILY == SETUP_ARRAY) return ; // No events stored while( DAILY[loop] ) { tmp = DAILY[loop]; // Temp. store event data if(time() < DAILY[loop][0]) return ; // Check again next interval if(time() - DAILY[loop][0] <= IGNORE) perform_event(DAILY[loop][4], DAILY[loop][1], DAILY[loop][2], DAILY[loop][3]); // Remove present event, then reschedule it in the stack // in a day's time with same parameters. DAILY = exclude_array(DAILY, loop); if(!add_event("daily", ({ tmp[0]+DAY_DIFF, tmp[1], tmp[2], tmp[3], tmp[4] }) )) write("Event error1\n"); save_events(); if(DAILY == SETUP_ARRAY) break; } return ; } static void check_hourly() { mixed *tmp; int loop; if(HOURLY == SETUP_ARRAY) return ; // No events stored while( HOURLY[loop] ) { tmp = HOURLY[loop]; if(time() < HOURLY[loop][0]) return ; // Check again next interval if(time() - HOURLY[loop][0] <= IGNORE) perform_event(HOURLY[loop][4], HOURLY[loop][1], HOURLY[loop][2], HOURLY[loop][3]); // Remove present event, then reschedule it in the stack HOURLY = exclude_array(HOURLY, loop); catch(add_event("hourly", ({tmp[0]+HOUR_DIFF, tmp[1], tmp[2], tmp[3], tmp[4]}))); save_events(); if(HOURLY == SETUP_ARRAY) break; } return ; } static void check_weekly() { mixed *tmp; int loop; if(WEEKLY == SETUP_ARRAY) return ; // No events stored while( WEEKLY[loop] ) { tmp = WEEKLY[loop]; if(time() < WEEKLY[loop][0]) return ; // Check again next interval if(time() - WEEKLY[loop][0] <= IGNORE) perform_event(WEEKLY[loop][4], WEEKLY[loop][1], WEEKLY[loop][2], WEEKLY[loop][3]); // Remove present event, then reschedule it in the stack // in a week's time with same parameters. WEEKLY = exclude_array(WEEKLY, loop); if(!add_event("weekly", ({ tmp[0]+WEEK_DIFF, tmp[1], tmp[2], tmp[3], tmp[4] }))) write("Event error3\n"); save_events(); if(WEEKLY == SETUP_ARRAY) break; } return ; } static void check_once() { int loop; if(ONCE == SETUP_ARRAY) return ; // No events stored while( ONCE[loop] ) { if(time() < ONCE[loop][0]) return ; // Check again next interval if(time() - ONCE[loop][0] <= IGNORE) perform_event(ONCE[loop][4], ONCE[loop][1], ONCE[loop][2], ONCE[loop][3]); // Remove event from the stack and procede to next event ONCE = exclude_array(ONCE, loop); save_events(); if(ONCE == SETUP_ARRAY) break; } return ; } // Perform preset event on remote object static void perform_event(string access, string file, string func, string arg) { object what; string permis, err; // Attempt to locate requested target file err = catch( call_other(file, "???") ); if(!err) what = find_object(file); if(err || !what) { ERROR("Event error: Could not load " + file, err); return ; } // Get user's command permission string permis = geteuid(what); // If attempting to access ROOT object without ROOT permissions, // block and log illegal access attempt if(permis == ROOT_UID && access != ROOT_UID && !adminp(access)) { ERROR("Event error: Illegal root access attempt by " + access, " " + func + "(" + arg + ") on " + file); return ; } // Perform stored function call on specified object err = catch( call_other(file, func, arg) ); if(err) ERROR("Event error: " + file + " " + func + "(" + arg + ")", err); return ; } // Add new event to a specified event stack int add_event(string type, mixed *event) { mixed *tmp; int loop, flag; // Check accessing permissions ... ensure root command // if(geteuid(previous_object()) != ROOT_UID && // previous_object() != this_object()) return 0; if (previous_object()) { if(geteuid(previous_object()) != ROOT_UID) return 0; } else if( origin()!=ORIGIN_LOCAL) return 0; if(sizeof(event) != 5) return 0; // Invalid event array // Store specific stack into a temporary array if(type == "once") tmp = ONCE; else if(type == "hourly") tmp = HOURLY; else if(type == "daily") tmp = DAILY; else if(type == "weekly") tmp = WEEKLY; else return 0; // Invalid type format // Add new event to stack, then sort events in increasing time tmp += ({ event }); tmp = sort_array(tmp, "sort_stack", this_object()); // Replace updated event arrays from tmp if(type == "once") ONCE = tmp; else if(type == "hourly") HOURLY = tmp; else if(type == "daily") DAILY = tmp; else if(type == "weekly") WEEKLY = tmp; save_events(); // Save updated event stack return 1; } // Event stack sorting routine static int sort_stack(mixed *event1, mixed *event2) { return ( event1[0] - event2[0] ); } // Event removal from specific event stack int remove_event(string type, mixed *event) { mixed *tmp; int pos; // Check accessing permissions ... ensure root command if(geteuid(previous_object()) != ROOT_UID) return 0 ; // Store stack array into temporary array if(type == "once") tmp = ONCE; else if(type == "hourly") tmp = HOURLY; else if(type == "daily") tmp = DAILY; else if(type == "weekly") tmp = WEEKLY; else return 0 ; pos = member_array(event, tmp); if(pos == -1) return 0 ; // No such event found tmp -= ({ event }); // Replace updated array back into stack if(type == "once") ONCE = tmp; else if(type == "hourly") HOURLY = tmp; else if(type == "daily") DAILY = tmp; else if(type == "weekly") WEEKLY = tmp; save_events(); return 1 ; } // External stack request query for event command mixed *query_stack(string type) { if(base_name(previous_object())!=CMD_EVENT) { if(type == "once") return copy(ONCE); else if(type == "hourly") return copy(HOURLY); else if(type == "daily") return copy(DAILY); else if(type == "weekly") return copy(WEEKLY); else if(type == "all") return ({ copy(ONCE), copy(HOURLY), copy(DAILY), copy (WEEKLY) }); return ({}); } else { if(type == "once") return ONCE; else if(type == "hourly") return HOURLY; else if(type == "daily") return DAILY; else if(type == "weekly") return WEEKLY; else if(type == "all") return ({ ONCE, HOURLY, DAILY, WEEKLY }); return ({}); } }