// 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; }