Commit 695b533e authored by Robert Sprowson's avatar Robert Sprowson Committed by ROOL
Browse files

Add path manipulation commands AppPath, RemPath, PrepPath

This triplet of commands allows obey files and similar to 'edit' path variables
such that they don't grow ever longer each time the obey file is run, and to
ensure it is possible to get the priority of elements on the path as desired.

Removed a malloc/free from *SafeLogon; the other commands all assume one OSCLI
buffer of space is available on the stack and use an automatic variable.
parent 950dabbd
No preview for this file type
......@@ -2,3 +2,4 @@
NoFS:File server '%0' not found
BadFile:Corrupt CMOS file
BadVer:CMOS file is for a different OS version
WantStr:System variable must contain a string
......@@ -28,6 +28,7 @@
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <ctype.h>
#include "kernel.h"
/*From exports*/
......@@ -134,6 +135,22 @@ static int get_nvm_size(void)
return rg.r[0]?osbyte_CONFIGURE_CHECKSUM+1:rg.r[1];
}
static int stricmp(const char *first, const char *second)
{ for (;;)
{ unsigned int a = *(const unsigned char *) first++;
unsigned int b = *(const unsigned char *) second++;
if (a == 0) return -b;
if (a != b)
{ unsigned int c = (unsigned int) tolower(a);
unsigned int d = (unsigned int) tolower(b);
signed int result = c - d;
if (result != 0) return result;
}
}
}
/*------------------------------------------------------------------------*/
static os_error *Add_App (const char *tail)
......@@ -858,7 +875,7 @@ finish:
/*------------------------------------------------------------------------*/
static os_error *Safe_Logon (const char *tail)
{ struct safelogon_args {char *fs, *user, *password; char argb [os_CLI_LIMIT_RO4 + 1];} *argl;
{ struct {char *fs, *user, *password; char argb [os_CLI_LIMIT_RO4 + 1];} argl;
int station, net, context, collate;
fileswitch_fs_no temp_fs;
netfs_file_server_context file_server_context;
......@@ -868,10 +885,6 @@ static os_error *Safe_Logon (const char *tail)
tracef ("Safe_Logon\n");
argl = malloc(sizeof(struct safelogon_args));
if (argl == 0)
goto finish;
/*Fix bug: check that the temporary filing system is indeed NetFS. JRC
16th Feb 1995*/
if ((error = xosargs_read_temporary_fs (&temp_fs)) != NULL)
......@@ -879,23 +892,23 @@ static os_error *Safe_Logon (const char *tail)
if (temp_fs == fileswitch_FS_NUMBER_NETFS)
{ if ((error = xos_read_args ("fs/a,user/a,password", tail,
(char *) argl, sizeof *argl, NULL)) != NULL)
(char *) &argl, sizeof argl, NULL)) != NULL)
goto finish;
tracef ("fs \"%s\"\n" _ argl->fs);
tracef ("user \"%s\"\n" _ argl->user);
tracef ("fs \"%s\"\n" _ argl.fs);
tracef ("user \"%s\"\n" _ argl.user);
tracef ("password \"%s\"\n" _
argl->password != NULL? argl->password: "NULL");
argl.password != NULL? argl.password: "NULL");
/*If the first character of the fs is not ':', we steer clear.*/
if (argl->fs [0] == ':')
{ argl->fs++;
if (argl.fs [0] == ':')
{ argl.fs++;
/*Station number or name?*/
named_fs = xeconet_read_station_number (argl->fs, NULL, &station,
named_fs = xeconet_read_station_number (argl.fs, NULL, &station,
&net) != NULL;
if (named_fs)
tracef ("fs is named \"%s\"\n" _ argl->fs);
tracef ("fs is named \"%s\"\n" _ argl.fs);
else
tracef ("fs is numbered %d.%d\n" _ net _ station);
......@@ -920,7 +933,7 @@ static os_error *Safe_Logon (const char *tail)
file_server_context.user_name);
if (named_fs)
{ if ((error = xterritory_collate (territory_CURRENT, argl->fs,
{ if ((error = xterritory_collate (territory_CURRENT, argl.fs,
file_server_context.disc_name, territory_IGNORE_CASE,
&collate)) != NULL)
goto finish;
......@@ -932,7 +945,7 @@ static os_error *Safe_Logon (const char *tail)
file_server_context.net_no == net;
if (found_fs)
{ if ((error = xterritory_collate (territory_CURRENT, argl->user,
{ if ((error = xterritory_collate (territory_CURRENT, argl.user,
file_server_context.user_name, territory_IGNORE_CASE,
&collate)) != NULL)
goto finish;
......@@ -944,7 +957,7 @@ static os_error *Safe_Logon (const char *tail)
on? JRC 19th Dec 1994*/
netfs_read_user_info info;
sprintf (info AS request.user_name, "%s\r", argl->user);
sprintf (info AS request.user_name, "%s\r", argl.user);
tracef ("doing fs op ...\n");
if ((error = xnetfs_do_fs_op_to_given_fs
......@@ -963,7 +976,6 @@ static os_error *Safe_Logon (const char *tail)
} } } } }
finish:
free(argl);
/*Ignore errors up to this point. If there have been any, it's a safe bet
that |logon_required| is TRUE.*/
if (error != NULL)
......@@ -981,6 +993,111 @@ finish:
return error;
}
/*------------------------------------------------------------------------*/
static os_error *AppPrepRem_Path (const char *tail, int which)
{ struct {char *varname, *element; char argb [os_CLI_LIMIT_RO4 + 1];} argl;
os_error *error = NULL;
os_var_type type;
size_t existing, extra, len;
char *comma, *next, *editpath = NULL;
tracef ("App|Prep|RemPath subreason %d\n" _ which);
if ((error = xos_read_args ("v/a,e/a", tail, (char *) &argl,
sizeof argl, NULL)) != NULL)
goto finish;
/*Read the existing path variable, it could be any size*/
xos_read_var_val_size (argl.varname, 0, os_VARTYPE_STRING, (int *) &existing, NULL, &type);
if (existing == 0)
{ /*Be silent on remove of non-existent variables*/
if (which == main_REM_PATH) goto finish;
tracef ("Variable '%s' doesn't exist, acting as create\n" _ argl.varname);
which = main_APP_PATH;
}
else
{ if (type != os_VARTYPE_STRING)
{ error = main_error_lookup (ErrorBase_BootCommands + 3, "WantStr");
goto finish;
}
/*Length of contents of existing path variable*/
existing = ~existing;
}
/*For append or prepend, overallocate to allow space for the insertion*/
extra = (which != main_REM_PATH) ? (strlen (argl.element) + 1 /*Possible comma*/)
: 0;
editpath = (char *) malloc (existing + 1 /*Terminator*/ + extra);
if (editpath == NULL)
{ error = main_error_lookup (ErrorBase_BootCommands + 2, "NoMem");
goto finish;
}
if (existing)
{ error = xos_read_var_val (argl.varname, editpath, existing, 0, os_VARTYPE_STRING,
NULL, NULL, NULL);
if (error != NULL) /*Where did it go?!*/
goto finish;
}
editpath [existing] = '\0';
/*Scan the existing path elements, deleting matches with the given element*/
next = editpath;
while (*next)
{ comma = strchr (next, ',');
if (comma) *comma = '\0'; /*Isolate that portion*/
len = strlen (next);
if (comma) len++; /*Comma counted as part of the element length*/
if (stricmp (next, argl.element) == 0)
{ /*Delete it*/
tracef (" element '%s' matches subject, deleting\n" _ next);
if (!comma && (next > editpath))
{ /*Removing the last element, just trim with a terminator*/
next [-1] = '\0';
break;
}
memmove (next, &next [len], strlen (&next [len]) + 1 /*Terminator*/);
}
else
{ /*Step next*/
tracef (" element '%s'\n" _ next);
next = next + len;
if (comma) *comma = ','; /*Restore the comma*/
}
}
tracef ("After removing duplicates '%s'\n" _ editpath);
if (which != main_REM_PATH)
{ /*Firm up on that possible comma now duplicates are removed*/
len = strlen (editpath);
if (len == 0) which = main_APP_PATH;
/*Append or prepend (any remove was done implicitly)*/
if (which == main_APP_PATH)
{ if (len) strcat (editpath, ",");
strcat (editpath, argl.element);
}
else
{ memmove (&editpath [extra], editpath, strlen (editpath));
strcpy (editpath, argl.element);
editpath [extra - 1] = ',';
}
}
tracef ("After edits '%s'\n" _ editpath);
error = xos_set_var_val (argl.varname, (byte *) editpath, strlen (editpath),
0, os_VARTYPE_STRING, NULL, NULL);
finish:
free (editpath);
tracef ("App|Prep|RemPath DONE\n");
if (error != NULL)
tracef ("with error %s\n" _ error->errmess);
return error;
}
static os_error *App_Path (const char *tail) { return AppPrepRem_Path (tail, main_APP_PATH); }
static os_error *Prep_Path (const char *tail) { return AppPrepRem_Path (tail, main_PREP_PATH); }
static os_error *Rem_Path (const char *tail) { return AppPrepRem_Path (tail, main_REM_PATH); }
/*------------------------------------------------------------------------*/
static os_error *Shrink_RMA(const char *tail)
{
......@@ -1097,6 +1214,9 @@ _kernel_oserror *main_initialise (char *tail, int podule_base,
Commands [main_SAVE_CMOS] = &Save_CMOS;
Commands [main_REPEAT] = &Repeat;
Commands [main_SAFE_LOGON] = &Safe_Logon;
Commands [main_APP_PATH] = &App_Path;
Commands [main_PREP_PATH] = &Prep_Path;
Commands [main_REM_PATH] = &Rem_Path;
Commands [main_FREE_POOL] = &Free_Pool;
Commands [main_SHRINK_RMA] = &Shrink_RMA;
Commands [main_ADD_TO_RMA] = &Add_To_RMA;
......
......@@ -68,6 +68,21 @@ command-keyword-table: main_command
add-syntax:,
invalid-syntax: "Syntax: *SafeLogon [[:]<station number>|:<File server name>] <user name> [[:<CR>]<Password>]",
help-text: "*SafeLogon initialises the current (or given) file server for your use, except that if you are already logged on, it does nothing\n"),
AppPath( min-args: 2, max-args: 2,
gstrans-map: 2,
add-syntax:,
invalid-syntax: "Syntax: *AppPath <variable> <path element>",
help-text: "*AppPath appends a path element to a path variable, ensuring there are no duplicates\n"),
PrepPath( min-args: 2, max-args: 2,
gstrans-map: 2,
add-syntax:,
invalid-syntax: "Syntax: *PrepPath <variable> <path element>",
help-text: "*PrepPath prepends a path element to a path variable, ensuring there are no duplicates\n"),
RemPath( min-args: 2, max-args: 2,
gstrans-map: 2,
add-syntax:,
invalid-syntax: "Syntax: *RemPath <variable> <path element>",
help-text: "*RemPath removes a path element from a path variable\n"),
FreePool( min-args: 0, max-args: 0,
gstrans-map: 0,
add-syntax:,
......@@ -139,6 +154,21 @@ command-keyword-table: main_command
international:,
invalid-syntax: "SafeLogonSyntax",
help-text: "SafeLogonHelp"),
AppPath( min-args: 2, max-args: 2,
gstrans-map: 2,
international:,
invalid-syntax: "AppPathSyntax",
help-text: "AppPathHelp"),
PrepPath( min-args: 2, max-args: 2,
gstrans-map: 2,
international:,
invalid-syntax: "PrepPathSyntax",
help-text: "PrepPathHelp"),
RemPath( min-args: 2, max-args: 2,
gstrans-map: 2,
international:,
invalid-syntax: "RemPathSyntax",
help-text: "RemPathHelp"),
FreePool( min-args: 0, max-args: 0,
gstrans-map: 0,
international:,
......
......@@ -39,12 +39,15 @@
#define main_SAVE_CMOS 5
#define main_REPEAT 6
#define main_SAFE_LOGON 7
#define main_FREE_POOL 8
#define main_SHRINK_RMA 9
#define main_ADD_TO_RMA 10
#define main_APP_SLOT 11
#define main_X 12
#define main_COMMAND_COUNT 13
#define main_APP_PATH 8
#define main_PREP_PATH 9
#define main_REM_PATH 10
#define main_FREE_POOL 11
#define main_SHRINK_RMA 12
#define main_ADD_TO_RMA 13
#define main_APP_SLOT 14
#define main_X 15
#define main_COMMAND_COUNT 16
#define X_ENVVAR "X$Error"
#define RES_APP_PATH "Resources:$.Apps"
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment