1

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <dirent.h>
#include <sys/stat.h>
#include <ctype.h>
#include <errno.h>
#include "timeout.h"



char room[100] = "Lobby";
char home[100] = "/tmp/ehrhardt";
char myname[20] = "ehrhardt";

#define check(X) if (!(X)) { \
	printf ("You enter the computer Pool. The dungeon collapses\n."); \
	exit (1); \
	}

void chomp (char * s)
{
	int c;
	while (s) {
		c = *s;
		if (isspace (c)) {
			(*s) = 0;
			return;
		}
		s++;
	}
}

void list_objects (DIR * d, char * dirname)
{
	char filename[1000];
	struct stat buf;
	struct dirent * entry;

	check (d);
	rewinddir (d);
	while ((entry = readdir (d))) {
		sprintf (filename, "%s/%s", dirname, entry->d_name);
		if ((lstat (filename, &buf) >= 0) &&
		    ((buf.st_mode & S_IFMT) == S_IFREG) && (buf.st_size == 0)) {
			printf ("   %s\n", entry->d_name);
		}
	}
}

void list_people (DIR * d, char * dirname)
{
	char filename[1000];
	struct stat buf;
	struct dirent * entry;

	check (d);
	rewinddir (d);
	while ((entry = readdir (d))) {
		if (strcmp (entry->d_name, ".") == 0)
			continue;
		if (strcmp (entry->d_name, "..") == 0)
			continue;
		if (strcmp (entry->d_name, myname) == 0)
			continue;
		sprintf (filename, "%s/%s", dirname, entry->d_name);
		if ((lstat (filename, &buf) >= 0) &&
		    ((buf.st_mode & S_IFMT) == S_IFDIR)) {
			printf ("   %s\n", entry->d_name);
		}
	}
}

void list_exits (DIR * d, char * dirname)
{
	struct stat buf;
	struct dirent * entry;
	char filename[1000];
	int ret;

	check (d);
	rewinddir (d);
	while ((entry = readdir (d))) {
		char target[100];
		int fd;
		
		sprintf (filename, "%s/%s", dirname, entry->d_name);
		fd = open (filename, O_RDONLY);
		if (fd < 0)
			continue;
		if ((lstat (filename, &buf) >= 0) &&
		    ((buf.st_mode & S_IFMT) == S_IFREG) &&
		    (buf.st_size > 0)) {
			ret = read (fd, target, 99);
			check (ret > 0);
			target[ret] = 0;
			chomp(target);
			printf ("   %s leads to %s\n", entry->d_name, target);
		}
		close (fd);
	}
}

#define NOISE(name, filename) printf ("You here a strange noise from something called %s\n", name); check (unlink (filename) >= 0); continue;

int show_messages (int remove)
{
	char dirname[1000];
	char filename[1000];
	char buffer[1000];
	DIR * d;
	struct dirent * entry;
	struct stat buf;
	int fd, ret;
	
	sprintf (dirname, "%s/%s", room, myname);
	d = opendir (dirname);
	check (d);
	while ((entry = readdir (d))) {
		sprintf (filename, "%s/%s", dirname, entry->d_name);
		if (strcmp (entry->d_name, ".") == 0)
			continue;
		if (strcmp (entry->d_name, "..") == 0)
			continue;
		if (lstat (filename, &buf) < 0) {
			NOISE(entry->d_name, filename)
		}
		if ((buf.st_mode & S_IFMT) != S_IFREG) {
			NOISE(entry->d_name, filename);
		}
		fd = open (filename, O_RDONLY);
		if (fd < 0) {
			NOISE(entry->d_name, filename);
		}
		ret = read (fd, buffer, 999);
		if (ret <= 0) {
			close (fd);
			NOISE(entry->d_name, filename);
		}
		printf ("%s says: ", entry->d_name);
		while (ret > 0) {
			buffer[ret] = 0;
			printf ("%s", buffer);
			ret = read (fd, buffer, 999);
		}
		close (fd);
		check (unlink (filename) >= 0);
	}
	closedir (d);
	/* Try to remove the directory because we are leaving the room. */
	if (remove) {
		ret = rmdir (dirname);
		/* We could not remove the directory. The only valid reason
		 * is a message that was generated after the last call
		 * to readdir. In this case ret should be EEXIST.
		 */
		if (ret < 0) {
			check (errno == EEXIST);
			return 0;
		}
	}
	return 1;
}


#define DONE 0
#define NOEXIST -1     /* Source doen't exist */
#define NOTOBJECT -2   /* Source does exist but is not an object. */
#define NOCREATE -3    /* Cannot create target object */
#define NODELETE -4    /* Cannot delete src. */

int move_object (char * src, char * dst, char * name)
{
	char fsrc[1000];
	char fdst[1000];
	struct stat buf;
	int fd;

	sprintf (fsrc, "%s/%s", src, name);
	sprintf (fdst, "%s/%s", dst, name);

	if (lstat (fsrc, &buf) < 0)
		return NOEXIST;
	if ((buf.st_mode & S_IFMT) != S_IFREG)
		return NOTOBJECT;
	fd = open (fdst, O_RDWR | O_CREAT | O_EXCL, S_IRUSR|S_IWUSR);
	if (fd < 0)
		return NOCREATE;
	close (fd);
	if (unlink (fsrc) >= 0)
		return DONE;
	/* If we end up here there are two possibilities:
	   - we were not allowed to unlink the fsrc (permission problem etc.)
	   - someone else took the object before us.
           In both cases we try to remove fdst instead an tell the
	   caller that we didn't move the object.
	 */
	if (unlink (fdst) >= 0)
		return NODELETE;
	/* We successfully created an object in fdst, but can
	 * remove neither fsrc or fdst. Bail out. */
	check (0);
}


