/*
 * mars-nwe-dosutils - NetWare/DOS utility tools.
 *
 * Copyright (C) 2026 Mario Fetka
 * Copyright (C) 1993,1996 Martin Stover, Marburg, Germany
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, see <http://www.gnu.org/licenses/>.
 */

/*
 * Purpose: NET multicall front-end and command dispatcher for the DOS utility collection.
 * Depends on: net.h plus command modules such as login.c, map.c, flag.c, ndir.c, trustee.c, tools.c and netcall.c.
 */

#define VERS_DATE "21-May-96"

#include "net.h"

char *funcname=NULL;
char  prgpath[65];

typedef int (*NET_FUNC)(int argc, char *argv[], int mode);

/*
 * net_functions
 *
 * Purpose:
 *   Maps NET subcommands and stand-alone multicall executable names to their
 *   implementation function. The same binary can be invoked either as NET
 *   with the command name in argv[1], or through a renamed/stub executable
 *   where argv[0] already contains the command name.
 *
 * Fields:
 *   name        - uppercase command or alias name used for dispatch.
 *   description - short text shown by the built-in usage listing.
 *   func        - command implementation entry point.
 *   mode        - small command-specific selector passed to shared handlers.
 *
 * Notes:
 *   NCOPY is intentionally kept out of this table while the NCP74
 *   server-side copy/open-handle path is still under investigation. Keeping
 *   ncopy.c in the build makes it compile-tested, but removing the table entry
 *   prevents accidental execution through NET/Multicall dispatch.
 */
static struct s_net_functions {
 char      *name;
 char      *description;
 NET_FUNC  func;
 int       mode;
} net_functions[] = {

{"SPAWN",  "spawn program(command file)" ,          func_exec   , 0},
{"EXEC",   "execute program(command file)",         func_exec   , 1},
{"ECHO",   "echoes string (command file)" ,         func_echo   , 0},
{"CD",     "change directory (command file)" ,      func_cwd    , 0},
{"LOGIN",  "login to server as user" ,              func_login  , 0},
{"PROFILE","read command file" ,                    func_profile, 0},
{"CAPTURE","list and redirect printers" ,           func_capture, 0},
{"ENDCAP", "cancel redirect printers" ,             func_capture, 1},
{"MAP",    "list maps and map drives" ,             func_map    , 0},
{"MAPDEL", "removes maps" ,                         func_map    , 1},
{"PATH",   "list and set search path" ,             func_path   , 0},
{"PATHDEL","removes search path" ,                  func_path   , 1},
{"PATHINS","insert search path" ,                   func_path   , 2},
{"LOGOUT", "logout from server",       		    func_logout , 0},
{"FLAG",   "display or modify file attributes",     func_flag   , 0},
{"FLAGDIR","display or modify directory attributes",func_flagdir, 0},
{"GRANT",  "grant trustee rights",                  func_grant  , 0},
{"REVOKE", "revoke trustee rights",                 func_revoke , 0},
{"REMOVE", "remove trustee",                        func_remove , 0},
{"NDIR",   "list directory contents",               func_ndir   , 0},
{"RIGHTS", "display effective file/directory rights",func_rights, 0},
{"CREATOR","display or set creator/modifier/archive ids",func_creator,0},
{"SLIST",  "list servers",          		    func_slist  , 0},
{"WHOAMI", "show current NetWare user",              func_whoami , 0},
#if 0 /* NCOPY disabled: unsafe/open server-side-copy work-in-progress. */
{"NCOPY",  "copy files",                            func_ncopy  , 0},
#endif
{"PASSWD", "change password",          		    func_passwd , 0},
#if 1
{"TESTS",  "only testroutines!",                    func_tests  , 0},
#endif
{"DEBUG",  "set debug level, for mars_nwe only !",  func_debug  , 0}
};

#define MAX_FUNCS  (sizeof(net_functions) / sizeof(struct s_net_functions))

