]> granicus.if.org Git - nethack/commitdiff
*** empty log message ***
authorjwalz <jwalz>
Sat, 5 Jan 2002 21:05:58 +0000 (21:05 +0000)
committerjwalz <jwalz>
Sat, 5 Jan 2002 21:05:58 +0000 (21:05 +0000)
sys/share/pcsys.c [new file with mode: 0644]

diff --git a/sys/share/pcsys.c b/sys/share/pcsys.c
new file mode 100644 (file)
index 0000000..dee9486
--- /dev/null
@@ -0,0 +1,552 @@
+/*     SCCS Id: @(#)pcsys.c    3.3     1999/12/10                */
+/* NetHack may be freely redistributed.  See license for details. */
+
+/*
+ *  System related functions for MSDOS, OS/2, TOS, and Windows NT
+ */
+
+#define NEED_VARARGS
+#include "hack.h"
+#include "wintty.h"
+
+#include <ctype.h>
+#include <fcntl.h>
+#ifndef MSDOS                  /* already done */
+#include <process.h>
+#endif
+#ifdef __GO32__
+#define P_WAIT         0
+#define P_NOWAIT       1
+#endif
+#ifdef TOS
+#include <osbind.h>
+#endif
+#if defined(MSDOS) && !defined(__GO32__)
+#define findfirst findfirst_file
+#define findnext findnext_file
+#define filesize filesize_nh
+#endif
+
+
+#if defined(MICRO) || defined(WIN32) || defined(OS2)
+void FDECL(nethack_exit,(int));
+#else
+#define nethack_exit exit
+#endif
+static void NDECL(msexit);
+
+
+#ifdef MOVERLAY
+extern void __far __cdecl _movepause( void );
+extern void __far __cdecl _moveresume( void );
+extern unsigned short __far __cdecl _movefpause;
+extern unsigned short __far __cdecl _movefpaused;
+#define     __MOVE_PAUSE_DISK    2   /* Represents the executable file */
+#define     __MOVE_PAUSE_CACHE   4   /* Represents the cache memory */
+#endif /* MOVERLAY */
+
+#ifdef MFLOPPY
+STATIC_DCL boolean NDECL(record_exists);
+# ifndef TOS
+STATIC_DCL boolean NDECL(comspec_exists);
+# endif
+#endif
+
+#ifdef WIN32CON
+extern int GUILaunched;    /* from nttty.c */
+#endif
+
+#ifdef MICRO
+
+void
+flushout()
+{
+       (void) fflush(stdout);
+       return;
+}
+
+static const char *COMSPEC =
+# ifdef TOS
+"SHELL";
+# else
+"COMSPEC";
+# endif
+
+#define getcomspec() nh_getenv(COMSPEC)
+
+# ifdef SHELL
+int
+dosh()
+{
+       extern char orgdir[];
+       char *comspec;
+# ifndef __GO32__
+       int spawnstat;
+# endif
+#if defined(MSDOS) && defined(NO_TERMS)
+       int grmode = iflags.grmode;
+#endif
+       if ((comspec = getcomspec())) {
+#  ifndef TOS  /* TOS has a variety of shells */
+               suspend_nhwindows("To return to NetHack, enter \"exit\" at the system prompt.\n");
+#  else
+#   if defined(MSDOS) && defined(NO_TERMS)
+               grmode = iflags.grmode;
+#   endif
+               suspend_nhwindows((char *)0);
+#  endif /* TOS */
+               chdirx(orgdir, 0);
+#  ifdef __GO32__
+               if (system(comspec) < 0) {  /* wsu@eecs.umich.edu */
+#  else
+#   ifdef MOVERLAY
+       /* Free the cache memory used by overlays, close .exe */
+       _movefpause |= __MOVE_PAUSE_DISK;
+       _movefpause |= __MOVE_PAUSE_CACHE;
+       _movepause();
+#   endif
+               spawnstat = spawnl(P_WAIT, comspec, comspec, (char *)0);
+#   ifdef MOVERLAY
+                _moveresume();
+#   endif
+
+               if ( spawnstat < 0) {
+#  endif
+                       raw_printf("Can't spawn \"%s\"!", comspec);
+                       getreturn("to continue");
+               }
+#  ifdef TOS
+/* Some shells (e.g. Gulam) turn the cursor off when they exit */
+               if (iflags.BIOS)
+                       (void)Cursconf(1, -1);
+#  endif
+               chdirx(hackdir, 0);
+               get_scr_size(); /* maybe the screen mode changed (TH) */
+#  if defined(MSDOS) && defined(NO_TERMS)
+               if (grmode) gr_init();
+#  endif
+               resume_nhwindows();
+       } else
+               pline("Can't find %s.",COMSPEC);
+       return 0;
+}
+# endif /* SHELL */
+
+# ifdef MFLOPPY
+
+void
+eraseall(path, files)
+const char *path, *files;
+{
+       char buf[PATHLEN];
+       char *foundfile;
+
+       foundfile = foundfile_buffer();
+       Sprintf(buf, "%s%s", path, files);
+       if (findfirst(buf))
+           do {
+              Sprintf(buf, "%s%s", path, foundfile);
+               (void) unlink(buf);
+           } while (findnext());
+       return;
+}
+
+/*
+ * Rewritten for version 3.3 to be faster
+ */
+void
+copybones(mode)
+int mode;
+{
+       char from[PATHLEN], to[PATHLEN], last[13];
+       char *frompath, *topath;
+       char *foundfile;
+#  ifndef TOS
+       int status;
+       char copy[8], *comspec;
+#  endif
+
+       if (!ramdisk)
+               return;
+
+       /* Find the name of the last file to be transferred
+        */
+       frompath = (mode != TOPERM) ? permbones : levels;
+       foundfile = foundfile_buffer();
+       last[0] = '\0';
+       Sprintf(from, "%s%s", frompath, allbones);
+       topath = (mode == TOPERM) ? permbones : levels;
+#  ifdef TOS
+       eraseall(topath, allbones);
+#  endif
+       if (findfirst(from))
+               do {
+#  ifdef TOS
+                       Sprintf(from, "%s%s", frompath, foundfile);
+                       Sprintf(to, "%s%s", topath, foundfile);
+                       if (_copyfile(from, to))
+                               goto error_copying;
+#  endif
+                       Strcpy(last, foundfile);
+               } while (findnext());
+#  ifdef TOS
+       else
+               return;
+#  else
+       if (last[0]) {
+               Sprintf(copy, "%cC copy",switchar());
+
+               /* Remove any bones files in `to' directory.
+                */
+               eraseall(topath, allbones);
+
+               /* Copy `from' to `to' */
+               Sprintf(to, "%s%s", topath, allbones);
+               comspec = getcomspec();
+               status =spawnl(P_WAIT, comspec, comspec, copy, from,
+                       to, "> nul", (char *)0);
+       } else
+               return;
+#  endif /* TOS */
+
+       /* See if the last file got there.  If so, remove the ramdisk bones
+        * files.
+        */
+       Sprintf(to, "%s%s", topath, last);
+       if (findfirst(to)) {
+               if (mode == TOPERM)
+                       eraseall(frompath, allbones);
+               return;
+       }
+
+#  ifdef TOS
+error_copying:
+#  endif
+       /* Last file didn't get there.
+        */
+       Sprintf(to, "%s%s", topath, allbones);
+       msmsg("Can't copy \"%s\" to \"%s\" -- ", from, to);
+#  ifndef TOS
+       if (status < 0)
+           msmsg("can't spawn \"%s\"!", comspec);
+       else
+#  endif
+           msmsg((freediskspace(topath) < filesize(from)) ?
+           "insufficient disk space." : "bad path(s)?");
+       if (mode == TOPERM) {
+               msmsg("Bones will be left in \"%s\"\n",
+                       *levels ? levels : hackdir);
+       } else {
+               /* Remove all bones files on the RAMdisk */
+               eraseall(levels, allbones);
+               playwoRAMdisk();
+       }
+       return;
+}
+
+void
+playwoRAMdisk()
+{
+       int c;
+
+       msmsg("Do you wish to play without a RAMdisk? [yn] (n)");
+
+       /* Set ramdisk false *before* exit-ing (because msexit calls
+        * copybones)
+        */
+       ramdisk = FALSE;
+       c = tgetch(); if (c == 'Y') c = 'y';
+       if (c != 'y') {
+               settty("Be seeing you...\n");
+               nethack_exit(EXIT_SUCCESS);
+       }
+       set_lock_and_bones();
+       return;
+}
+
+int
+saveDiskPrompt(start)
+int start;
+{
+       char buf[BUFSIZ], *bp;
+       char qbuf[QBUFSZ];
+
+       int fd;
+
+       if (flags.asksavedisk) {
+               /* Don't prompt if you can find the save file */
+               if ((fd = open_savefile()) >= 0) {
+                       (void) close(fd);
+                       return 1;
+               }
+               clear_nhwindow(WIN_MESSAGE);
+               pline("If save file is on a save disk, insert that disk now.");
+               mark_synch();
+               Sprintf(qbuf,"File name (default \"%s\"%s) ?", SAVEF,
+                       start ? "" : ", <Esc> cancels save");
+               getlin(qbuf, buf);
+               clear_nhwindow(WIN_MESSAGE);
+               if (!start && *buf == '\033')
+                       return 0;
+
+               /* Strip any whitespace. Also, if nothing was entered except
+                * whitespace, do not change the value of SAVEF.
+                */
+               for (bp = buf; *bp; bp++)
+                       if (!isspace(*bp)) {
+                               strncpy(SAVEF, bp, PATHLEN);
+                               break;
+                       }
+       }
+       return 1;
+}
+
+/* Return 1 if the record file was found */
+STATIC_OVL boolean
+record_exists()
+{
+       FILE *fp;
+
+       fp = fopen_datafile(RECORD, "r", TRUE);
+       if (fp) {
+               fclose(fp);
+               return TRUE;
+       }
+       return FALSE;
+}
+#endif /* MFLOPPY */
+
+# ifdef TOS
+#define comspec_exists() 1
+# else
+#  ifdef MFLOPPY
+/* Return 1 if the comspec was found */
+STATIC_OVL boolean
+comspec_exists()
+{
+       int fd;
+       char *comspec;
+
+       if ((comspec = getcomspec()))
+               if ((fd = open(comspec, O_RDONLY)) >= 0) {
+                       (void) close(fd);
+                       return TRUE;
+               }
+       return FALSE;
+}
+#  endif /* MFLOPPY */
+# endif
+
+
+# ifdef MFLOPPY
+/* Prompt for game disk, then check for record file.
+ */
+void
+gameDiskPrompt()
+{
+       if (flags.asksavedisk) {
+               if (record_exists() && comspec_exists())
+                       return;
+               (void) putchar('\n');
+               getreturn("when the game disk has been inserted");
+       }
+       if (comspec_exists() && record_exists())
+               return;
+
+       if (!comspec_exists())
+               msmsg("\n\nWARNING: can't find command processor \"%s\"!\n", getcomspec());
+       if (!record_exists())
+               msmsg("\n\nWARNING: can't find record file \"%s\"!\n", RECORD);
+       msmsg("If the game disk is not in, insert it now.\n");
+       getreturn("to continue");
+       return;
+}
+# endif /* MFLOPPY */
+#endif /* MICRO */
+
+/*
+ * Add a backslash to any name not ending in /, \ or :  There must
+ * be room for the \
+ */
+void
+append_slash(name)
+char *name;
+{
+       char *ptr;
+
+       if (!*name)
+               return;
+       ptr = name + (strlen(name) - 1);
+       if (*ptr != '\\' && *ptr != '/' && *ptr != ':') {
+               *++ptr = '\\';
+               *++ptr = '\0';
+       }
+       return;
+}
+
+void
+getreturn(str)
+const char *str;
+{
+#ifdef TOS
+       msmsg("Hit <Return> %s.", str);
+#else
+       msmsg("Hit <Enter> %s.", str);
+#endif
+       while (Getchar() != '\n') ;
+       return;
+}
+
+void
+msmsg VA_DECL(const char *, fmt)
+       VA_START(fmt);
+       VA_INIT(fmt, const char *);
+# if defined(MSDOS)
+       if (iflags.grmode)
+               gr_finish();
+# endif
+       Vprintf(fmt, VA_ARGS);
+       flushout();
+       VA_END();
+       return;
+}
+
+/*
+ * Follow the PATH, trying to fopen the file.
+ */
+#ifdef TOS
+# ifdef __MINT__
+#define PATHSEP ':'
+# else
+#define PATHSEP ','
+# endif
+#else
+#define PATHSEP ';'
+#endif
+
+FILE *
+fopenp(name, mode)
+const char *name, *mode;
+{
+       char buf[BUFSIZ], *bp, *pp, lastch = 0;
+       FILE *fp;
+
+       /* Try the default directory first.  Then look along PATH.
+        */
+       (void) strncpy(buf, name, BUFSIZ - 1);
+       buf[BUFSIZ-1] = '\0';
+       if ((fp = fopen(buf, mode)))
+               return fp;
+       else {
+               int ccnt = 0;
+               pp = getenv("PATH");
+               while (pp && *pp) {
+                       bp = buf;
+                       while (*pp && *pp != PATHSEP) {
+                               lastch = *bp++ = *pp++;
+                               ccnt++;
+                       }
+                       if (lastch != '\\' && lastch != '/') {
+                               *bp++ = '\\';
+                               ccnt++;
+                       }
+                       (void) strncpy(bp, name, (BUFSIZ - ccnt) - 2);
+                       bp[BUFSIZ-1] = '\0';
+                       if ((fp = fopen(buf, mode)))
+                               return fp;
+                       if (*pp)
+                               pp++;
+               }
+       }
+#ifdef OS2_CODEVIEW /* one more try for hackdir */
+       (void) strncpy(buf, hackdir, BUFSZ);
+       buf[BUFSZ-1] = '\0';
+       if ((strlen(name) + 1 + strlen(buf)) < BUFSZ - 1) {
+               append_slash(buf);
+               Strcat(buf,name);
+       } else 
+               impossible("fopenp() buffer too small for complete filename!");
+       if(fp = fopen(buf,mode))
+               return fp;
+#endif
+       return (FILE *)0;
+}
+
+#if defined(MICRO) || defined(WIN32) || defined(OS2)
+void nethack_exit(code)
+int code;
+{
+       msexit();
+#ifdef MTHREAD_VIEW
+       if (iflags.mthreaded) nh_thread_exit(code);  /* no return from this */
+       else
+#endif
+       exit(code);
+}
+
+/* Chdir back to original directory
+ */
+#ifdef TOS
+extern boolean run_from_desktop;       /* set in pcmain.c */
+#endif
+
+static void msexit()
+{
+#ifdef CHDIR
+       extern char orgdir[];
+#endif
+
+       flushout();
+#ifndef TOS
+# ifndef WIN32
+       enable_ctrlP();         /* in case this wasn't done */
+# endif
+#endif
+#ifdef MFLOPPY
+       if (ramdisk) copybones(TOPERM);
+#endif
+#ifdef CHDIR
+       chdir(orgdir);          /* chdir, not chdirx */
+       chdrive(orgdir);
+#endif
+#ifdef TOS
+       if (run_from_desktop)
+           getreturn("to continue"); /* so the user can read the score list */
+# ifdef TEXTCOLOR
+       if (colors_changed)
+               restore_colors();
+# endif
+#endif
+#ifdef WIN32CON
+       /* Only if we started from the GUI, not the command prompt,
+        * we need to get one last return, so the score board does
+        * not vanish instantly after being created.
+        * GUILaunched is defined and set in nttty.c.
+        */
+
+       if (GUILaunched) getreturn("to end");
+#endif
+       return;
+}
+#ifdef WIN32
+/*
+ * This is a kludge.  Just before the release of 3.3.0 the latest
+ * version of a popular MAPI mail product was found to exhibit
+ * a strange result where the current directory was changed out
+ * from under NetHack resulting in a failure of all subsequent
+ * file operations in NetHack.  This routine is called prior
+ * to all file open/renames/deletes in file.c.
+ *
+ * A more elegant solution will be sought after 3.3.0 is released.
+ */
+void dircheck()
+{
+       char dirbuf[BUFSZ];
+       dirbuf[0] = '\0';
+       if (getcwd(dirbuf, sizeof dirbuf) != (char *)0)
+               /* pline("%s,%s",dirbuf,hackdir); */
+               if (strcmp(dirbuf,hackdir) != 0)
+                       chdir(hackdir);         /* chdir, not chdirx */
+}
+#endif
+#endif /* MICRO || WIN32 || OS2 */