|
|
/********************************************************************/ /** Microsoft LAN Manager **/ /** Copyright(c) Microsoft Corp., 1987-1990 **/ /********************************************************************/
/*
* Switches.c - switch handling routines * * ??/??/??, ??????, initial code * 10/31/88, erichn, uses OS2.H instead of DOSCALLS * 12/04/88, erichn, DOS LM integration * 06/08/89, erichn, canonicalization sweep, stronger typing * 02/20/91, danhi, change to use lm 16/32 mapping layer */
#define INCL_NOCOMMON
#include <os2.h>
#include <apperr.h>
#include <lmerr.h>
#include <stdio.h>
#include <process.h>
#include <ctype.h>
#include <malloc.h>
#include "netcmds.h"
#include "nettext.h"
/* External variables */
int DOSNEAR FASTCALL firstswitch(TCHAR *known) { if (SwitchList[0] == NULL) return 0; if (sw_compare(known, SwitchList[0]) >= 0) return 1; else return 0; }
/*
* Is the cmd line a valid form of NET ADMIN /C */ int DOSNEAR FASTCALL IsAdminCommand(VOID) { if (!SwitchList[0] || !ArgList[1]) return 0; _tcsupr(SwitchList[0]); return (IsComputerName(ArgList[1]) && (sw_compare(swtxt_SW_ADMIN_COMMAND, SwitchList[0]) >= 0)); }
/*** noswitch, oneswitch, twoswitch
* * noswitch() Returns TRUE is no switches on the command line * oneswitch() Returns TRUE is there is exactly one switch * twoswitch() Returns TRUE is there are exactly two switches * */
int DOSNEAR FASTCALL noswitch(VOID) { return (SwitchList[0] == NULL); }
int DOSNEAR FASTCALL oneswitch(VOID) { return ((SwitchList[0] != NULL) && (SwitchList[1] == NULL)); }
int DOSNEAR FASTCALL twoswitch(VOID) { return ((SwitchList[0] != NULL) && (SwitchList[1] != NULL) && (SwitchList[2] == NULL)); }
/*** noswitch_optional, oneswitch_optional
* * as above, except that the switch provided as argument is considered * an optional switch that will be allowed. So if you say * oneswitch_optional("/FOO"), then one switch (any switch) is OK, * and so is two switches if one of them is "/FOO". */ int DOSNEAR FASTCALL noswitch_optional(TCHAR *optional_switch ) { return ( noswitch() || ( oneswitch() && (sw_compare(optional_switch, SwitchList[0]) >= 0) ) ) ; }
int DOSNEAR FASTCALL oneswitch_optional(TCHAR *optional_switch ) { return ( oneswitch() || ( twoswitch() && ( (sw_compare(optional_switch, SwitchList[0]) >= 0) || (sw_compare(optional_switch, SwitchList[1]) >= 0) ) ) ) ; }
/***
* o n l y s w i t c h * * Returns TRUE if the first switch matches the named switch, and it * is the only switch. */ int DOSNEAR FASTCALL onlyswitch(TCHAR *known) { return (oneswitch() && firstswitch(known)); }
/*** ValidateSwitches
* * Given a list of valid switches, check each entry in the switch * list. * * This function not only checks for invalid switches, but also * attempts to discern ambiguous usages. A usage is ambiguous if * it does not match any valid swithc exactly, and it a partial * match of more than one switch. See sw_compare(). This * algorithm can be fooled by nasty lists of valid switches, such * as one which lists the same switch twice. * * The function has been modified to canonicalize the SwitchList. * It replaces an '=' in /x=value with a ':'; it translates * switches if needed, (see switches.h); and it expands unambiguous * partial matches to the full switch name. * * Returns: * 1: All switches OK * *: If any error, prints a message and exits. * */
int DOSNEAR FASTCALL ValidateSwitches(USHORT cmd, SWITCHTAB valid_list[]) { USHORT match; int comp_result; USHORT candidate; /* most recent NEAR match */ USHORT i,j; TCHAR * good_one; /* which element (cmd_line or trans) of the valid_list */ int needed; TCHAR FAR * sepptr;
for (i = 0; SwitchList[i]; i++) { sepptr = _tcschr(SwitchList[i], ':'); if (sepptr) *sepptr = NULLC; _tcsupr(SwitchList[i]); if (sepptr) *sepptr = ':';
candidate = 0; match = 0;
for (j = 0; valid_list[j].cmd_line; j++) { comp_result = sw_compare(valid_list[j].cmd_line, SwitchList[i]);
if (comp_result == 0) { candidate = j; match = 1; break; } else if (comp_result == 1) { match++; candidate = j; } }
if (match == 0) { if (! _tcscmp(swtxt_SW_HELP, SwitchList[i])) help_help(cmd, ALL);
if (! _tcscmp(swtxt_SW_SYNTAX, SwitchList[i])) help_help(cmd, USAGE_ONLY);
IStrings[0] = SwitchList[i]; ErrorPrint(APE_SwUnkSw, 1); help_help(cmd, USAGE_ONLY); } else if (match > 1) { IStrings[0] = SwitchList[i]; ErrorPrint(APE_SwAmbSw, 1); help_help(cmd, USAGE_ONLY); }
switch(valid_list[candidate].arg_ok) { case NO_ARG: if (sepptr) { ErrorPrint(APE_InvalidSwitchArg, 0); help_help(cmd, USAGE_ONLY); } break;
case ARG_OPT: break;
case ARG_REQ: if (!sepptr) { ErrorPrint(APE_InvalidSwitchArg, 0); help_help(cmd, USAGE_ONLY); } break; }
/* (expansion || translation) required ? */ if (comp_result || valid_list[candidate].translation) { if (valid_list[candidate].translation) good_one = valid_list[candidate].translation; else good_one = valid_list[candidate].cmd_line;
needed = _tcslen(good_one);
if (sepptr) needed += _tcslen(sepptr);
if ((SwitchList[i] = calloc(needed+1, sizeof(TCHAR))) == NULL) ErrorExit(NERR_InternalError);
_tcscpy(SwitchList[i], good_one);
if (sepptr) _tcscat(SwitchList[i], sepptr); } }
return 1; }
/*** sw_compare
* * Compare a known switch name to a switch string passed from * the command line. * * The command-line switch may still retain the "excess baggage" * of a value (as in /B:1024). The comparison is not sensitive * to case, and should be DBCS compatible as it uses the runtime * library to do all searches and compares. * * Returns: * -1: No match * 0: Exact match to full length of known switch * 1: Partial match; matches initial substring of * known switch * * The difference between return 0/1 is used by ValidateSwitches() * to detect the presence of a possibly ambiguous usage. Once * that function has checked all switches, further compares can * treat results 0 & 1 from this function as "match". */
int DOSNEAR FASTCALL sw_compare(TCHAR *known, TCHAR *cand) { register unsigned int complen;
/* Try to find end of switch name by looking */ /* the for separator between name and value, */ /* otherwise use total length. */
complen = _tcscspn(cand, TEXT(":"));
if (complen < 2) /* Special check for empty switch SLASH */ return -1;
if (complen > _tcslen(known)) return -1;
if (_tcsncmp(known,cand,complen) != 0) return -1;
if (complen == _tcslen(known)) return 0;
return 1; }
/*
* Used only by interpre.c */
int DOSNEAR FASTCALL CheckSwitch(TCHAR *x) { register TCHAR **p;
for (p=SwitchList; *p; p++) if (sw_compare(x,*p) >= 0) { return 1; }
return 0; }
|