#include #include #include #include #include #include #include #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_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 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 room[100] = "Lobby"; char home[100] = "/tmp/ehrhardt"; char filename[200]; DIR * d = opendir (room); int ret; int args; check (d); while (1) { fgets (line, 1000, stdin); if (feof (stdin)) break; ret = sscanf (line, "%s %s", command, arg); 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); } 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; 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); closedir (d); chomp (target); d = opendir (target); check (d); strcpy (room, target); 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 { printf ("Unknown command\n"); } } return 0; }