LanMan 36.2 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
/* Copyright 1998 Acorn Computers Ltd
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/*
*
*  LanMan.C -- Lan Manager network client main module
*
*  Versions
*
*  28-02-94 INH Derived from FSinC (added c.Statics)
*
*
*/

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
Stewart Brodie's avatar
Stewart Brodie committed
29
#include <locale.h>
30 31 32 33
#include <string.h>

#include "kernel.h"
#include "swis.h"
Robert Sprowson's avatar
Robert Sprowson committed
34 35 36 37 38
#include "Global/Services.h"
#include "Global/FileTypes.h"
#include "Global/NewErrors.h"
#include "Interface/HighFSI.h"

39 40 41 42 43
#include "sys/dcistructs.h"
#include "sys/types.h"
#include "netinet/in.h"
#include "arpa/inet.h"

44
#include "stdtypes.h"
45 46
#include "LanMan.h"
#include "LMVars.h"
47
#include "Params.h"
48 49 50
#include "CoreFn.h"
#include "BufLib.h"
#include "NetBIOS.h"
51
#include "SMB.h"
52
#include "Xlate.h"
Ben Avison's avatar
Ben Avison committed
53
#include "VersionNum"
54 55
#include "Omni.h"
#include "Printers.h"
56
#include "RPC.h"
57 58
#include "Stats.h"
#include "Logon.h"
Stewart Brodie's avatar
Stewart Brodie committed
59 60
#include "LanMan_MH.h"

61 62
/* ---------------------------------- */

Robert Sprowson's avatar
Robert Sprowson committed
63
extern void *Resources(void);
64

65
#define DEFAULT_ETHER_TYPE 	"_default_"
66 67

typedef void (*pfnShutdown)(void);
Stewart Brodie's avatar
Stewart Brodie committed
68
typedef void (*pfnTransportInit)(void);
69 70 71 72 73 74 75 76

enum {
        LMInitState_Uninitialised,
        LMInitState_PreInit,
        LMInitState_FullyInited,
        LMInitState_Boot
};

Stewart Brodie's avatar
Stewart Brodie committed
77 78 79
static void startcallbacks(void);
static void stopcallbacks(void);

80 81 82 83
static _kernel_oserror *LM_init_phase_2(void);

/* ---------------------------------- */

Robert Sprowson's avatar
Robert Sprowson committed
84 85 86 87 88 89
struct LMvars LM_Vars;
static volatile int callbackflag = 0;
static int msg_struct[4]; /* MessageTrans block */
static _kernel_oserror msg_buff; /* MessageTrans buffer */
static _kernel_oserror *msg_oserr;
int    LM_pw;          /* Our module's private word */
90
struct NETBIOS_TRANSPORT *NB_ActiveTransport; /* Selected net transport */
Stewart Brodie's avatar
Stewart Brodie committed
91
static pfnTransportInit NB_InitedTransport; /* Identify active transport */
92 93
static bool LM_Declared;  /* True if we're registered as a filing system */

Robert Sprowson's avatar
Robert Sprowson committed
94
/* ---------------------------------- */
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112

#define CMOS_FSNUMBER   5
/* Contains number of FS to be booted */
#define CMOS_FSFLAGS    16
/* Contains flags, bit 4 is set if booting is enabled */
#define FSF_BOOT        0x10

#define CMOS_FSSTAT     1 /* NAS 11/Feb/97 */
#define CMOS_FSERVER1   2 /* NAS 11/Feb/97 */
#define CMOS_FSERVER    158 /* NAS 11/Feb/97 */
#define FSERVER_LEN     (172-159+1)
/* Locations in CMOS containing file server name.
   It's assumed this is less than NAME_LIMIT. If it's not, put FSERVER_LEN
   at NAME_LIMIT-1, and it'll have to be truncated. */

#define CMOS_NB_TYPE    0x6F
#define	NBTYPE_IP_BIT	(1<<0)

Robert Sprowson's avatar
Robert Sprowson committed
113 114 115 116 117 118 119 120 121 122 123
/* ------------------ */

const char *MsgLookup(const char *token)
{
  if (_swix(MessageTrans_Lookup, _INR(0,7),
            msg_struct, token, &msg_buff, sizeof(msg_buff), 0, 0, 0, 0) != NULL)
  {
    return "";
  }
  return (const char *)&msg_buff;
}
124

Robert Sprowson's avatar
Robert Sprowson committed
125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
/* ------------------ */

err_t MsgSetOSError (_kernel_oserror *err)
{
  /* Record the last OS error, and translate that into a LanMan
   * error number so we can retrieve the actual error later in MsgError().
   */
  msg_oserr = err;
  if (err == NULL)
    return OK;

  return EUSELASTSETOSERR; /* Hint hint */
}

/* ------------------ */

_kernel_oserror *MsgError(int which)
{
143 144 145 146
  struct {
    int errnum;
    char errmess[8];
  } token;
Robert Sprowson's avatar
Robert Sprowson committed
147

148 149
  if (which == OK) return NULL; /* No error */

Robert Sprowson's avatar
Robert Sprowson committed
150 151 152 153
  if (which == EUSELASTSETOSERR)
  {
    /* An OS error outside this module */
    if (msg_oserr != NULL) return msg_oserr;
154
    which = EHOWDTHATHAPPEN;
Robert Sprowson's avatar
Robert Sprowson committed
155 156
  }

157 158
  sprintf(token.errmess, "E%02u", which);
  if ((which == EDIRNOTEMPTY) || (which == ENOACCESS))
Robert Sprowson's avatar
Robert Sprowson committed
159
  {
160 161 162 163
      /* Fudge for Filer_Action which expects a FileCore
       * style specific error return code
       */
      which = ErrorNumber_DirNotEmpty;
Robert Sprowson's avatar
Robert Sprowson committed
164
  }
165 166 167
  token.errnum = Our_Error_Base + which;
  return _swix(MessageTrans_ErrorLookup, _INR(0,3),
            &token, msg_struct, &msg_buff, sizeof(msg_buff));
Robert Sprowson's avatar
Robert Sprowson committed
168
}
169 170 171 172 173 174 175 176 177 178

