/* ioop.c: Function operators for input and output. */
#define _POSIX_SOURCE
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include "x.tab.h"
#include "operator.h"
#include "execute.h"
#include "data.h"
#include "memory.h"
#include "io.h"
#include "cmstring.h"
#include "config.h"
#include "ident.h"
#include "util.h"
#define FILE_BUF_SIZE 100
void op_echo(void)
{
Data *args;
/* Accept a string to echo. */
if (!func_init_1(&args, BUFFER))
return;
/* Write the string to any connection associated with this object. */
tell(cur_frame->object->dbref, args[0].u.buffer);
pop(1);
push_int(1);
}
void op_echo_file(void)
{
size_t size, i, r;
Data *args;
FILE *fp;
char *fname;
Buffer *buf;
struct stat statbuf;
int len;
/* Accept the name of a file to echo. */
if (!func_init_1(&args, STRING))
return;
/* Don't allow walking back up the directory tree. */
if (strstr(string_chars(args[0].u.str), "../")) {
cthrow(perm_id, "Filename %D is not legal.", &args[0]);
return;
}
len = string_length(args[0].u.str);
fname = TMALLOC(char, len + 6);
memcpy(fname, "text/", 5);
memcpy(fname + 5, string_chars(args[0].u.str), len);
fname[len + 5] = 0;
/* Stat the file to get its size. */
if (stat(fname, &statbuf) < 0) {
tfree_chars(fname);
cthrow(perm_id, "Cannot find file %D.", &args[0]);
return;
}
size = statbuf.st_size;
/* Open the file for reading. */
fp = open_scratch_file(fname, "r");
tfree_chars(fname);
pop(1);
if (!fp) {
cthrow(file_id, "Cannot open file %D for reading.", &args[0]);
return;
}
/* Allocate a buffer to hold the file contents. */
buf = buffer_new(size);
/* Read in the file. */
i = 0;
while (i < size) {
r = fread(buf->s + i, sizeof(unsigned char), size, fp);
if (r <= 0) {
buffer_discard(buf);
close_scratch_file(fp);
cthrow(file_id, "Trouble reading file %D.", &args[0]);
return;
}
i += r;
}
/* Write the file. */
tell(cur_frame->object->dbref, buf);
/* Discard the buffer and close the file. */
buffer_discard(buf);
close_scratch_file(fp);
push_int(1);
}
void op_disconnect(void)
{
/* Accept no arguments. */
if (!func_init_0())
return;
/* Kick off anyone assigned to the current object. */
push_int(boot(cur_frame->object->dbref));
}