int main ()
{
	char line[100];
	char command[100];
	char arg[100];
	char arg2[250];
	char filename[200];
	DIR * d = opendir (room);
	int ret;
	int args;
	char * ptr;

	check (d);
	sprintf (filename, "%s/%s", room, myname);
	check (mkdir (filename, S_IRWXU) >= 0);
	while (1) {
		settimeout();
		ptr = fgets (line, 1000, stdin);
		cleartimeout();
		if (feof (stdin))
			break;
		show_messages (0);
		if (!ptr) {
			continue;
		}
		ret = sscanf (line, "%s %s %s", command, arg, arg2);
		if (ret < 1)
			continue;
		args = ret - 1;
		if (strcmp (command, "look") == 0) {
			printf ("Roomname: %s\n", room);
			printf ("Objects that are here:\n");
			list_objects (d, room);
			printf ("Exits that are here:\n");
			list_exits (d, room);
			printf ("People that are here:\n");
			list_people (d, room);
		} else if (strcmp (command, "inventory") == 0) {
			DIR * h = opendir (home);

			printf ("Objects in you inventory:\n");
			list_objects (h, home);
			closedir (h);
		} else if (strcmp (command, "go") == 0) {
			struct stat buf;
			int fd, i;
			char target[100];

			if (args != 1) {
				printf ("Where?\n");
				continue;
			}
			sprintf (filename, "%s/%s", room, arg);
			fd = open (filename, O_RDONLY);
			if (fd < 0) {
				printf ("You bump into a wall\n");
				continue;
			}
			ret = lstat (filename, &buf);
			check (ret >= 0);
			if ((buf.st_mode & S_IFMT) != S_IFREG) {
				printf ("You bump into a %s\n", arg);
				continue;
			}
			ret = read (fd, target, 99);
			check (ret >= 0);
			if (ret == 0) {
				printf ("You bump into a %s\n", arg);
				continue;
			}
			close (fd);
			for (i=0; i<100; i++) {
				if (show_messages (1))
					break;
			}
			if (i >= 100) {
				printf ("Can't leave room\n");
				check (0);
			}
			closedir (d);
			chomp (target);
			d = opendir (target);
			check (d);
			strcpy (room, target);
			sprintf (filename, "%s/%s", room, myname);
			check (mkdir (filename, S_IRWXU) >= 0);
			printf ("You enter the %s\n", target);
		} else if (strcmp (command, "take") == 0) {
			if (args != 1) {
				printf ("What?\n");
				continue;
			}
			ret = move_object (room, home, arg);
			switch (ret) {
			case DONE:
				printf ("Ok\n"); break;
			case NOEXIST:
				printf ("I don't see a %s here\n", arg); break;
			case NOTOBJECT:
				printf ("You can't take %s with you\n", arg); break;
			case NOCREATE:
				printf ("You can't take %s. Maybe you already have one\n", arg); break;
			case NODELETE:
				printf ("You can't take %s with you\n", arg); break;
			default:
				printf ("Something went wrong\n");
				check (0);
			}
		} else if (strcmp (command, "drop") == 0) {
			if (args != 1) {
				printf ("What?\n");
				continue;
			}
			ret = move_object (home, room, arg);
			switch (ret) {
			case DONE:
				printf ("Ok\n"); break;
			case NOEXIST:
				printf ("You don't have a %s\n", arg); break;
			case NOTOBJECT:
				printf ("You don't have a %s\n", arg); break;
			case NOCREATE:
				printf ("You can't drop %s here. Maybe there already is one\n", arg); break;
			case NODELETE:
				printf ("You can't drop %s\n", arg); break;
			default:
				printf ("Something went wrong\n");
				check (0);
			}
		} else if (strcmp (command, "say") == 0) {
			char * p;
			struct stat buf;
			int i, fd;

			if (args < 1) {
				printf ("To whom?\n");
				continue;
			}
			if (strcmp (arg, myname) == 0) {
				printf ("Talking to yourself, eh?\n");
				continue;
			}
			if (args < 2) {
				printf ("What?\n");
				continue;
			}
			p = line;
			/* Skip two words ... */
			for (i=0; i<2; ++i) {
				while (isspace ((int)(*p))) p++;
				while (!isspace ((int)(*p))) p++;
			}
			/* and additional whitespace */
			while (isspace ((int)(*p))) p++;
			sprintf (filename, "%s/%s", room, arg);
			if ((strcmp (arg, ".") == 0) ||
			    (strcmp (arg, "..") == 0) ||
			    (lstat (filename, &buf) < 0)) {
				printf ("You can't see %s here\n", arg);
				continue;
			}
			if ((buf.st_mode & S_IFMT) != S_IFDIR) {
				printf ("You can't talk to %s\n", arg);
				continue;
			}
			sprintf (filename, "%s/%s/%s", room, arg, myname);
			fd = open (filename, O_WRONLY|O_EXCL|O_CREAT,
			           S_IRUSR|S_IWUSR);
			if (fd < 0) {
				printf ("%s doesn't seem to take any notice of you\n", arg);
				continue;
			}
			ret = write (fd, p, strlen(p));
			if (ret < 0) {
				printf ("%s doesn't seem to take any notice of you\n", arg);
			} else if (ret != strlen (p)) {
				printf ("You have a strange feeling that %s heard only part of the message\n", arg);
			}
			close (fd);
		} else if (strcmp (command, "quit") == 0) {
			break;
		} else {
			printf ("Unknown command\n");
		}
	}
	show_messages (1);
	return 0;
}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值