/* ------------------ */

int RdCMOS ( int addr )
{
  return (_kernel_osbyte ( 161, addr, 0 ) & 0xFF00 ) >> 8;
}

/* ------------------ */

Stewart Brodie's avatar
Stewart Brodie committed
179
static void WrCMOS ( int addr, unsigned int data )
180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209
{
  _kernel_osbyte ( 162, addr, data );
}

/* --------------------- */

static void SetFSName(char *buf_in)
{
  int i, t;

  WrCMOS(CMOS_FSSTAT, 0);
  WrCMOS(CMOS_FSERVER1, buf_in[0]);
  if (buf_in[0] == 0) return;

  for (i=1; i < FSERVER_LEN; i++)
  {
    /* NAS 11/Feb/97 */
    t = buf_in[i];
    if (t <= 0x20 || t > 0x7F) t = 0;
    WrCMOS ( CMOS_FSERVER+i-1, t);
    if (t == 0) break;
  }
}

/* --------------------- */

static void GetFSName ( char *buf_out )
{
  int i;

Stewart Brodie's avatar
Stewart Brodie committed
210 211 212 213
  if (!_kernel_getenv("Inet$ServerName", buf_out, CMOS_FSERVER)) {
          return;
  }

214 215 216 217 218 219 220 221 222 223 224
  if ( RdCMOS ( CMOS_FSSTAT ) == 0 )
  {
    /* NAS 11/Feb/97 */
    *buf_out++ = RdCMOS ( CMOS_FSERVER1 );
    for ( i=1; i < FSERVER_LEN; i++ )
      *buf_out++ = RdCMOS ( CMOS_FSERVER+i-1 );
  }

  *buf_out = 0;
}

225 226
/* --------------------- */

Robert Sprowson's avatar
Robert Sprowson committed
227
static void lanman_announce_lanmanfs(int r2, void *pw)
228 229 230
{
#ifndef NO_NETBEUI
  /* Send the service call announcing the presence/absence of a protocol module */
231
  if (NB_InitedTransport == NB_NetBEUI_Setup)
232 233 234 235 236
    (void) _swix(OS_ServiceCall, _INR(0,4), pw,
      Service_DCIProtocolStatus, r2, DCIVERSION, Module_Title);
#endif
}

237 238 239 240 241 242 243 244
/* Finalisation code ------------------------------------ */

static void LM_Undeclare ( void )
{
  _kernel_swi_regs r;

  if ( LM_Declared )
  {
245
    r.r[0] = FSControl_RemoveFS;
246 247 248 249 250 251 252 253 254
    r.r[1] = (int)FilingSystemName;

    _kernel_swi( XOS_Bit | OS_FSControl, &r, &r );
    LM_Declared = false;
  }
}

/* ------------------ */

Stewart Brodie's avatar
Stewart Brodie committed
255
static void LM_GracefulClosedown(void)
256
{
257 258 259 260 261 262 263
  stopcallbacks();
  SMB_Shutdown();            /* Dismounts all SMB mounts first as */
  Omni_Shutdown();           /* Omni_Shutdown zeros the Mounts lists */
  Prn_Shutdown();            /* Free print jobs */
  NB_Shutdown();             /* Also calls LLC_Shutdown */
  Buf_Shutdown();            /* Tell MBufManager we're done */
  LM_Vars.initialised = LMInitState_PreInit;
Stewart Brodie's avatar
Stewart Brodie committed
264 265 266 267 268 269 270
}

_kernel_oserror * LM_Finalise (int fatal, int podule, void *pw)
{
  debug0("Finalise\n");
  (void) fatal;
  (void) podule;
271

272
  /* Dismount all (NB.Before announcing we're done with the protocol) */
Stewart Brodie's avatar
Stewart Brodie committed
273
  LM_GracefulClosedown();
274
  /* Tell the DCI driver the NetBEUI protocol is gone */
Robert Sprowson's avatar
Robert Sprowson committed
275
  lanman_announce_lanmanfs(DCIPROTOCOL_DYING, pw);
276
  /* Now mark this filing system as gone */
277
  LM_Undeclare();
278

Robert Sprowson's avatar
Robert Sprowson committed
279 280 281
  _swix(MessageTrans_CloseFile, _IN(0), msg_struct);
  _swix(ResourceFS_DeregisterFiles, _IN(0), Resources());

282 283 284 285 286 287 288 289 290
  return NULL;
}


/* LM_declare ------------------------------------------ */

static _kernel_oserror *LM_Declare ( void )
{
  _kernel_oserror *err;
291
  int InfoBlk[12];
292 293 294 295

  LM_Declared = false;

  InfoBlk[0] = (int)FilingSystemName             - (int)Image_RO_Base;
Stewart Brodie's avatar
Stewart Brodie committed
296
  InfoBlk[1] = -1; /* Self-ident - request call FSFunc_PrintStartupBanner */
297 298 299 300 301 302 303 304 305
  InfoBlk[2] = (int) veneer_fsentry_open         - (int)Image_RO_Base;
  InfoBlk[3] = (int) veneer_fsentry_getbytes     - (int)Image_RO_Base;
  InfoBlk[4] = (int) veneer_fsentry_putbytes     - (int)Image_RO_Base;
  InfoBlk[5] = (int) veneer_fsentry_args         - (int)Image_RO_Base;
  InfoBlk[6] = (int) veneer_fsentry_close        - (int)Image_RO_Base;
  InfoBlk[7] = (int) veneer_fsentry_file         - (int)Image_RO_Base;
  InfoBlk[8] = Information_Word;
  InfoBlk[9] = (int) veneer_fsentry_func         - (int)Image_RO_Base;
  InfoBlk[10] = (int)veneer_fsentry_gbpb         - (int)Image_RO_Base;
Stewart Brodie's avatar
Stewart Brodie committed
306
  InfoBlk[11] = Information2_Word;
307

308
  err = _swix(OS_FSControl, _INR(0,3), FSControl_AddFS, Image_RO_Base,
Stewart Brodie's avatar
Stewart Brodie committed
309
    (int)InfoBlk - (int)Image_RO_Base, LM_pw);
310
  if ( err == NULL )
311
    LM_Declared = true;
312 313 314 315 316 317 318 319 320 321 322 323 324 325

  return err;
}


