This necessarily required implementing the -R option (restricted read/write).
.I @piracy
opcode. This opcode is seldom used.
.TP
+.B \-R <path>
+(class \fBRestricted\fP, name \fBrestricted\fP)
+Restricted read/write. Reading and writing files will be restricted
+only to the provided path. Ordinarily xfrotz will write or read its
+saves, transcripts, and move recordings in whatever path or directory
+the user provides when the
+.B SAVE,
+.B SCRIPT,
+or
+.B RECORDING
+commands are given. This can be undesirable if xfrotz is run in a
+restricted environment, by a front end, or by a chatbot. This option will
+cause xfrotz to write or read only to the provided path and nowhere else.
+Then the controlling process can then watch that directory for changes
+and need not worry about someone scribbling or snooping who-knows-where.
+.TP
.B \-rm <number>
(class \fBMargin\fP, name \fBrightMargin\fP)
Sets the right margin.
{"+e", ".ignoreErrors", XrmoptionNoArg, (void *)"false"},
{"-p", ".piracy", XrmoptionNoArg, (void *)"true"},
{"+p", ".piracy", XrmoptionNoArg, (void *)"false"},
+ {"-R", ".restricted", XrmoptionSepArg, (void *)NULL},
{"-t", ".tandy", XrmoptionNoArg, (void *)"true"},
{"+t", ".tandy", XrmoptionNoArg, (void *)"false"},
{"-u", ".undoSlots", XrmoptionSepArg, (void *)NULL},
&f_setup.ignore_errors},
{".Piracy", ".piracy", parse_boolean,
&f_setup.piracy},
+ {".Restricted", ".restricted", parse_string,
+ &f_setup.restricted_path},
{".Tandy", ".tandy", parse_boolean,
&f_setup.tandy},
{".UndoSlots", ".undoSlots", parse_int,
#define XK_MISCELLANY
#include <X11/keysymdef.h>
#undef XK_MISCELLANY
+#include <libgen.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int saved_replay = istream_replay;
int saved_record = ostream_record;
char file_name[FILENAME_MAX + 1];
+ int i;
+ char *tempname;
zchar answer[4];
+ char path_separator[2];
char *ext;
+ path_separator[0] = PATH_SEPARATOR;
+ path_separator[1] = 0;
+
/* Turn off playback and recording temporarily */
istream_replay = 0;
ostream_record = 0;
}
/* Use the default name if nothing was typed */
- if (file_name[0] == 0)
- strcpy(file_name, default_name);
+ if (file_name[0] == 0) {
+ /* If FILE_NO_PROMPT, restrict to currect directory. */
+ /* If FILE_NO_PROMPT and using restricted path, then */
+ /* nothing more needs to be done to restrict the */
+ /* file access there. */
+ if (flag == FILE_NO_PROMPT && f_setup.restricted_path == NULL) {
+ tempname = basename((char *)default_name);
+ strncpy(file_name, tempname, FILENAME_MAX);
+ } else
+ strcpy(file_name, default_name);
+ }
+
+ /* If we're restricted to one directory, strip any leading path left
+ * over from a previous call to os_read_file_name(), then prepend
+ * the prescribed path to the filename. Hostile leading paths won't
+ * get this far. Instead we return failure a few lines above here if
+ * someone tries it.
+ */
+ if (f_setup.restricted_path != NULL) {
+ for (i = strlen(file_name); i > 0; i--) {
+ if (file_name[i] == PATH_SEPARATOR) {
+ i++;
+ break;
+ }
+ }
+ tempname = strdup(file_name + i);
+ strncpy(file_name, f_setup.restricted_path, FILENAME_MAX);
+
+ /* Make sure the final character is the path separator. */
+ if (file_name[strlen(file_name)-1] != PATH_SEPARATOR) {
+ strncat(file_name, path_separator, FILENAME_MAX - strlen(file_name) - 2);
+ }
+ strncat(file_name, tempname, strlen(file_name) - strlen(tempname) - 1);
+ }
if (flag == FILE_NO_PROMPT) {
ext = strrchr(file_name, '.');