diff --git a/Resources/UK/CmdHelp b/Resources/UK/CmdHelp index 38a105bf5e6399367c2e1c87e9954f48ec15dc2c..0f89259bba7213866e12d193e96858e5c0535c7b 100644 Binary files a/Resources/UK/CmdHelp and b/Resources/UK/CmdHelp differ diff --git a/Resources/UK/Messages b/Resources/UK/Messages index 73b35252360daeb522f5b6188d79636afb52b095..5936e4f319f5f77fa8be0ffe6ee0310a9a6bada1 100644 --- a/Resources/UK/Messages +++ b/Resources/UK/Messages @@ -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 diff --git a/c/main b/c/main index 6df64ce263366f9d53a025a0bea458b48bea3daf..f07755cb46034028a82ed67a70bcd3668da2081b 100644 --- a/c/main +++ b/c/main @@ -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; diff --git a/cmhg/header b/cmhg/header index 3732200c25df424e2c2d9550fa0ff43e67f85c61..6b741f4ade96568e698e7743af0364304546ac13 100644 --- a/cmhg/header +++ b/cmhg/header @@ -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:, diff --git a/h/main b/h/main index 78fa9572eff8bfafcf1789238242d5e935ecc9f4..711ec718dd3378d5ad140a14209d9aebb07127d6 100644 --- a/h/main +++ b/h/main @@ -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"