/* *Command processor ------------------------------------ */

#define MAX_ARGS    20
#define MAX_CMDLEN  256

static char Cmdbuf[ MAX_CMDLEN ];

/* --------------------- */

Stewart Brodie's avatar
Stewart Brodie committed
326
static int GetArgs ( const char *args, char *argv_out[], int maxargs )
327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367
{
  /* Splits "args" into a number of separate arguments. Each one is
     copied into Cmdbuf so it is held statically. Pointers to the
     start of each one are put in argv_out. Any unused spaces in
     argv_out are set to NULL for convenience. Returns the number
     of arguments actually found.  */

  int i, argc;

  for (i=0; i < maxargs; i++ ) argv_out[i] = NULL;

  i=0; /* In this loop, i counts characters in Cmdbuf */
  argc=0;

  do
  {
    while ( *args == ' ' ) /* Skip spaces */
      args++;

    if ( *args < ' ' )  /* The end */
      break;

    /* Got one */

    if ( argc >= maxargs )  /* Too many! */
      break;

    argv_out[argc++] = Cmdbuf+i;

    while ( i < MAX_CMDLEN-1 && *args > ' ' ) /* Copy it */
      Cmdbuf[i++] = *args++;

    Cmdbuf[i++] = 0;     /* Terminate it */
  }
    while ( i < MAX_CMDLEN-1 );

  return argc;
}

/* --------------------- */

368
static _kernel_oserror *Cmd_LanMan ( const char *args )
369 370 371 372 373
{
  /* No args! */
  _kernel_swi_regs r;
  (void) args;

374
  r.r[0] = FSControl_SelectFS;
375 376 377 378 379 380 381
  r.r[1] = (int)FilingSystemName;

  return _kernel_swi( XOS_Bit | OS_FSControl, &r, &r );
}

/* --------------------- */

382
static _kernel_oserror *Cmd_Free ( const char *args )
Stewart Brodie's avatar
Stewart Brodie committed
383 384 385 386 387 388 389 390 391 392
{
  _kernel_swi_regs r;
  _kernel_oserror *e;
  int values[6];
  char *argv[1];

  if (GetArgs(args, argv, sizeof(argv)/sizeof(*argv)) == 0)
    argv[0] = getenv("FileSwitch$" FilingSystemName "$CSD");

  if (argv[0] == NULL)
Robert Sprowson's avatar
Robert Sprowson committed
393
    return MsgError( EBADDRV );
Stewart Brodie's avatar
Stewart Brodie committed
394 395 396 397 398 399 400 401 402

  r.r[0] = 4; /* 64-bit free space - will not fail! */
  r.r[1] = Our_FS_Number;
  r.r[2] = (int) values;
  r.r[3] = (int) argv[0];
  e = Omni_FreeOp_SWI(&r);

  if (e == NULL) {
    if (values[3] == 0 && values[5] == 0) {
Robert Sprowson's avatar
Robert Sprowson committed
403
      printf("%s &%08X\n", MsgLookup("Free"), values[2] );
Stewart Brodie's avatar
Stewart Brodie committed
404
      if (values[4] != -1) {
Robert Sprowson's avatar
Robert Sprowson committed
405
        printf("%s &%08X\n", MsgLookup("Used"), values[4] );
Stewart Brodie's avatar
Stewart Brodie committed
406 407
      }
      else {
Robert Sprowson's avatar
Robert Sprowson committed
408
        printf("%s\n", MsgLookup("UsedUK")); /* Unknown */
Stewart Brodie's avatar
Stewart Brodie committed
409 410 411
      }
    }
    else {
Robert Sprowson's avatar
Robert Sprowson committed
412
      printf("%s &%08X%08X\n", MsgLookup("Free"), values[3], values[2] );
Stewart Brodie's avatar
Stewart Brodie committed
413
      if (values[4] != -1) {
Robert Sprowson's avatar
Robert Sprowson committed
414
        printf("%s &%08X%08X\n", MsgLookup("Used"), values[5], values[4] );
Stewart Brodie's avatar
Stewart Brodie committed
415 416
      }
      else {
Robert Sprowson's avatar
Robert Sprowson committed
417
        printf("%s\n", MsgLookup("UsedUK")); /* Unknown */
Stewart Brodie's avatar
Stewart Brodie committed
418 419 420 421 422 423 424
      }
    }
  }

  return e;
}

Stewart Brodie's avatar
Stewart Brodie committed
425
/* --------------------- */
426
static _kernel_oserror *Cmd_ListFS ( const char *args )
Stewart Brodie's avatar
Stewart Brodie committed
427 428 429 430 431 432 433 434 435 436 437
{
  char *argv[1];

  if (GetArgs(args, argv, sizeof(argv)/sizeof(*argv)) == 0) {
    return Omni_DumpServers();
  }
  else {
    return Omni_DumpShares(argv[0]);
  }
}

Stewart Brodie's avatar
Stewart Brodie committed
438 439
/* --------------------- */

440
static _kernel_oserror *Cmd_LMConnect ( const char *args )
441 442 443 444 445 446
{
  char *argv[5];
  err_t res;
  int   tmp;

  if ( GetArgs ( args, argv, 5 ) < 3 )
Robert Sprowson's avatar
Robert Sprowson committed
447
    return MsgError(EBADPARAM);
448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463

  /* Convert '-' user name to NULL */

  if ( argv[3] != NULL    &&
       argv[3][0] == '-'  &&
       argv[3][1] == 0 )
    argv[3] = NULL;

  res =  Omni_MountServer ( argv[1],  /* Server */
          argv[3], /* User name or NULL */
          argv[4], /* password or NULL */
          argv[0], /* Mountname */
          argv[2], /* Drive name */
          &tmp ); /* MountID_out */

  Omni_RecheckInfo ( RI_MOUNTS );
Robert Sprowson's avatar
Robert Sprowson committed
464
  return MsgError(res);
465 466 467 468
}

