/* editor.c */
/* $Id: editor.c,v 1.4 1993/08/22 04:54:02 nils Exp $ */
#include <stdio.h>
#include <sys/types.h>
#ifdef NeXT
#include <sys/dir.h>
#else
# include <dirent.h>
#endif
#include "interface.h"
#include "db.h"
#include "net.h"
#include "editor.h"
#include "externs.h"
static void prompt(dsc)
struct descriptor_data *dsc;
{
(void)queue_string(dsc, EPROMPT);
}
static void print(dsc, message, option)
struct descriptor_data *dsc;
char *message;
int option; /* true if display for no prompts; false otherwise */
{
(void)queue_string(dsc, message);
(void)queue_write(dsc, "\n", 1);
}
int valid_filename P((char *));
int valid_filename(fname)
char *fname;
{
char *k;
puts(fname);
if (!fname || *fname == '\0') {
puts("null");
return 0;
}
if (!strncmp (fname, "../", 3) ||
!strcmp (fname, "..")) {
puts("back");
return 0;
}
if ((k = strchr (fname, '/')))
return valid_filename (k+1);
puts("ok.");
return 1;
}
void do_mkdir(player, raw_fname)
dbref player;
char *raw_fname;
{
if(!valid_filename(raw_fname)) {
notify(player, "Sorry, that isn't a valid filename.");
return;
}
if(mkdir(make_pfile(player,raw_fname),0755)<0) {
notify(player, tprintf("Error creating %s",raw_fname));
return;
}
notify(player, tprintf("directory %s created.",raw_fname));
}
void do_ls(player, raw_fname)
dbref player;
char *raw_fname;
/*
{
DIR *dirlist;
#if defined(SYSV) || defined(SYSV_MAYBE) || defined(HPUX)
struct dirent *ent;
#else
struct direct *ent;
#endif
char *fname;
char opbuf[1024];
if (*raw_fname == '\0')
raw_fname=".";
else if(!valid_filename(raw_fname)) {
notify(player,"Sorry, that isn't a valid filename.");
return;
}
dirlist = opendir(fname = make_pfile(player,raw_fname));
if(!dirlist) {
notify(player, "Sorry, i can't open that file.");
return;
}
while (ent = readdir (dirlist))
if(strcmp(ent->d_name, "..")) {
struct stat statbuf;
sprintf(opbuf,"%s/%s",fname, ent->d_name);
lstat(opbuf,&statbuf);
sprintf(opbuf,"%-15s%c %d",
ent->d_name,
((statbuf.st_mode&S_IFMT)==S_IFDIR)?'/':
((statbuf.st_mode&S_IFMT)==S_IFLNK)?'@':
' ',
statbuf.st_size);
notify(player, opbuf);
}
closedir (dirlist);
}
*/ {}
char *make_pfile(player, fname)
dbref player;
char *fname;
{
static char op[1024];
if(strlen(fname)>900)
fname[900]='\0';
sprintf(op,"files/p/%d/%s", player, fname);
return op;
}
void do_editfile(player, fname)
dbref player;
char *fname;
{
struct descriptor_data *dsc;
char *name_buffer;
char line_buff[80];
FILE *fp;
struct top *head;
struct buffer *p;
int count = 0;
if (Typeof(player) != TYPE_PLAYER) {
notify(player,"Excuse me, but you aren't a player.");
return;
}
for (dsc=descriptor_list; dsc->state==CONNECTED && dsc->player != player;
dsc=dsc->next);
if (dsc == NULL) {
notify(player,"But you don't seem to be connected!");
return;
}
if (*fname == '\0') {
notify(player, "Syntax: +edit <filename>");
return;
}
if (!valid_filename(fname)) {
notify(player, "Sorry, that isn't a valid filename.");
return;
}
/* make SURE filename does not overrun buffer, or disaster! */
if (strlen(fname)+strlen(db[player].name)+10 > 80) {
fname[80 - strlen(db[player].name) - 10] = '\0';
}
name_buffer = make_pfile (player, fname);
if ((fp = fopen(name_buffer, "r")) == NULL)
if ((fp = fopen(name_buffer, "w")) == NULL) {
notify(player,"Can't open/create file!");
return;
}
fprintf(stderr, tprintf("Player %d(dsc %d) opened %s for editing.\n",
player, dsc,name_buffer));
MALLOC(head, struct top, 1);
MALLOC(head->next, struct buffer, 1);
strcpy(head->filename, name_buffer);
dsc->edit_buff = head;
p = head->next;
p->next = NULL;
while (fgets(line_buff, 80, fp) != NULL) {
MALLOC(p->next, struct buffer, 1);
p = p->next;
line_buff[strlen(line_buff)-1] = '\0';
strcpy(p->line, line_buff);
p->next = NULL;
count++;
}
head->state = COMMAND;
head->issaved = 1;
fclose(fp);
notify(player, "Welcome to MUSEdit V1.0");
notify(player, "Type \"h\" for help.");
notify(player, tprintf("Editing \"%s\", %d lines.", fname, count));
prompt(dsc);
}
void parse_range(head, range, p1, p2, start_line)
struct top *head;
char *range;
struct buffer **p1;
struct buffer **p2;
int *start_line;
{
char *c;
int l1, l2, t, count;
if (!*range) { /* no arguments supplied */
*p1 = head->next->next;
*p2 = NULL;
if (start_line) *start_line = 1;
return;
}
c = strchr(range, '-');
if ((l1 = atoi(range)) <= 0) l1 = 1;
if (c) {
*c++ = '\0';
if ((l2 = atoi(c)) <= 0) l2 = 0;
} else l2 = l1;
if ((l1 > l2) && l2) {
t = l1;
l1 = l2;
l2 = t;
}
*p1 = head->next->next;
count = 1;
while ((count < l1) && (*p1 != NULL)) {
count++;
*p1 = (*p1)->next;
}
if (!l2) {
*p2 = NULL;
} else {
for (*p2 = *p1; (count < l2) && (*p2 != NULL);
count++, *p2 = (*p2)->next);
}
if (start_line) *start_line = l1;
return;
}
void do_ehelp(player)
dbref player;
{
spit_file(player,EDIT_HELP_FILE,NULL);
return;
}
void do_list(player, head, string)
dbref player;
struct top *head;
char *string;
{
struct buffer *l, *u;
parse_range(head, string, &l, &u, &(head->linenum));
while ((l != NULL) && (u->next != l)) {
notify(player, tprintf("[%2d]: %s", head->linenum, l->line));
l = l->next;
head->linenum++;
}
}
void do_esearch(player, head, string, case_sense)
dbref player;
struct top *head;
char *string;
int case_sense;
{
int matches = 0, linenum = 0;
struct buffer *s;
char *t, *u, *v;
for (s = head->next->next; s; s = s->next) {
linenum++;
t = s->line;
while(*t) {
u = t;
v = string;
while (*v && ((case_sense) ? *v : to_lower(*v))
== ((case_sense) ? *u : to_lower(*u))) v++, u++;
if (*v == '\0') {
matches++;
notify(player,
tprintf("[%2d]: %s",linenum,s->line));
break;
}
t++;
}
}
if (matches == 0) notify(player, "No matches found.");
else notify(player, tprintf("%d matches found.",matches));
}
void do_delete(dsc, player, head, string)
struct descriptor_data *dsc;
dbref player;
struct top *head;
char *string;
{
struct buffer *l;
if ((head->state == COMMAND) && !*string) {
print(dsc, "Really delete everything? (y/n) ", 1);
head->state = DELETING;
} else {
parse_range(head, string, &(head->current),
&(head->bound), NULL);
head->issaved = 0;
for (l = head->next; l->next != head->current; l = l->next);
if (head->bound == NULL) l->next = NULL;
else l->next = head->bound->next;
l = head->current->next;
while (head->current != head->bound->next) {
free(head->current);
head->current = l;
l = l->next;
}
notify(player, "Deleted.");
}
}
void do_write(player, head, string)
dbref player;
struct top *head;
char *string;
{
struct buffer *p;
FILE *fp;
char fname[80];
if (head->next->next == NULL) {
unlink(head->filename);
} else {
if (*string == '\0') strcpy(fname, head->filename);
else {
if (strlen(string)+strlen(db[player].name)+10 > 80) {
string[80-strlen(db[player].name)-10] = '\0';
}
sprintf(fname, tprintf("./files/p/%s/%s",
db[player].name, string));
}
if ((fp = fopen(fname, "w")) == NULL ) {
notify(player, "Error opening file!");
fprintf(stderr,"File I/O error from %s.",
db[player].name);
return;
}
for (p = head->next->next; p != NULL; p = p->next) {
fputs(p->line, fp);
fputs("\n", fp);
}
fclose(fp);
}
notify(player, "Written.");
head->issaved=1;
}
void set_change(dsc, player, head, string)
struct descriptor_data *dsc;
dbref player;
struct top *head;
char *string;
{
head->state=CHANGE;
parse_range(head, string, &(head->current), &(head->bound),
&(head->linenum));
head->bound = head->bound->next;
notify(player, tprintf("[%2d]: %s", head->linenum,
head->current->line));
print(dsc, tprintf("[%2d]: ", head->linenum), 0);
}
void set_insert(dsc, player, head, string)
struct descriptor_data *dsc;
dbref player;
struct top *head;
char *string;
{
head->state=INSERT;
parse_range(head, string, &(head->current), &(head->bound),
&(head->linenum));
head->bound = head->current->next;
if (head->bound == NULL) {
notify(player, "Use \"a\" to add to the end of a file.");
head->state=COMMAND;
return;
}
notify(player, tprintf("[%2d]: %s", head->linenum,
head->current->line));
print(dsc, tprintf("[%2d]: ", ++head->linenum), 0);
}
void set_add(dsc, player, head)
struct descriptor_data *dsc;
dbref player;
struct top *head;
{
head->state=ADD;
head->current = head->next;
head->linenum = 1;
while (head->current->next != NULL) {
head->current = head->current->next;
head->linenum++;
}
print(dsc, tprintf("[%2d]: ", head->linenum), 0);
}
void do_change(dsc, player, head, string)
struct descriptor_data *dsc;
dbref player;
struct top *head;
char *string;
{
if (strcmp(string,".")) {
if (strlen(string) > 80) string[80] = '\0';
strcpy(head->current->line, string);
head->current = head->current->next;
head->linenum++;
head->issaved=0;
if (head->current == head->bound) head->state = COMMAND;
else {
notify(player, tprintf("[%2d]: %s",
head->linenum, head->current->line));
print(dsc, tprintf("[%2d]: ", head->linenum), 0);
}
} else head->state = COMMAND;
}
void do_add(dsc, head, string)
struct descriptor_data *dsc;
struct top *head;
char *string;
{
if (strcmp(string,".")) {
MALLOC(head->current->next, struct buffer, 1);
head->current = head->current->next;
if (strlen(string) > 80) string[80] = '\0';
strcpy(head->current->line, string);
head->linenum++;
print(dsc, tprintf("[%2d]: ", head->linenum), 0);
} else {
head->issaved=0;
head->state = COMMAND;
head->current->next = NULL;
}
}
void do_insert(dsc, head, string)
struct descriptor_data *dsc;
struct top *head;
char *string;
{
if (strcmp(string,".")) {
MALLOC(head->current->next, struct buffer, 1);
head->current = head->current->next;
if (strlen(string) > 80) string[80] = '\0';
strcpy(head->current->line, string);
head->linenum++;
if((head->linenum%10)==0)
print(dsc, tprintf("%2d: ", head->linenum), 0);
head->issaved=0;
} else {
head->state = COMMAND;
head->current->next = head->bound;
}
}
void do_quit(dsc, player, head)
struct descriptor_data *dsc;
dbref player;
struct top *head;
{
if (head->state == COMMAND && !head->issaved) {
print(dsc, "But you haven't saved your changes! Really quit? (y/n) ", 1);
head->state = QUITTING;
} else {
dsc->edit_buff = NULL;
if (head->next->next == NULL) unlink(head->filename);
notify(player, "Bye.");
head->state = QUITTING;
}
}
void edit_command(dsc, player, string)
struct descriptor_data *dsc;
dbref player;
char *string;
{
char cmd = *string;
struct top *head;
head = dsc->edit_buff;
if (head->state == COMMAND) {
for (string++; *string && *string == ' '; string++);
switch(cmd) {
case 'c' :
case 'C' : set_change(dsc, player, head, string);
break;
case 'l' :
case 'L' : do_list(player, head, string);
break;
case 's' :
do_esearch(player, head, string, 0);
break;
case 'S' : do_esearch(player, head, string, 1);
break;
case 'i' :
case 'I' : set_insert(dsc, player, head, string);
break;
case 'h' :
case 'H' : do_ehelp(player);
break;
case 'a' :
case 'A' : set_add(dsc, player, head);
break;
case 'd' :
case 'D' : do_delete(dsc, player, head, string);
break;
case 'w' :
case 'W' : do_write(player, head, string);
break;
case 'q' :
case 'Q' : do_quit(dsc, player, head);
break;
default : notify(player,
"Unknown command. (Type \"h\" for help.)");
break;
}
if (head->state == COMMAND) prompt(dsc);
return;
} else {
switch (head->state) {
case CHANGE :
do_change(dsc, player, head, string);
break;
case ADD :
do_add(dsc, head, string);
break;
case INSERT :
do_insert(dsc, head, string);
break;
case DELETING :
if (to_lower(*string) == 'y')
do_delete(dsc, player, head, "");
head->state = COMMAND;
break;
case QUITTING :
if (to_lower(*string) == 'y') {
do_quit(dsc, player, head);
return;
} else head->state = COMMAND;
}
if (head->state == COMMAND) prompt(dsc);
}
}
/********************************* EDITOR.C *********************************/