// The "ed" command. // Written by Buddha@TMI (2-19-92) // Expanded by Buddha@TMI (6-10-92) for file locking. // This file allows entry into the "ed" editor, and keeps track of // people editing and what file they are editing, so that there are // no stupid accidents involving two people editing the same file and // losing changes. // This is part of the TMI mudlib. To strip away this header is very wrong. // Very very wrong. // Butchered by Robocoder (6-23-93) to use file locking daemon #include <flock.h> #include <mudlib.h> #include <logs.h> #include <uid.h> inherit DAEMON ; int cmd_ed(string file) { mixed *dir; int test; string tmp, err; if (in_edit(this_player())) { // get real! you can't do this! notify_fail("You are already editing a file.\n"); return 0; } // set our permissions. seteuid(geteuid(this_player())); // If they haven't given an arguement as to what file... if (!file) file=(string)this_player()->query("cwf"); if (!file) { write("Editing: [no file specified]\n"); ed(); return 1; } // get the filename to edit tmp = (string)this_player()->query("cwd"); file = resolv_path(tmp, file); // Check if there is such a directory .. dir = explode(file, "/"); if (file_size(implode( dir[0..sizeof(dir)-2], "/")) != -2) { write("Ed: No such directory file path.\n"); return 1; } // Check to make sure the file isn't actually a directory. if (directory_exists(file)) { notify_fail("Ed: Directory with that name already exists.\n"); return 0; } // Can we write here? err = catch( test = write_file(file, "") ); if (err) { write("Ed: Could not edit requested file.\n" + err ); return 1; } // now check and see if the file is being edited by someone else. if (test) { if (file_size(file) == 0) rm(file); if (!(file_lock(file, F_LOCK))) { // in this case, it is, so we make a temp copy. tmp = "/tmp/" + geteuid(this_player()) + "." + implode(explode(file, "/"), "_"); write("That file is being edited by " + capitalize(geteuid(query_lock_object(file))) + ".\n"); if (!(file_lock(tmp, F_LOCK))) { write("Ed: Unable to create temporary file.\n"); return 1; } // cp(file, tmp); // Is cp broken? if (file_size(tmp)) rm(tmp); if (file_size(file) > 0) write_file(tmp, read_file(file)); file = tmp; } } // Now let's make the message you see as you go into ed. tmp = "Editing: " + file; // Can we write here? err = catch( test = write_file(file, "") ); if (err) { write("Ed: Could not edit requested file.\n" + err ); file_lock(file, F_UNLOCK); return 1; } if (!test) tmp += " [read only]"; // is it new? else if (!file_size(file)) tmp += " [new file]"; tmp += "\n"; // write the message that we're editing a file... write(tmp); this_player()->set("cwf",file); // Yes, the evil admin logging... it can be circumvented, but // this tells us at least most of what gets changed. // actually, this would be better if it only logged when a crucial // file is actually changed. #ifdef ED_LOG log_file(ED_LOG, wrap(capitalize(geteuid(this_player())) + " : \"" + file + "\" [" + extract(ctime(time()), 4, 15) + "]")); #endif // okay, let's invoke the editor, and have it go to the done function after. ed(file, "done_editing"); return 1; } void done_editing() { string file; int access, size; if (!geteuid(this_player())) return; file = query_lock_filename(this_player()); access = 0; if (file && (size = file_size(file)) >= 0) { access = write_file(file, ""); if (!size) rm(file); } if ((!file || !(file_lock(file, F_UNLOCK))) && access) { seteuid(ROOT_UID); log_file("ed_accidents", geteuid(this_player()) + " not listed\n"); } return; } void query_editors() { query_locks(); } int clean_up() { return 0; }