/* --------------------- */

469
static _kernel_oserror *Cmd_LMDisconnect ( const char *args )
470 471 472 473 474 475
{
  char *argv[1];
  int mountID;
  err_t res;

  if ( GetArgs( args, argv, 1 ) < 1 )
Robert Sprowson's avatar
Robert Sprowson committed
476
    return MsgError(EBADPARAM);
477 478

  mountID = Omni_GetMountID(argv[0]);
Robert Sprowson's avatar
Robert Sprowson committed
479
  if ( mountID == 0 ) return MsgError ( EBADDRV );
480 481 482

  res = Omni_DismountServer(mountID);
  Omni_RecheckInfo ( RI_MOUNTS );
Robert Sprowson's avatar
Robert Sprowson committed
483
  return MsgError (res);
484 485 486 487 488
}


/* --------------------- */

Stewart Brodie's avatar
Stewart Brodie committed
489 490 491 492 493 494
static void LanMan_InitTransport(pfnTransportInit i)
{
        NB_InitedTransport = i;
        (*i)();
}

495 496 497 498 499 500
static void SetDefaultVars ( void )
{
  char *name;
  char fs_name [ FSERVER_LEN+1 ];

  LM_Vars.initialised = LMInitState_Uninitialised;
Ben Avison's avatar
Ben Avison committed
501 502 503
  LM_Vars.namemode = NM_FIRSTCAPS;

  /* See where IP packets are going to be sent */
504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519
  name = getenv("Inet$EtherType");
  strcpyn ( LM_Vars.drivername,
                (name==NULL) ? DEFAULT_ETHER_TYPE : name, NAME_LIMIT );

  name = getenv("Inet$HostName");
  /* Trap added to catch 'ARM_NoName', as set by STB OS */
  if ((name == NULL) || (stricmp(name,"ARM_NoName")==0))
    strcpy ( LM_Vars.machinename,   "" );
  else
  {
    strcpyn_upper ( LM_Vars.machinename, name, NAME_LIMIT );
    /* Truncate at first dot - it might be a full domain name */
    name = strchr ( LM_Vars.machinename, '.' );
    if ( name != NULL ) *name = 0;
  }

Ben Avison's avatar
Ben Avison committed
520 521 522 523 524 525 526 527 528 529 530 531 532
  /* See if the user has overridden the default filetype */
  name = getenv("LanMan$DefaultType");
  if (name != NULL)
  {
    _swix(OS_FSControl, _INR(0,1)|_OUT(2), 31, name, &LM_Vars.default_type);
  }
  else
  {
    LM_Vars.default_type = CNV_DEFAULT_TYPE;
  }

  /* Read the base of the OS ROM so there's an address to use for
   * untyped load/exec address, ensuring they would abort if used
533
   */
Ben Avison's avatar
Ben Avison committed
534 535
  _swix(OS_Module, _INR(0,2)|_OUT(3), 12, 0, 0, &LM_Vars.untyped_address);
  LM_Vars.untyped_address = LM_Vars.untyped_address & ~((1<<20) - 1);
536

Ben Avison's avatar
Ben Avison committed
537 538 539
  /* Following 'get from CMOS' bits added 980127:RCE
   * to address user complaints that it has to be typed in every time
   */
540 541 542 543 544 545 546 547
  Lgn_Init();
  GetFSName(fs_name);
  if (fs_name[0] != '\0')
  {
    strcpy(LM_Vars.workgroup,fs_name);
  }

  /* Set transport type from CMOS, unless overridden on command line */
548 549 550
#ifdef NO_NETBEUI
  LanMan_InitTransport(NB_NBIP_Setup);
#else
Stewart Brodie's avatar
Stewart Brodie committed
551
  LanMan_InitTransport(RdCMOS ( CMOS_NB_TYPE ) & NBTYPE_IP_BIT  ?
552 553
    NB_NBIP_Setup : NB_NetBEUI_Setup);
#endif
554 555 556 557
}

/* --------------------- */

558
static _kernel_oserror *Cmd_LMLogoff( const char *args )
559 560 561 562 563 564 565 566
{
  (void) args;
  Lgn_Logoff();
  return NULL;
}

/* --------------------- */

567
static _kernel_oserror *Cmd_LMLogon( const char *args )
568 569 570
{
  char *argv[3];
  if ( GetArgs(args, argv, 3) < 2 )
Robert Sprowson's avatar
Robert Sprowson committed
571
    return MsgError(EBADPARAM);
572 573 574

  /* argv[2] may be NULL for blank password */

Robert Sprowson's avatar
Robert Sprowson committed
575
  return MsgError (Lgn_Logon ( argv[0], argv[1], argv[2] ) );
576 577
}

Robert Sprowson's avatar
Robert Sprowson committed
578 579
/* --------------------- */

Robert Sprowson's avatar
Robert Sprowson committed
580
#ifdef DEBUG
Robert Sprowson's avatar
Robert Sprowson committed
581 582 583 584 585 586 587 588 589 590
static char *LM_Status(void)
{
        switch (LM_Vars.initialised) {
        case LMInitState_Uninitialised: return "Dormant";
        case LMInitState_PreInit: return "Waiting for driver";
        case LMInitState_FullyInited: return "Active";
        case LMInitState_Boot: return "Waiting to boot";
        default: return "Dead";
        }
}
Robert Sprowson's avatar
Robert Sprowson committed
591
#endif
592 593 594

/* --------------------- */

595
static _kernel_oserror *Cmd_LMInfo ( const char *args )
596 597 598
{
  (void) args;
  Omni_Debug();
Robert Sprowson's avatar
Robert Sprowson committed
599 600 601 602
#ifdef DEBUG
  debug1("Status: %s\n", LM_Status());
  Stat_Show();
#endif
603 604 605 606 607
  return NULL;
}

/* --------------------- */