/*
 * get_entry_nr
 *
 * Purpose:
 *   Resolves a DOS program path or command token to an entry in the NET
 *   dispatch table. The basename is extracted, an optional extension is
 *   removed, and the result is uppercased before it is compared with the
 *   registered command names.
 *
 * Returns:
 *   The net_functions[] index on match, or -1 if the token is not registered.
 */
static int get_entry_nr(char *fstr)
{
  int       entry    = MAX_FUNCS;
  char      buff[200];
  char      funcn[100];
  char      *pp;
  strmaxcpy(buff, fstr, sizeof(buff)-1);
  korrpath(buff);
  get_path_fn(buff, NULL, funcn);
  pp=strrchr(funcn, '.');
  if (NULL != pp) *pp = '\0';
  upstr(funcn);
  while (entry--) {
    if (!strcmp(funcn, net_functions[entry].name)) return(entry);
  }
  return(-1);
}

/*
 * call_func_entry
 *
 * Purpose:
 *   Attempts to dispatch argv[0] to a registered NET command. This supports
 *   both stand-alone multicall-style invocations and the second pass from
 *   main(), where argv is shifted so that NET subcommands are dispatched as if
 *   they were executable names.
 *
 * Notes:
 *   Most commands require IPX/requester initialization before they run. MAP is
 *   allowed to run without a successful ipx_init() so it can report existing
 *   mapping state and requester-related errors in the traditional utility
 *   style.
 *
 * Returns:
 *   The command result, or -0xff when no matching command was found.
 */
int call_func_entry(int argc, char *argv[])
{
  int       funcmode;
  int       result   = -1;
  NET_FUNC  func     = NULL;
  int       entry = get_entry_nr(argv[0]);
  if (entry > -1) {
    func     = net_functions[entry].func;
    funcmode = net_functions[entry].mode;
    funcname = net_functions[entry].name;
  }
  if (NULL != func) {
    if (ipx_init() || func == func_map) {
      result = (*func)(argc, argv, funcmode);
    } else {
      fprintf(stderr, "Cannot init IPX\n");
    }
  } else result = -0xff;
  return(result);
}

/*
 * get_path
 *
 * Purpose:
 *   Stores the directory part of argv[0] in the global prgpath buffer. Some
 *   command handlers use this to locate companion files or command scripts
 *   relative to the NET executable.
 */
static void get_path(char *path)
{
  char buf[100];
  strmaxcpy(buf, path, sizeof(buf)-1);
  korrpath(buf);
  get_path_fn(buf, prgpath, NULL);
}

/*
 * main
 *
 * Purpose:
 *   NET multicall entry point. First try to dispatch by argv[0], which handles
 *   renamed/stub executables such as FLAG.EXE or NDIR.EXE. If that fails, try
 *   again with argv shifted by one so "NET FLAG ..." and similar command
 *   forms work through the same dispatch table.
 *
 * Returns:
 *   The selected command's return code. If no command matches, print the
 *   built-in usage list and return the not-found result.
 */
int main(int argc, char *argv[])
{
  int result = -0xff;
  get_path(argv[0]);
  result = call_func_entry(argc, argv);
  if (result == -0xff)
    result = call_func_entry(argc-1, argv+1);
  if (result == -0xff) {
    int  k= MAX_FUNCS;
    char progname[256];
    strmaxcpy(progname, argv[0], sizeof(progname)-1);
    upstr(progname);
    fprintf(stderr, "\n"
     "* (C)opyright (C) 1993,1996  Martin Stover, Marburg, Germany *\n"
     "  Version: %s\n\n", VERS_DATE);

    fprintf(stderr, "Usage:\t%s func ... \nfuncs:", progname);
    while (k--) {
      if (net_functions[k].func) {
        fprintf(stderr, "\t%s\t: %s\n",
           net_functions[k].name, net_functions[k].description);
      }
    }
  }
  return(result);
}


