Author Topic: read_file help  (Read 2482 times)

Offline Dorrin

  • Acquaintance
  • *
  • Posts: 7
    • View Profile
read_file help
« on: March 13, 2014, 10:05:47 PM »
I'm trying to make a dynamic signpost where I can have one object, but based on the room  you're in, it will grab a description from another file (signpost_desc/whatever).

Problem is, whenever I do a read_file, all I get back is 0. I can run this command:
Code: [Select]
eval write(read_file("/u/d/dorrin/desc"));and I get the contents of the file, followed by Result:0

I'm reading the man file, and it says it will return 0 if I go past the end of the file OR it has a nonpositive line number, but I'm not providing any of those in the function call, just telling it to read the whole file (which is currently two lines long).

So what's the deal? I can see it working in other pieces of code (reading into variable, etc), but I can't get it to work at all.

Offline quixadhal

  • BFF
  • ***
  • Posts: 633
    • View Profile
    • WileyMUD
Re: read_file help
« Reply #1 on: March 14, 2014, 12:36:40 AM »
The 0 isn't from read_file(), it's from the write() around it (which actually is void)...

Offline melkor

  • Acquaintance
  • *
  • Posts: 35
  • Dreamer
    • View Profile
Re: read_file help
« Reply #2 on: March 14, 2014, 02:35:27 AM »
The line "Result:0" is returned from the command "eval" which you are using to test the read_file() function.
Code: [Select]
> eval write(read_file("/README"))
--A buch of stuff from the README file---
Result = 0
> eval read_file("/README")
Result = 0
>
It is the standard behavior of "eval" in order for you to have the exit code of the tested command.

If you want to read the file and display it in some description - make sure that you are putting the file into a variable, parsing it if needed and then displaying the contents of the variable in your object description.
death() is just a heartbeat() away...
Old mudlibs and drivers archive

Offline nfa

  • Acquaintance
  • *
  • Posts: 28
    • View Profile
Re: read_file help
« Reply #3 on: March 14, 2014, 03:12:35 AM »
On FR eval(exec) wraps (simplified) its arguments in a temporary file inside a
Code: [Select]
mixed do_call() { ... }block and calls it. Since there is no explicit return statement you will 0 returned. I bet that if you do
Code: [Select]
eval return read_file("/README")you will get what you expect (the file contents if file exists, 0 otherwise)

Offline Dorrin

  • Acquaintance
  • *
  • Posts: 7
    • View Profile
Re: read_file help
« Reply #4 on: March 14, 2014, 07:02:52 AM »
Ok, I think I'm heading in the right direction, but I'm still not seeing any results. The code for my signpost is as follows:

Code: [Select]
#include <mudlib.h>

inherit OBJECT;

void create()
{
    ::create();
    set("name","signpost");
    set("short","a signpost");
    set("id",({"sign","sign post","post","signpost"}));
    set("long", "This is a sign post");
    set("level",1);
    set("bulk",500);
    set("weight",2500);
    set("value",0);
    set("type/other", 1);
    set("prevent_get","How do you propose doing that?\n");
    set("prevent_insert","How do you propose doing that?\n");

}

void init()
{
    add_action("_touch", "touch");
}

string _touch()
{
    string sign_desc;
    sign_desc = read_file("/u/d/dorrin/obj/signpost_descs/workroom");
    this_player()->write("Signpost Desc: " + sign_desc);
    return 1;
}

I have also tried to just return sign_desc, return "Signpost Desc: " + sign_desc and all I get is either nothing or
Code: [Select]
~/obj> touch
Signpost Desc: 0
~/obj>

Eventually this will go into the long as an @@query_long and a dynamic lookup of the file name based on the room name, but I tried to dumb it down just to get it working

Offline melkor

  • Acquaintance
  • *
  • Posts: 35
  • Dreamer
    • View Profile
Re: read_file help
« Reply #5 on: March 14, 2014, 07:36:44 AM »
It looks logical. However i can see that the return type of the function _touch() is string but you are returning an integer.
Try the following:
Code: [Select]
int _touch() {
    string sign_desc;
    sign_desc = read_file("/u/d/dorrin/obj/signpost_descs/workroom");
    if(sign_desc) {
        write("Signpost Desc: " + sign_desc + "\n");
        return 1;
    } else {
        write("There is an error! Tell a wiz!\n");
        return 0;
    }
}

Here is the output of my little test as i do not have a working TMI-2 at the moment:
Code: [Select]
> eval string sign_desc; sign_desc  = read_file("/README"); if(sign_desc) { write("SP: "+sign_desc+"\n");  } else { write("Error!\n"); }
SP: --the contents of the /README file--

Result = 0
The above example works like a charm. But see what is happening when i try to read a file which is too large:
Code: [Select]
> eval string sign_desc; sign_desc  = read_file("/log/debug.log"); if(sign_desc) { write("SP: "+sign_desc+"\n");  } else { write("Error!\n"); }
Error: *Printable strings limited to length of 8192.

Current object: /tmp/eval_file ("/tmp/eval_file")
Current program: /tmp/eval_file.c
File: "/tmp/eval_file.c" Line: 1
"Line: 114  File: "/std/user.c" Object: /std/user#29 ("virosh") Program: "/std/user.c"
Line: 11  File: "/cmds/eval.c" Object: /cmds/eval ("/cmds/eval") Program: "/cmds/eval.c"
Line: 1  File: "/tmp/eval_file.c" Object: /tmp/eval_file ("/tmp/eval_file") Program: "/tmp/eval_file.c""
----------

>
As you can see the error is thrown even at an earlier stage. You may also try to use catch() during the execution of read_file() or make some additional checks how large the file is before reading it.

When you write your code - always write checks even if you are currently checking something. :) It is a much better way of finding where your issue is.
death() is just a heartbeat() away...
Old mudlibs and drivers archive

Offline Dorrin

  • Acquaintance
  • *
  • Posts: 7
    • View Profile
Re: read_file help
« Reply #6 on: March 14, 2014, 10:23:49 AM »
Thanks for helping to point me in the right direction. I found out what was wrong (I believe).... I needed to add a seteuid(getuid); to the create, otherwise I don't think my file had the ability to use read_file... after all the checks and everything else were in, I just kept running in to a block where the file could be found, but nothing was read into the variable.

After checking some other files, the one common things between them was that, so I added it in and bingo, I can now read the file with no problem.

Offline quixadhal

  • BFF
  • ***
  • Posts: 633
    • View Profile
    • WileyMUD
Re: read_file help
« Reply #7 on: March 14, 2014, 07:48:10 PM »
Been forever since I touched TMI-2, but if there's a pager option for the player object, you might want to make your code a little more user friendly, in case someone makes a sign that's epic novel length. :)

Essentially, I would probably run the file through a word wrapping function in case it has lines longer than the user's terminal width, and if it has more than about 20 lines, route it through a pager utility instead of splatting it out as a single write.

It's easy to say you'll never make such things, and then in 10 years either you have minions on your staff, or you've moved on and somebody else takes it over, and your name is cursed for letting people spam the maximum string length's worth of /usr/dict/words at people. :)