608
static _kernel_oserror *Cmd_LMNameMode ( const char *args )
609 610 611 612 613 614 615
{
  char *argv[1];
  int tmp;

  if ( GetArgs( args, argv, 1 ) < 1 ||
       sscanf( argv[0], "%d", &tmp) != 1 ||
       tmp < 0 ||
Stewart Brodie's avatar
Stewart Brodie committed
616 617 618
#ifdef TRACE
       0
#else
619
       tmp > 2
Stewart Brodie's avatar
Stewart Brodie committed
620
#endif
621
     )
Robert Sprowson's avatar
Robert Sprowson committed
622
    return MsgError (EBADPARAM);
623 624 625 626 627 628 629

  LM_Vars.namemode = tmp;
  return NULL;
}

/* --------------------- */

630
static _kernel_oserror *Cmd_LMServer ( const char *args )
631 632 633 634 635
{
  char *argv[MAX_ARGS];
  int i;

  if ( GetArgs( args, argv, MAX_ARGS ) < 1 )
Robert Sprowson's avatar
Robert Sprowson committed
636
    return MsgError ( EBADPARAM );
637 638 639

  if ( argv[1] == NULL ) /* Just name of server */
  {
Stewart Brodie's avatar
Stewart Brodie committed
640
    Omni_AddInfo ( OAI_SERVER, argv[0], NULL, NULL );
641 642 643 644
  }
  else
  {
    for ( i=1; i < MAX_ARGS && argv[i] != NULL; i++ )
Stewart Brodie's avatar
Stewart Brodie committed
645
      Omni_AddInfo ( OAI_DISK, argv[0], argv[i], NULL );
646 647 648 649 650 651 652 653
  }

  Omni_RecheckInfo (RI_SERVERS);
  return NULL;
}

/* --------------------- */

654
static _kernel_oserror *Cmd_LMPrinters ( const char *args )
655 656 657 658 659
{
  char *argv[MAX_ARGS];
  int i;

  if ( GetArgs( args, argv, MAX_ARGS ) < 1 )
Robert Sprowson's avatar
Robert Sprowson committed
660
    return MsgError ( EBADPARAM );
661 662 663

  if ( argv[1] == NULL ) /* Just name of server */
  {
Stewart Brodie's avatar
Stewart Brodie committed
664
    Omni_AddInfo ( OAI_SERVER, argv[0], NULL, NULL );
665 666 667 668
  }
  else
  {
    for ( i=1; i < MAX_ARGS && argv[i] != NULL; i++ )
Stewart Brodie's avatar
Stewart Brodie committed
669
      Omni_AddInfo ( OAI_PRINTER, argv[0], argv[i], NULL );
670 671 672 673 674 675 676 677 678
  }

  Omni_RecheckInfo (RI_SERVERS);
  Omni_RecheckInfo (RI_PRINTERS);
  return NULL;
}

/* --------------------- */

Stewart Brodie's avatar
Stewart Brodie committed
679
static _kernel_oserror *Cmd_FS ( const char *args )
680 681 682 683 684 685
{
  /* This is a *Configure/Status command handler - it's therefore unusual */
  char *argv[1];

  if ( (int) args == 0 ) /* Show 'Configure' options */
  {                      /* Syntax corrected 980127 RCE */
Robert Sprowson's avatar
Robert Sprowson committed
686
    printf("FS           %s\n", MsgLookup("ConfFS"));
687 688 689 690 691 692
    return NULL;
  }
  else if ( (int) args == 1 ) /* Show FS status */
  {
    char buf[NAME_LIMIT];
    GetFSName(buf);
Robert Sprowson's avatar
Robert Sprowson committed
693
    printf("FS           %s\n", buf[0] ? buf : MsgLookup("NoHome"));
694 695 696 697
    return NULL;
  }

  if ( GetArgs( args, argv, 1 ) < 1 )
Robert Sprowson's avatar
Robert Sprowson committed
698
    return MsgError ( EBADPARAM );
699 700 701 702 703 704 705

  SetFSName(argv[0]);
  return NULL;
}

/* --------------------- */

706
static _kernel_oserror *Cmd_LMTransport ( const char *args )
707 708 709 710 711
{
  /* This is a *Configure/Status command handler */
  char *argv[1];
  char *tp1 = "IP";

712 713 714 715 716 717 718 719 720
#ifdef NO_NETBEUI
  if (args == arg_CONFIGURE_SYNTAX || args == arg_STATUS)
  {
    printf("LMTransport  IP\n");
    return NULL;
  }
#else
  char *tp0 = "NetBEUI";
  if ( args == arg_CONFIGURE_SYNTAX ) /* Show 'Configure' options */
721 722 723 724
  {
    printf("LMTransport  [%s | %s]\n", tp0, tp1);
    return NULL;
  }
725
  else if ( args == arg_STATUS ) /* Show FS status */
726 727 728 729 730
  {
    printf("LMTransport  %s\n",
      (RdCMOS(CMOS_NB_TYPE) & NBTYPE_IP_BIT) ? tp1:tp0);
    return NULL;
  }
731
#endif
732
  if ( GetArgs( args, argv, 1 ) < 1 )
Robert Sprowson's avatar
Robert Sprowson committed
733
    return MsgError ( EBADPARAM );
734

735
#ifndef NO_NETBEUI
736 737
  if ( stricmp ( argv[0], tp0 ) == 0 )
    WrCMOS(CMOS_NB_TYPE, RdCMOS(CMOS_NB_TYPE) & ~NBTYPE_IP_BIT );
738 739 740
  else
#endif
  if ( stricmp ( argv[0], tp1 ) == 0 )
741 742
    WrCMOS(CMOS_NB_TYPE, RdCMOS(CMOS_NB_TYPE) | NBTYPE_IP_BIT );
  else
Robert Sprowson's avatar
Robert Sprowson committed
743
    return configure_BAD_OPTION;
744 745 746 747 748

  return NULL;
}

/* --------------------- */
749
static _kernel_oserror *Cmd_LMNameServer( const char *args )
750 751 752 753 754 755
{
  /* This is a *Configure/Status command handler - it's therefore unusual */
  char *argv[1];
  struct in_addr address;
  int result;

756
  if ( args == arg_CONFIGURE_SYNTAX ) /* Show 'Configure' options */
757 758 759 760
  {
    printf("LMNameServer xx.xx.xx.xx\n");
    return NULL;
  }
761
  else if ( args == arg_STATUS ) /* Show FS status */
762 763 764 765 766 767 768 769 770 771 772 773 774 775
  {
    int b0, b1, b2, b3;

    b0 = RdCMOS(NBNSIPCMOS0);
    b1 = RdCMOS(NBNSIPCMOS1);
    b2 = RdCMOS(NBNSIPCMOS2);
    b3 = RdCMOS(NBNSIPCMOS3);

    if ( ((b0 != 0) && (b0 != 127) && (b0 <= 223))  &&  ((b3 != 0) && (b3 != 255)) )
    {
      printf("LMNameServer %d.%d.%d.%d\n", b0,b1,b2,b3);
    }
    else
    {
Robert Sprowson's avatar
Robert Sprowson committed
776
      printf("LMNameServer %s\n", MsgLookup("NoHome"));
777 778 779 780 781 782 783 784
    }
    return NULL;
  }
  else if (GetArgs(args,argv,1) == 1)
  {
    result = inet_aton(argv[0],&address);
    if (result)
    {
Robert Sprowson's avatar
Robert Sprowson committed
785
      unsigned char b0, b1, b2, b3;
786

Robert Sprowson's avatar
Robert Sprowson committed
787 788 789 790
      b0 = (unsigned char)(address.s_addr >> 0);
      b1 = (unsigned char)(address.s_addr >> 8);
      b2 = (unsigned char)(address.s_addr >> 16);
      b3 = (unsigned char)(address.s_addr >> 24);
791 792 793

      if ( ((b0 != 127) && (b0 <= 223))  &&  ((b3 != 255)) )
      {
Stewart Brodie's avatar
Stewart Brodie committed
794 795 796 797
        WrCMOS(NBNSIPCMOS0,(int) b0);
        WrCMOS(NBNSIPCMOS1,(int) b1);
        WrCMOS(NBNSIPCMOS2,(int) b2);
        WrCMOS(NBNSIPCMOS3,(int) b3);
798 799 800 801
        return NULL;
      }
    }
  }
Robert Sprowson's avatar
Robert Sprowson committed
802
  return MsgError(EBADPARAM);
803 804 805 806
}

/* --------------------- */

Stewart Brodie's avatar
Stewart Brodie committed
807
typedef _kernel_oserror * (*CommandFnPtr) ( const char *args );
808

809 810
#define CmdEntry(X) [CMD_##X] = Cmd_##X
static CommandFnPtr Cmd_Dispatch[] =
811
{
812 813 814 815 816 817 818 819 820 821 822 823 824 825
  CmdEntry(LanMan),
  CmdEntry(LMConnect),
  CmdEntry(LMDisconnect),
  CmdEntry(LMLogon),
  CmdEntry(LMInfo),
  CmdEntry(LMNameMode),
  CmdEntry(LMLogoff),
  CmdEntry(LMServer),
  CmdEntry(LMPrinters),
  CmdEntry(FS),
  CmdEntry(LMTransport),
  CmdEntry(LMNameServer),
  CmdEntry(Free),
  CmdEntry(ListFS)
826 827
};

828
#define MAX_CMDS (sizeof Cmd_Dispatch / sizeof Cmd_Dispatch[0])
Stewart Brodie's avatar
Stewart Brodie committed
829

830 831
/* --------------------- */

Stewart Brodie's avatar
Stewart Brodie committed
832
_kernel_oserror *LM_Command ( const char *args, int argc, int cmd_no, void *pw )
833 834 835 836 837
{
  (void) pw;
  (void) argc;

  if ( cmd_no < 0 || cmd_no >= MAX_CMDS )
Robert Sprowson's avatar
Robert Sprowson committed
838
    return MsgError(ENOTPRESENT);
839 840 841 842 843 844

  return Cmd_Dispatch[cmd_no](args);
}

/* Service call handler --------------------------------- */
static void LM_check_driver_status(_kernel_swi_regs *r);
Stewart Brodie's avatar
Stewart Brodie committed
845
static void LM_check_internet_status(_kernel_swi_regs *r);
846
static void LM_check_protocol_status(_kernel_swi_regs *r);
847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863

void LM_Service ( int service_number, _kernel_swi_regs *r, void *pw )
{
  (void) pw;
  /* Any changes to list of service calls?  Must mirror in cmhg inputfile too! */

  switch(service_number)
  {
    case Service_FSRedeclare:
      LM_Declare();
      break;

    case Service_OmniAction:
      Omni_ServiceCall (r);
      break;

    case Service_ResourceFSStarting:
Robert Sprowson's avatar
Robert Sprowson committed
864 865
      /* Reregister with ResourceFS */
      (*(void (*)(void *, void *, void *, void *))r->r[2])(Resources(), 0, 0, (void *)r->r[3]);
866 867 868
      break;

    case Service_DCIDriverStatus:
869
      LM_check_driver_status(r);
Stewart Brodie's avatar
Stewart Brodie committed
870 871
      break;

872 873 874 875
    case Service_DCIProtocolStatus:
      LM_check_protocol_status(r);
      break;

Stewart Brodie's avatar
Stewart Brodie committed
876 877 878 879
    case Service_InternetStatus:
      if (NB_InitedTransport == NB_NBIP_Setup) {
          LM_check_internet_status(r);
      }
880 881 882 883 884 885 886 887 888 889 890 891
      break;

    default:
      break;
  }
}

/* SWI handler ------------------------------------------ */

_kernel_oserror *LM_Swi( int swi_ofs, _kernel_swi_regs *r, void *pw )
{
  (void) pw;  /* Not used */
Stewart Brodie's avatar
Stewart Brodie committed
892
  switch ( swi_ofs )
893
  {
Stewart Brodie's avatar
Stewart Brodie committed
894
    case LanMan_OmniOp - LanMan_00:
895 896
      return OmniOp_SWI(r);

Stewart Brodie's avatar
Stewart Brodie committed
897
    case LanMan_LogonOp - LanMan_00:
898 899
      return Lgn_LogonOp_SWI(r);

Stewart Brodie's avatar
Stewart Brodie committed
900
    case LanMan_FreeOp - LanMan_00:
901 902
      return Omni_FreeOp_SWI(r);

Stewart Brodie's avatar
Stewart Brodie committed
903
    case LanMan_NameOp - LanMan_00:
Robert Sprowson's avatar
Robert Sprowson committed
904
      return MsgError(RPC_NameOp(r->r[0], /* reason code */
905 906 907
                                  (char *)(r->r[1]), /* name in */
                                  (char *)(r->r[2])  /* buffer out */
                                   ));
Stewart Brodie's avatar
Stewart Brodie committed
908
    case LanMan_Transact - LanMan_00:
Robert Sprowson's avatar
Robert Sprowson committed
909
      return MsgError(RPC_Transact((char *)(r->r[0]), /* server */
910 911 912 913 914
                                    (char *)(r->r[1]), /* share name */
                                    (void *)(r->r[2]) /* params */
                                     ));

    default:
Robert Sprowson's avatar
Robert Sprowson committed
915
      return MsgError(ENOTPRESENT);
916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937
  }

  return NULL;
}

/* Initialisation code ---------------------------------- */

static char *copy_space ( char *dst, char *src, int maxlen )
{
  while ( *src > ' ' )
  {
    if ( --maxlen > 0 )
      *dst++ = *src;
    src++;
  }

  *dst = 0;
  return src;
}

/* ------------------------------- */

Stewart Brodie's avatar
Stewart Brodie committed
938
static err_t ProcessCmdLine ( const char *_line )
939 940
{
  char cli[256];
Stewart Brodie's avatar
Stewart Brodie committed
941 942
  char *end;
  char *line;
943 944 945 946 947 948

  /* This code relies on NB_xxx_Setup() only setting variables, not
     allocating anything. Multiple NB_xxx_Setup()'s may be called if
     the user is being perverse */

  /* NAS 20/3/97 - RO doesn't pass a 0-terminated string, but a ctrl-terminated one */
Stewart Brodie's avatar
Stewart Brodie committed
949
  strncpy(cli, _line, 255);
950 951 952 953 954 955 956 957 958
  line = end = cli;
  while (*end >= ' ') end++;
  *end = '\0';

  while ((line = strchr(line, '-')) != NULL)
  {
    line++;
    switch ( toupper(*line) )
    {
Robert Sprowson's avatar
Robert Sprowson committed
959
      case 'D': /* -d<driver_name> specify driver name */
960 961 962
         line = copy_space ( LM_Vars.drivername, line+1, NAME_LIMIT );
         break;

Robert Sprowson's avatar
Robert Sprowson committed
963
      case 'N': /* -n disable network browsing */
964 965 966
         Lgn_Logoff();
         break;

Robert Sprowson's avatar
Robert Sprowson committed
967
      case 'M': /* -m<name> use name as the advertised NETBIOS name */
968 969 970 971
         line = copy_space( LM_Vars.machinename, line+1, NAME_LIMIT );
         strcpyn_upper( LM_Vars.machinename,LM_Vars.machinename,NAME_LIMIT );
         break;

Robert Sprowson's avatar
Robert Sprowson committed
972
      case 'I': /* -i use NBIP */
Stewart Brodie's avatar
Stewart Brodie committed
973
         LanMan_InitTransport(NB_NBIP_Setup);
974 975
         break;

976
#ifndef NO_NETBEUI
Robert Sprowson's avatar
Robert Sprowson committed
977
      case 'T': /* -t use NetBEUI */
Stewart Brodie's avatar
Stewart Brodie committed
978
         LanMan_InitTransport(NB_NetBEUI_Setup);
979
         break;
980
#endif
981 982 983 984 985 986 987 988 989 990 991 992 993 994

      default:
         return ECMDLINE;
    }
  }

  return OK;
}


/* ------------------------------- */

void LM_Boot(void)
{
Stewart Brodie's avatar
Stewart Brodie committed
995
  int tries=1;
996 997 998 999 1000 1001
  int tmp;
  err_t res;
  char *serv_name;
  char fs_name [ FSERVER_LEN+1 ];

  if (LM_Vars.initialised < LMInitState_FullyInited) {
Robert Sprowson's avatar
Robert Sprowson committed
1002
    debug1("LM_Boot called, but cannot comply: %s\n", LM_Status());
1003 1004 1005 1006 1007 1008 1009 1010
    LM_Vars.initialised = LMInitState_Boot;
    return;
  }

  GetFSName(fs_name);

  if ( strlen(fs_name) == 0 )
  {
Robert Sprowson's avatar
Robert Sprowson committed
1011
    debug0("Auto-boot: server name has not been set...\n");
1012 1013 1014 1015 1016
    return;
  }

  /* Ready to go... */

Stewart Brodie's avatar
Stewart Brodie committed
1017 1018 1019 1020
  for (;;) {
    serv_name = RPC_GetDomainController(fs_name);
    if ( serv_name == NULL )
      serv_name = fs_name;
1021

Robert Sprowson's avatar
Robert Sprowson committed
1022
    debug1( "Server name '%s'\n", serv_name );
1023

Stewart Brodie's avatar
Stewart Brodie committed
1024
    /* Wash'n'go... */
1025

Stewart Brodie's avatar
Stewart Brodie committed
1026 1027 1028 1029 1030
    res =  Omni_MountServer ( serv_name,  /* Server */
            "ARMBOOT", "", /* User name & password */
            "BOOT",        /* Mountname */
            "ARMBOOT",     /* Drive name */
            &tmp );          /* MountID_out */
1031

Stewart Brodie's avatar
Stewart Brodie committed
1032 1033
    if ( res != OK )
    {
Robert Sprowson's avatar
Robert Sprowson committed
1034 1035
      printf("%s '%s' - ", MsgLookup("BootBad"), serv_name);
      printf("%s", MsgError(res)->errmess);
Stewart Brodie's avatar
Stewart Brodie committed
1036 1037 1038 1039 1040 1041 1042 1043 1044 1045
      /* tmp will be zero unless the share was successfully created */
      if (tmp == 0)
      {
        char var_name[sizeof("Inet$ServerName12")];
        sprintf(var_name, "Inet$ServerName%d", ++tries);
        if (!_kernel_getenv(var_name, fs_name, FSERVER_LEN))
          continue; /* Try next server */
      }
    }
    break;
1046 1047 1048
  }
}

Stewart Brodie's avatar
Stewart Brodie committed
1049

1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064
/* ------------------------------- */


/* SNB 980224.
 *
 *
 *  This function has been split into two as it is inappropriate for some
 *  parts of this code to be executed during a service call.  The initialised
 *  member of LM_Vars has been promoted to 'int' type so that it can hold any
 *  of the values in the anonymous enum at the top of this file.  This is used
 *  to control the execution of the LM_init_phase_2 function.
 *
 *
 */

Stewart Brodie's avatar
Stewart Brodie committed
1065
_kernel_oserror *LM_Initialise(const char *cmd_tail, int pod_base, void *pw)
1066 1067 1068 1069
{
  _kernel_oserror *err;
  _kernel_swi_regs R;

Stewart Brodie's avatar
Stewart Brodie committed
1070 1071 1072 1073
  debug_initialise("LanManFS", "", "");
  debug_atexit();
  debug_set_options(0,0,0);
  debug_output_device(DEBUGIT_OUTPUT);
1074 1075 1076 1077 1078 1079 1080 1081
  LM_Vars.initialised = LMInitState_Uninitialised;

  (void)pod_base;
  if (pw != NULL)
  {
    LM_pw = (int)pw;
  }

Robert Sprowson's avatar
Robert Sprowson committed
1082 1083 1084 1085 1086 1087
  err = _swix(ResourceFS_RegisterFiles, _IN(0), Resources());
  if (err != NULL) return err;
  err = _swix(MessageTrans_OpenFile, _INR(0,2),
              msg_struct, "Resources:$.ThirdParty.OmniClient.LanManFS.Messages", 0);
  if (err != NULL) goto initdereg;

1088 1089 1090 1091 1092 1093 1094
  SetDefaultVars();

  R.r[0] = 129;
  R.r[1] = 0;
  R.r[2] = 255;
  _kernel_swi(OS_Byte, &R, &R);
  if (R.r[1] < 0xA2)
Robert Sprowson's avatar
Robert Sprowson committed
1095 1096 1097 1098
  {
    err = MsgError(ERISCOSVER);
    goto initclose;
  }
1099

Robert Sprowson's avatar
Robert Sprowson committed
1100
  if (cmd_tail != NULL)
1101
  {
Robert Sprowson's avatar
Robert Sprowson committed
1102 1103
    err = MsgError(ProcessCmdLine(cmd_tail));
    if (err != NULL) goto initclose;
1104 1105 1106
  }

  err = LM_Declare();
Robert Sprowson's avatar
Robert Sprowson committed
1107
  if (err != NULL) goto initclose;
1108 1109

  LM_Vars.initialised = LMInitState_PreInit;
1110

1111
  (void) LM_init_phase_2();
1112 1113 1114

#ifndef NO_NETBEUI
  /* Cheap way to set a callback ;-) Send service call announcing ourselves */
1115
  if (NB_InitedTransport == NB_NetBEUI_Setup) {
1116 1117 1118 1119 1120
    callevery_handler(&R, pw);
    callbackflag = 2;
  }
#endif

1121
  return NULL;
Robert Sprowson's avatar
Robert Sprowson committed
1122 1123 1124 1125 1126 1127

initclose:
  _swix(MessageTrans_CloseFile, _IN(0), msg_struct);
initdereg:
  _swix(ResourceFS_DeregisterFiles, _IN(0), Resources());
  return err;
1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142
}

static _kernel_oserror *LM_init_phase_2(void)
{
  /* Initialise various modules */

  enum { MAXEXITS = 4 };
  pfnShutdown shutdowns[MAXEXITS];
  int ctr = 0;
  int want_boot;
  int oldstate = LM_Vars.initialised;
  _kernel_oserror *err;

  want_boot = (LM_Vars.initialised == LMInitState_Boot);

Robert Sprowson's avatar
Robert Sprowson committed
1143
  debug0("Initialising...\n");
1144 1145 1146 1147 1148 1149 1150

  if (!FS_Init() || !SMB_Init()) goto initfailed;
  shutdowns[ctr++] = (pfnShutdown) SMB_Shutdown;
  if (!RPC_Init() || !Prn_Init()) goto initfailed;
  shutdowns[ctr++] = (pfnShutdown) Prn_Shutdown;
  if (!Stat_Init()) goto initfailed;

Robert Sprowson's avatar
Robert Sprowson committed
1151
  err = MsgError(Buf_Init());
1152 1153 1154 1155 1156 1157
  if (err != NULL) goto abort;

  shutdowns[ctr++] = (pfnShutdown) Buf_Shutdown;

  /* Try to start various modules */

Robert Sprowson's avatar
Robert Sprowson committed
1158
  debug0("Starting network transport...\n");
1159

Robert Sprowson's avatar
Robert Sprowson committed
1160
  err = MsgError( NB_Startup() );
1161 1162 1163 1164 1165 1166 1167
  if (err != NULL)
  {
    debug2(    "Error - NB_Startup() returned %d (%s)\n",err->errnum,err->errmess);
    goto abort;
  }

#if 0
Robert Sprowson's avatar
Robert Sprowson committed
1168
  debug0("Starting filing system...\n");
1169 1170 1171

  err = LM_Declare();
  if (err != NULL) {
Robert Sprowson's avatar
Robert Sprowson committed
1172
          debug1("LanManFS: %s\n", err->errmess);
1173 1174 1175 1176 1177
          NB_Shutdown();
          goto abort;
  }
#endif

<