1 /* ***********************************************************
   2    *                                                         *
   3    * Copyright, (C) Honeywell Bull Inc., 1987                *
   4    *                                                         *
   5    * Copyright, (C) Honeywell Information Systems Inc., 1985 *
   6    *                                                         *
   7    *********************************************************** */
   8 
   9 /* HISTORY COMMENTS:
  10   1) change(86-10-31,Rohs), approve(87-07-13,MCR7580), audit(87-07-13,Leskiw),
  11      install(87-08-07,MR12.1-1072):
  12      Created.
  13   2) change(87-10-27,Flegel), approve(87-10-29,MCR7787),
  14      audit(88-01-26,DGHowe), install(88-02-24,MR12.2-1028):
  15      Re-designed to have Multics BFT maintain ALL queues.
  16   3) change(88-02-19,Flegel), approve(88-09-07,MCR7978), audit(88-09-14,Lee),
  17      install(88-10-07,MR12.2-1145):
  18      Repair expand_path to correctly return the appropriate second component.
  19   4) change(88-09-28,Flegel), approve(88-09-28,MCR7998), audit(88-09-28,Lee),
  20      install(88-10-07,MR12.2-1145):
  21      Repair ascii mode for the transfer of small files (<512 Kbytes) to the PC.
  22                                                    END HISTORY COMMENTS */
  23 
  24 /* COMPILER: Lattice C, V2.15 */
  25 
  26 /**************************************************************
  27 
  28      BFT_LOAD.C
  29 
  30      This file contains the minor capabilites for
  31      Background File Transfer, and the routines needed to load
  32      BFT as a major capability on the PC.
  33 
  34 ***************************************************************/
  35 
  36 #include <stdio.h>
  37 #include <fcntl.h>
  38 #include <dos.h>
  39 #include <mowse.h>
  40 #include <bft.h>
  41 
  42 #define SEEK_START     0      /* Beginning positioning in lseek */
  43 #define SEEK_CURRENT   1      /* Current positioning in lseek */
  44 #define SEEK_EOF       2      /* EOF positioning in lseek */
  45 
  46 #define DOS_STAR_FIRST 0x4E   /* DOS Function to locate first starname entry */
  47 #define DOS_STAR_NEXT  0x4F   /* DOS Function to locate next starname entry */
  48 #define DOS_SET_DTA    0x1A   /* DOS Function to set DTA */
  49 
  50 #define MAXLONG        0x7FFFFFFF
  51 
  52 int _stack = STACKSIZE;     /* Lattice C constant to set stack size of a program */
  53 
  54 struct dta_struct           /* DTA structure for starnames */
  55 {
  56    char filler[30];
  57    char name[13];
  58 } dta;
  59 
  60 long lseek ();              /* File positioning */
  61 char *stptok();             /* C Runtime support */
  62 char *striptok();           /* Extracting tokens from messages */
  63 int  bftmajcap();           /* bft major capability handler */
  64 
  65 /* ^L */
  66 /************************************************************
  67 
  68      BFT_LOAD  (MAIN)
  69 
  70      PARAMETERS: ARGC - number of arguments on the command
  71                         line. (input)
  72 
  73      FUNCTION:   Loads the BFT major capbility into the CAT.
  74 
  75 *************************************************************/
  76 
  77 main (argc)
  78 
  79 int  argc;                            /* number of args */
  80 {
  81 int majnum;                           /* major capability number of the local system */
  82 int majnumr;                          /* major capability number of the remote system */
  83 int com_id;                           /* command id */
  84 int code;                             /* error code */
  85 mcb *mcb_ptr;                         /* mowse control block pointer */
  86 bft_data_ptr data_ptr;                /* pointer to bft's "static" data */
  87 
  88 
  89 /* make sure no additional args are given on the command line */
  90 
  91   if (argc > 1)
  92   {
  93      printf ("BFT:  Unexpected argument.\n   Usage: bft_load\n");
  94      return;
  95   }
  96 
  97 /* check to see if BFT is already on the local system */
  98 
  99   majnum = 0;
 100   if (findnumb ("BFT", WSLOCAL, &majnum) == 0)
 101   {
 102     fprintf (stderr, "BFT:  Already loaded.\n");
 103     return;
 104   }
 105 
 106 /* allocate space for bft's data */
 107 
 108   data_ptr = (bft_data_ptr) malloc (sizeof (bft_data));
 109   if (data_ptr == NULL)
 110   {
 111      fprintf (stderr, "BFT:  Memory allocation error.\n");
 112      return;
 113   }
 114 
 115 /* initialize variables that need it */
 116 
 117   data_ptr->source_file[0] = 0;
 118   data_ptr->source_flags = 0L;
 119   data_ptr->destination_file[0] = 0;
 120   data_ptr->destination_flags = 0L;
 121   data_ptr->inbuffpos = 0;
 122   data_ptr->outbuffpos = 0;
 123   data_ptr->inpos = 0L;
 124   data_ptr->outpos = 0L;
 125   data_ptr->inbufflen = 0;
 126   data_ptr->inbuffer[0] = '\0';
 127   data_ptr->outbuffer[0] = '\0';
 128   data_ptr->expand_dirname[0] = '\0';
 129 
 130 /* create the bft instance */
 131 
 132   if ((code = cretinst("BFT", bftmajcap, MAXARGSTRING, MAXARGSTRING, data_ptr, &mcb_ptr)) != 0)
 133   {
 134     free (data_ptr);
 135     return (bfterror (code, "Loading BFT.", NULL));
 136   }
 137 
 138 /* check to see if BFT is on the remote system, if not then load it */
 139 
 140   majnumr = 0;
 141   if (findnumb ("bft_main_", WSREMOTE, &majnumr) != 0)
 142   {
 143     if ((code = execom ("bft_main_", WSREMOTE, &com_id, mcb_ptr)) != 0)
 144     {
 145       destinst (&mcb_ptr);
 146       free (data_ptr);
 147       bfterror (code, "Loading remote bft_main_.", NULL);
 148       return;
 149     }
 150   }
 151 
 152 /* Make BFT resident */
 153 
 154   stayres (mcb_ptr);
 155 }
 156 /* ^L */
 157 /********************************************************************
 158 
 159      BFTMAJCAP
 160 
 161      PARAMETERS: MINUM      - Minor capability number to execute (input)
 162                  SENDER     - Major capability number of the sender (input)
 163                  ARG_STRING - The arguments passed to the minor (input)
 164                  ARG_LEN    - The length of the argument string (input)
 165                  DATA_PTR   - Pointer to the BFT data block (input)
 166                  MCB_PTR    - A pointer to the mowse control block (input)
 167 
 168      FUNCTION:   Executes the specified bft minor capability each of
 169                  which is described below.
 170 
 171 **********************************************************************/
 172 
 173 bftmajcap (minum, sender, arg_string, arg_len, data_ptr, mcb_ptr)
 174 
 175 int minum;                            /* minor capability number to call */
 176 int sender;                           /* major cap of the caller */
 177 int arg_len;                          /* length of the arg string */
 178 char *arg_string;                     /* string containing the argument */
 179 bft_data_ptr *data_ptr;               /* pointer to the BFT data block */
 180 mcb *mcb_ptr;                         /* pointer to the mowse control block */
 181 {
 182 char temp_str[MAXARGSTRING];          /* temporary message */
 183 
 184 
 185 /* switch on the minor capability */
 186 
 187   switch(minum)
 188   {
 189     case(BFT_SHUT_DOWN):
 190       bft_shut_down(mcb_ptr);
 191       break;
 192 
 193     case(CHECK_FILE_LENGTH):
 194       check_length(arg_string,arg_len,mcb_ptr,data_ptr);
 195       break;
 196 
 197    case(EXPAND_PC_PATH):
 198       expand_pc_path(arg_string,arg_len,mcb_ptr,data_ptr);
 199       break;
 200 
 201     case(INITIATE_FETCH):
 202       init_fetch (arg_string, arg_len, mcb_ptr, data_ptr);
 203       break;
 204 
 205     case(INITIATE_STORE):
 206       init_store (arg_string, arg_len, mcb_ptr, data_ptr);
 207       break;
 208 
 209     case(POSITION_FILE_POINTER):
 210       position_pointer (arg_string, arg_len, mcb_ptr, data_ptr);
 211       break;
 212 
 213     case(READ_ERROR):
 214       read_err (arg_string, arg_len, mcb_ptr, data_ptr);
 215       break;
 216 
 217     case(REC_DATA):
 218       rec_data(arg_string,arg_len,mcb_ptr,data_ptr);
 219       break;
 220 
 221     case(REC_EOF):
 222       receive_eof(arg_string,arg_len,mcb_ptr,data_ptr);
 223       break;
 224 
 225     case(SEND_DATA):
 226       send_data(arg_string,arg_len,mcb_ptr,data_ptr);
 227       break;
 228 
 229     case(SYSTEM_ERROR):
 230       system_shutdown();
 231       break;
 232 
 233     case(WRITE_ERROR):
 234       write_err (arg_string, arg_len, mcb_ptr, data_ptr);
 235       break;
 236 
 237     case(MESSAGE_TOO_LONG):
 238       bfterror (BFT_INVALID_MINOR, "message_too_long", mcb_ptr);
 239       system_shutdown();
 240       break;
 241 
 242     case(EXECUTE_COMMAND_REPLY):
 243       execute_command_reply(arg_string,arg_len,mcb_ptr,data_ptr);
 244       break;
 245 
 246     case(FAIL_CAPABILITY):
 247       bfterror (BFT_INVALID_MINOR, "fail_capability", mcb_ptr);
 248       system_shutdown();
 249       break;
 250 
 251     case(GET_STATUS):
 252       bfterror (BFT_INVALID_MINOR, "get_status", mcb_ptr);
 253       system_shutdown();
 254       break;
 255 
 256     case(QUERY_REPLY):
 257       bfterror (BFT_INVALID_MINOR, "query_reply", mcb_ptr);
 258       system_shutdown();
 259       break;
 260 
 261     case(RESET_APPLICATION):
 262       bfterror (BFT_INVALID_MINOR, "reset_application", mcb_ptr);
 263       system_shutdown();
 264       break;
 265 
 266     case(RESUME_APPLICATION):
 267       bfterror (BFT_INVALID_MINOR, "resume_application", mcb_ptr);
 268       system_shutdown();
 269       break;
 270 
 271     case(RESPONSE_CONNECT):
 272       bfterror (BFT_INVALID_MINOR, "response_connect", mcb_ptr);
 273       system_shutdown();
 274       break;
 275 
 276     case(RESPONSE_DISCONNECT):
 277       disconnect_response(mcb_ptr);
 278       break;
 279 
 280     case(REQUEST_CONNECT):
 281       bfterror (BFT_INVALID_MINOR, "request_connect", mcb_ptr);
 282       system_shutdown();
 283       break;
 284 
 285     case(REQUEST_DISCONNECT):
 286       disconnect_request(mcb_ptr,sender);
 287       break;
 288 
 289     case(SUSPEND_APPLICATION):
 290       bfterror (BFT_INVALID_MINOR, "suspend_application", mcb_ptr);
 291       system_shutdown();
 292       break;
 293 
 294     case(TERMINATE_APPLICATION):
 295       putbgmes(mcb_ptr,0,"BFT","BFT terminating.");
 296       destinst(&mcb_ptr);
 297       break;
 298 
 299     case(WAKE_UP):
 300       bfterror (BFT_INVALID_MINOR, "wake_up", mcb_ptr);
 301       system_shutdown();
 302       break;
 303 
 304     default:
 305       sprintf (temp_str, "%d", minum);
 306       bfterror (BFT_INVALID_MINOR, temp_str, mcb_ptr);
 307       system_shutdown();
 308       break;
 309   }
 310 }
 311 /* ^L */
 312 /******************************************************************
 313 
 314 BFT MINOR CAPABILITIES
 315 
 316 ********************************************************************/
 317 
 318 /******************************************************************
 319 
 320     BFT_SHUT_DOWN
 321 
 322     PARAMETERS: MCB_PTR    - pointer to the mowse control block (input)
 323 
 324     INFO EXTRACTED FROM ARGLIST:  NONE
 325 
 326     FUNCTION:   Shuts bft down.
 327 
 328 ********************************************************************/
 329 
 330 bft_shut_down(mcb_ptr)
 331 
 332 mcb  *mcb_ptr;                      /* pointer to the mowse control block */
 333 {
 334 int   majnum;                       /* major capability number of remote */
 335 
 336 
 337 /* Display the shutdown message */
 338 
 339   putbgmes (mcb_ptr, 0, "BFT", "BFT is shutting down.");
 340 
 341 /* check to see if BFT is on the remote system */
 342 
 343   majnum = 0;
 344   if (findnumb("bft_main_",WSREMOTE,&majnum) != 0)
 345   {
 346     putbgmes (mcb_ptr, 0, "BFT", "BFT major capability not found. BFT aborted.");
 347     return(0);
 348   }
 349 
 350   disrqst (majnum, mcb_ptr);
 351 }
 352 /* ^L */
 353 /******************************************************************
 354 
 355     CHECK_FILE_LENGTH
 356 
 357     PARAMETERS: ARG_STRING - string containing the argument (input)
 358                 ARG_LEN    - length of the arg string (input)
 359                 MCB_PTR    - pointer to the mowse control block (input)
 360                 DATA_PTR   - pointer to BFT data structure (input)
 361 
 362     INFO EXTRACTED FROM ARGLIST:
 363                 DESTINATION FILE NAME - filename on local system
 364                 DESTINATION FLAGS     - transfer flags
 365 
 366     FUNCTION:   Finds out how much is in the destination file
 367                 and calls position file pointer on the remote system.
 368                 This is indicating that a recover store is in progress, so
 369                 remember the stuff that was given to us.
 370 
 371 ********************************************************************/
 372 
 373 check_length (p_arg_string, p_arg_len, p_mcb_ptr, p_data_ptr)
 374 
 375 int  p_arg_len;                       /* length of the arg string */
 376 char *p_arg_string;                   /* string containing the argument */
 377 mcb  *p_mcb_ptr;                      /* pointer to the mowse control block */
 378 bft_data_ptr p_data_ptr;              /* pointer to BFT data structure */
 379 {
 380 char  token[MAXARGSTRING];            /* destination file being checked */
 381 char  *arg_pos;                       /* argument position */
 382 int   fp_dest;                        /* incoming file pointer */
 383 char  message[MAXARGSTRING];          /* Output message */
 384 int   message_len;                    /* Length of message */
 385 char  temp_str[MAXARGSTRING];         /* Temporary message holder */
 386 int   buff_pos;                       /* Position in buffer */
 387 int   buff_len;                       /* Length of buffer */
 388 int   line_cnt;                       /* Lines in file */
 389 int   open_mode;                      /* Modes for opening */
 390 
 391 
 392 /* extract the source and destination file */
 393 
 394   arg_pos = p_arg_string;
 395   arg_pos = striptok (arg_pos, p_data_ptr->destination_file);
 396   arg_pos = striptok (arg_pos, token);
 397   char2long (token, &p_data_ptr->destination_flags);
 398 
 399 /* if the destination file is not there return an error */
 400 
 401   open_mode = O_RDONLY;
 402   if (p_data_ptr->destination_flags & BFT_BINARY)
 403     open_mode |= O_RAW;
 404 
 405   if ((fp_dest = open (p_data_ptr->destination_file, open_mode)) == -1)
 406   {
 407     sprintf (temp_str, "%s opening %s.", getsyserr (errno), p_data_ptr->destination_file);
 408     message[0] = 0;
 409     message_len = 0;
 410     message_len = addtoken (message, message_len, temp_str, 0);
 411     executeb (WRITE_ERROR, message, message_len, p_mcb_ptr);
 412     return;
 413   }
 414 
 415 /* Calculate the length of the file:  chars for binary, lines for ascii */
 416 
 417   if (p_data_ptr->destination_flags & BFT_BINARY)
 418     sprintf (temp_str, "%ld", lseek (fp_dest, 0L, SEEK_EOF));
 419   else
 420   {
 421     p_data_ptr->outpos = 0;
 422     if ((line_cnt = count_lines (fp_dest, p_data_ptr->outbuffer, &p_data_ptr->outpos, &buff_len, &buff_pos)) == -1)
 423     {
 424       sprintf (temp_str, "%s line counting %s.", getsyserr (errno), p_data_ptr->destination_file);
 425       message[0] = 0;
 426       message_len = 0;
 427       message_len = addtoken (message, message_len, temp_str, 0);
 428       executeb (WRITE_ERROR, message, message_len, p_mcb_ptr);
 429       close (fp_dest);
 430       return;
 431     }
 432     sprintf (temp_str, "%d", line_cnt);
 433 
 434 /* Subtract the half line from the positioning count */
 435 
 436     p_data_ptr->outpos -= (buff_len - buff_pos);
 437   }
 438   close(fp_dest);
 439 
 440 /* Because we are positioning, we are setting up a new transfer, so store it */
 441 
 442   p_data_ptr->outbuffpos = 0;
 443 
 444 /* call position file pointer on the remote system */
 445 
 446   message_len = 0;
 447   message[0] = 0;
 448   message_len = addtoken (message, message_len, temp_str, 0);
 449 
 450   executeb (POSITION_FILE_POINTER, message, message_len, p_mcb_ptr);
 451 }
 452 /* ^L */
 453 /*******************************************************************
 454 
 455      COUNT_LINES
 456 
 457      PARAMETERS: FP       - file to examine                (INPUT)
 458                  BUFF     - buffer to use                  (INPUT)
 459                  FILE_POS - file position of last eol+1    (OUTPUT)
 460                           - maximum eols to pass           (INPUT)
 461                  BUFF_LEN - length of remaining buffer     (OUTPUT)
 462                  BUFF_POS - buffer position of last eol+1  (OUTPUT)
 463 
 464      FUNCTION:   Count the number of lines in the file, already opened.
 465                  If the initial FILE_POS is 0, then count to the last EOL.
 466                  Ultimately, the actual file_pointer (FP) is set to the next
 467                  character after the last block read into buff.
 468 
 469 ********************************************************************/
 470 
 471 count_lines (fp, buff, file_pos, buff_len, buff_pos)
 472 
 473 int  fp;                     /* File pointer */
 474 char *buff;                  /* Buffer to use fo counting */
 475 long *file_pos;              /* File position */
 476 int  *buff_len;              /* Buffer length */
 477 int  *buff_pos;              /* Position in buffer */
 478 {
 479 long line_cnt;               /* Number of lines */
 480 int  last_eol;               /* Position in buffer of last EOL */
 481 int  status;                 /* Read status */
 482 long max_count;              /* How far to count */
 483 int  i;
 484 
 485 
 486 /* Read chunks of the file counting LFs until either MAX or EOF */
 487 
 488   max_count = (*file_pos == 0) ? MAXLONG : *file_pos;
 489 
 490   line_cnt = 0;
 491   while (line_cnt < max_count)
 492   {
 493     if ((status = read (fp, buff, DISKBUFF)) <= 0)
 494     {
 495       if (*file_pos != 0)                             /* Error encountered */
 496         return (-1);
 497       else                                            /* Counted all thats there */
 498       {
 499         *file_pos = lseek (fp, 0L, SEEK_CURRENT);
 500         return ((int)line_cnt);
 501       }
 502     }
 503 
 504 /* Count of LFs */
 505 
 506     for (i = 0, last_eol = 0; (i < status) && (line_cnt < max_count); i++)
 507     {
 508       if (buff[i] == LF)
 509       {
 510         line_cnt += 1;
 511         last_eol = i+1;
 512       }
 513     }
 514 
 515 /* Update the return values */
 516 
 517     *buff_len = status;
 518     *buff_pos = last_eol;
 519   }
 520 
 521 /* Return the line count */
 522 
 523   *file_pos = lseek (fp, 0L, SEEK_CURRENT);
 524   return ((int)line_cnt);
 525 }
 526 /* ^L */
 527 /*******************************************************************
 528 
 529      EXPAND_PC_PATH
 530 
 531      PARAMETERS: ARG_STRING - string containing the argument (input)
 532                  ARG_LEN    - length of the arg string (input)
 533                  MCB_PTR    - pointer to the mowse control block (input)
 534                  DATA_PTR   - pointer to BFT data structure (input)
 535 
 536      INFO EXTRACTED FROM ARGLIST:
 537                  LOCATOR    - position in starname matching (FIRST || NEXT)
 538                  PATH       - path to be expanded
 539                  REQUEST_ID - major ID of request
 540                  DIRECTION  - direction of request
 541 
 542      FUNCTION:   Expand the PC pathname to an absolute pathname and
 543                  return the results to FULL_PC_PATH on MU:BFT.
 544 
 545 ********************************************************************/
 546 
 547 expand_pc_path (arg_string, arg_len, mcb_ptr, data_ptr)
 548 
 549 int arg_len;                          /* length of the arg string */
 550 char *arg_string;                     /* string containing the argument */
 551 mcb *mcb_ptr;                         /* pointer to the mowse control block */
 552 bft_data_ptr data_ptr;                /* pointer to BFT data structure */
 553 {
 554 char path[PATHNAMESIZE];              /* Path to expand */
 555 char *arg_pos;                        /* Argument positioning */
 556 char message[MAXARGSTRING];           /* Return message */
 557 int  message_len;                     /* Return message length */
 558 char request_id[2];                   /* Request ID of expansion */
 559 char entryname[ENTRYNAMESIZE];        /* Entryname porition of request */
 560 char direction[2];                    /* Direction of transfer */
 561 char locator[2];                      /* Starname mathc position */
 562 int  code;
 563 
 564 
 565 /* Strip the relative path, major, minor IDs from the list */
 566 
 567    arg_pos = arg_string;
 568    arg_pos = striptok (arg_pos, locator);
 569    arg_pos = striptok (arg_pos, path);
 570    arg_pos = striptok (arg_pos, request_id);
 571    arg_pos = striptok (arg_pos, direction);
 572 
 573 /* Expand the path, if one given, otherwise get next match */
 574 
 575    set_dta (&dta);
 576 
 577    if (locator[0] == BFT_FIRST)
 578    {
 579       getpath (path);
 580       expand_path (path, data_ptr->expand_dirname, entryname);
 581       sprintf (path, "%s\\%s", data_ptr->expand_dirname, entryname);
 582       code = 1;
 583 
 584       if (stpbrk (path, "*?") != NULL)
 585       {
 586          code = findfirst (path);
 587          sprintf (path, "%s\\%s", data_ptr->expand_dirname, dta.name);
 588       }
 589    }
 590    else
 591    {
 592       code = findnext ();
 593       sprintf (path, "%s\\%s", data_ptr->expand_dirname, dta.name);
 594    }
 595 
 596    if (code == 0)
 597       path[0] = '\0';
 598 
 599 /* Send the absolute path to MU:FULL_PC_PATH */
 600 
 601    message[0] = 0;
 602    message_len = 0;
 603    message_len = addtoken (message, message_len, path, strlen (path));
 604    message_len = addtoken (message, message_len, request_id, 0);
 605    message_len = addtoken (message, message_len, direction, 1);
 606    executeb (FULL_PC_PATH, message, message_len, mcb_ptr);
 607 
 608    return;
 609 }
 610 /* ^L */
 611 /********************************************************************
 612 
 613      INITIATE_FETCH
 614 
 615      PARAMETERS: ARG_STRING - string containing the argument (input)
 616                  ARG_LEN    - length of the arg string (input)
 617                  MCB_PTR    - pointer to the mowse control block (input)
 618                  DATA_PTR   - pointer to BFT data structure (input)
 619 
 620      INFO EXTRACTED FROM ARGLIST:
 621                  SOURCE FILE NAME - filename on local system
 622                  SOURCE FLAGS     - transfer modes
 623 
 624      FUNCTION:   Multics is beginning a PC -> Multics transfer
 625 
 626 ********************************************************************/
 627 
 628 init_fetch (arg_string, arg_len, mcb_ptr, data_ptr)
 629 
 630 int arg_len;                          /* length of the arg string */
 631 char *arg_string;                     /* string containing the argument */
 632 mcb *mcb_ptr;                         /* pointer to the mowse control block */
 633 bft_data_ptr data_ptr;                /* pointer to BFT data structure */
 634 {
 635 char  *arg_pos;                       /* argument position */
 636 char  token         [MAXARGSTRING];   /* Argument token */
 637 char  out_str       [MAXARGSTRING];   /* arguments to remote routines */
 638 int   out_len;                        /* length of out_str */
 639 char  temp_str      [MAXARGSTRING];   /* arguments to remote routines */
 640 int   temp_len;                       /* length of temp_str */
 641 int   fp_source;                      /* outgoing file pointer */
 642 
 643 
 644 /* extract the source file */
 645 
 646   arg_pos = arg_string;
 647   arg_pos = striptok (arg_pos, data_ptr->source_file);
 648   arg_pos = striptok (arg_pos, token);
 649   char2long (token, &data_ptr->source_flags);
 650 
 651 /* if the file is not there return an error */
 652 
 653   fp_source = open (data_ptr->source_file, O_RDONLY | O_RAW);
 654   if (fp_source == -1)
 655   {
 656     sprintf (out_str, "%s opening %s.", getsyserr (errno), data_ptr->source_file);
 657     temp_str[0]=0;
 658     temp_len = 0;
 659     temp_len = addtoken (temp_str, temp_len, out_str, 0);
 660     data_ptr->source_file[0]=0;
 661     executeb (READ_ERROR, temp_str, temp_len, mcb_ptr);
 662     return;
 663   }
 664 
 665 /* reset all the input buffers for file input */
 666 
 667   data_ptr->inbuffpos = 0;
 668   data_ptr->inpos = 0L;
 669   close(fp_source);
 670 
 671 /* Call send data on the local system */
 672 
 673   out_str[0] = 0;
 674   out_len = 0;
 675   bftmajcap (SEND_DATA, 0, out_str, out_len, data_ptr, mcb_ptr);
 676   return;
 677 }
 678 /* ^L */
 679 /********************************************************************
 680 
 681      INITIATE_STORE
 682 
 683      PARAMETERS: ARG_STRING - string containing the argument (input)
 684                  ARG_LEN    - length of the arg string (input)
 685                  MCB_PTR    - pointer to the mowse control block (input)
 686                  DATA_PTR   - pointer to BFT data structure (input)
 687 
 688      INFO EXTRACTED FROM ARGLIST:
 689                  DESTINATION FILENAME - the filename that the remote
 690                                         requests to transfer to.
 691                  FLAGS                - transfer modes
 692 
 693      FUNCTION:   Multics is beginning a transfer Multics -> PC transfer.
 694 
 695 *******************************************************************/
 696 
 697 init_store (arg_string, arg_len, mcb_ptr, data_ptr)
 698 
 699 int arg_len;                          /* length of the arg string */
 700 char *arg_string;                     /* string containing the argument */
 701 mcb *mcb_ptr;                         /* pointer to the mowse control block */
 702 bft_data_ptr data_ptr;                /* pointer to BFT data structure */
 703 {
 704 char  *arg_pos;                       /* Argumen position */
 705 char  token         [MAXARGSTRING];   /* Stripped token */
 706 char  temp_str      [STRINGSIZE];     /* temp string */
 707 int   temp_len;                       /* length of temp string */
 708 char  out_str       [MAXARGSTRING];   /* arguments to remote routines */
 709 int   out_len;                        /* length of out_str */
 710 int   fp_dest;                        /* outgoing file pointer */
 711 
 712 
 713 /* get the destination filename and transfer flags out of the arglist */
 714 
 715   arg_pos = arg_string;
 716   arg_pos = striptok (arg_pos, data_ptr->destination_file);
 717   arg_pos = striptok (arg_pos, token);
 718   char2long (token, &data_ptr->destination_flags);
 719 
 720 /* call remote write error if unable to open the file */
 721 
 722   fp_dest = open (data_ptr->destination_file, O_WRONLY | O_RAW | O_CREAT | O_TRUNC);
 723   if (fp_dest == -1)
 724   {
 725     sprintf (out_str, "%s opening %s.", getsyserr (errno), data_ptr->destination_file);
 726     temp_str[0]=0;
 727     temp_len = 0;
 728     temp_len = addtoken (temp_str, temp_len, out_str, 0);
 729 
 730     executeb (WRITE_ERROR, temp_str, temp_len, mcb_ptr);
 731     return;
 732   }
 733 
 734 /* make the file the current destination if all is ok */
 735 
 736   data_ptr->outbuffpos = 0;
 737   close (fp_dest);
 738 
 739 /* call SEND_DATA */
 740 
 741   executeb (SEND_DATA, out_str, 0, mcb_ptr);
 742 }
 743 /* ^L */
 744 /******************************************************************
 745 
 746      POSITION_FILE_POINTER
 747 
 748      PARAMETERS: ARG_STRING - string containing the argument (input)
 749                  ARG_LEN    - length of the arg string (input)
 750                  MCB_PTR    - pointer to the mowse control block (input)
 751                  DATA_PTR   - pointer to BFT data structure (input)
 752 
 753      INFO EXTRACTED FROM ARGLIST:
 754                  SOURCE FILE NAME - the source file to open
 755                  FILE SIZE        - position the pointer this many bytes into the file
 756                  SOURCE FLAGS     - transfer flags
 757 
 758      FUNCTION:   Opens the source file name to the position passed in
 759                  the file size and then calls send data locally.
 760 
 761 ********************************************************************/
 762 
 763 position_pointer (arg_string, arg_len, mcb_ptr, data_ptr)
 764 
 765 int arg_len;                          /* length of the arg string */
 766 char *arg_string;                     /* string containing the argument */
 767 mcb *mcb_ptr;                         /* pointer to the mowse control block */
 768 bft_data_ptr data_ptr;                /* pointer to BFT data structure */
 769 {
 770 char  token[MAXARGSTRING];            /* Token from message */
 771 char  *arg_pos;                       /* Arg list position */
 772 char  temp_str      [STRINGSIZE];     /* temp string */
 773 char  out_str       [MAXARGSTRING];   /* arguments to remote routines */
 774 int   out_len;                        /* length of out_str */
 775 int   fp_source;                      /* outgoing file pointer */
 776 int   line_pos;                       /* Line count positioning */
 777 int   i;
 778 int   open_mode;
 779 
 780 
 781 /* extract the path and and new position */
 782 
 783   arg_pos = arg_string;
 784   arg_pos = striptok (arg_pos, data_ptr->source_file);
 785   arg_pos = striptok (arg_pos, token);
 786   data_ptr->inpos = (long) atoi (token);
 787   arg_pos = striptok (arg_pos, token);
 788   char2long (token, &data_ptr->source_flags);
 789 
 790 /* if the file is not there return an error */
 791 
 792   open_mode = O_RDONLY;
 793   if (data_ptr->source_flags & BFT_BINARY)
 794     open_mode |= O_RAW;
 795   fp_source = open (data_ptr->source_file, open_mode);
 796   if (fp_source == -1)
 797   {
 798     sprintf (temp_str, "%s opening %s.", getsyserr (errno), data_ptr->source_file);
 799     out_str[0]=0;
 800     out_len = 0;
 801     out_len = addtoken (out_str, out_len, temp_str, 0);
 802     executeb (READ_ERROR, out_str, out_len, mcb_ptr);
 803     data_ptr->source_file[0]=0;
 804     return;
 805   }
 806 
 807 /* position input buffers to the appropriate position in the file */
 808 
 809   data_ptr->inbufflen = 0;
 810   data_ptr->inbuffpos = 0;
 811 
 812 /* Set the input file pointer position to the appropriate line count for ascii mode */
 813 
 814   if (!(data_ptr->source_flags & BFT_BINARY))
 815   {
 816     if (count_lines (fp_source, data_ptr->inbuffer, &data_ptr->inpos, &data_ptr->inbufflen, &data_ptr->inbuffpos) == -1)
 817     {
 818       sprintf (temp_str, "%s positioning %s.", getsyserr (errno), data_ptr->source_file);
 819       out_str[0]=0;
 820       out_len = 0;
 821       out_len = addtoken (out_str, out_len, temp_str, 0);
 822       executeb (READ_ERROR, out_str, out_len, mcb_ptr);
 823       data_ptr->source_file[0]=0;
 824       close (fp_source);
 825       return;
 826     }
 827   }
 828   close(fp_source);
 829 
 830 /* call send data on the local system */
 831 
 832   out_str[0] = 0;
 833   out_len = 0;
 834   bftmajcap (SEND_DATA, 0, out_str, out_len, data_ptr, mcb_ptr);
 835 }
 836 /* ^L */
 837 /******************************************************************
 838 
 839      RECEIVE_DATA
 840 
 841      PARAMETERS: ARG_STRING - string containing the argument (input)
 842                  ARG_LEN    - length of the arg string (input)
 843                  MCB_PTR    - pointer to the mowse control block (input)
 844                  DATA_PTR   - pointer to BFT data structure (input)
 845 
 846      INFO EXTRACTED FROM ARGLIST:
 847                  PART OF FILE - x number of bytes sent from the remote.
 848 
 849      FUNCTION:   Writes out x number of bytes to the destination file.
 850                  if any error has occured then remote write error is called
 851                  otherwise send data is called on the remote.
 852 
 853 ********************************************************************/
 854 
 855 rec_data (arg_string, arg_len, mcb_ptr, data_ptr)
 856 
 857 int arg_len;                          /* length of the arg string */
 858 char *arg_string;                     /* string containing the argument */
 859 mcb *mcb_ptr;                         /* pointer to the mowse control block */
 860 bft_data_ptr data_ptr;                /* pointer to BFT data structure */
 861 {
 862 int   i;                              /* temporary vars */
 863 char  out_str       [MAXARGSTRING];   /* arguments to remote routines */
 864 int   out_len;                        /* length of out_str */
 865 char  temp_str      [MAXARGSTRING];   /* arguments to remote routines */
 866 int   temp_len;                       /* length of temp_str */
 867 
 868 
 869 /* write out the info in the arg_string to the file buffer */
 870 
 871   i = put_data (arg_string, arg_len, data_ptr);
 872 
 873 /* if there were any problems then call remote write error */
 874 
 875   if (i != arg_len)
 876   {
 877     sprintf (out_str, "%s writing %s.", getsyserr (errno), data_ptr->destination_file);
 878     temp_str[0]=0;
 879     temp_len = 0;
 880     temp_len = addtoken (temp_str, temp_len, out_str, 0);
 881     executeb (WRITE_ERROR, temp_str, temp_len, mcb_ptr);
 882     data_ptr->destination_file[0]=0;
 883     return;
 884   }
 885 
 886 /* otherwise call send data on the remote */
 887 
 888   out_str[0]=0;
 889   out_len = 0;
 890   executeb (SEND_DATA, out_str, out_len, mcb_ptr);
 891   return;
 892 }
 893 /* ^L */
 894 /******************************************************************
 895 
 896      RECEIVE_EOF
 897 
 898      PARAMETERS: ARG_STRING - string containing the argument (input)
 899                  ARG_LEN    - length of the arg string (input)
 900                  MCB_PTR    - pointer to the mowse control block (input)
 901                  DATA_PTR   - pointer to BFT data structure (input)
 902 
 903      INFO EXTRACTED FROM ARGLIST: - none
 904 
 905      FUNCTION:   Writes out any remaining bytes in the output buffer
 906                  to the file, the file is closed and and the queue emptied
 907 
 908 ********************************************************************/
 909 
 910 receive_eof (arg_string, arg_len, mcb_ptr, data_ptr)
 911 
 912 int arg_len;                          /* length of the arg string */
 913 char *arg_string;                     /* string containing the argument */
 914 mcb *mcb_ptr;                         /* pointer to the mowse control block */
 915 bft_data_ptr data_ptr;                /* pointer to BFT data structure */
 916 {
 917 int   fp_dest;                        /* incoming file pointer */
 918 int   open_mode;                      /* Opening modes */
 919 int   status;                         /* error codes from reads and writes */
 920 char  out_str       [MAXARGSTRING];   /* arguments to remote routines */
 921 int   out_len;                        /* length of out_str */
 922 char  temp_str      [MAXARGSTRING];   /* arguments to remote routines */
 923 int   temp_len;                       /* length of temp_str */
 924 
 925 
 926 /* open the file for output */
 927 
 928   open_mode = O_RDWR;
 929   if (data_ptr->destination_flags & BFT_BINARY)
 930     open_mode |= O_RAW;
 931   fp_dest = open (data_ptr->destination_file, open_mode);
 932 
 933 /* if output file could not be opened call remote write error */
 934 
 935   if (fp_dest == -1)
 936   {
 937     sprintf (temp_str, "%s opening %s.", getsyserr (errno), data_ptr->destination_file);
 938     out_str[0]=0;
 939     out_len = 0;
 940     out_len = addtoken (out_str, out_len, temp_str, 0);
 941     executeb (WRITE_ERROR, out_str, out_len, mcb_ptr);
 942     return;
 943   }
 944 
 945 /* write out the buffer to the end of the file */
 946 
 947   lseek (fp_dest, 0L, SEEK_EOF);
 948   status = write (fp_dest, data_ptr->outbuffer, data_ptr->outbuffpos);
 949 
 950 /* if any problems writing to the file call remote write error */
 951 
 952   if (status < 0)
 953   {
 954     close(fp_dest);
 955     sprintf (out_str, "%s writing %s", getsyserr (errno), data_ptr->destination_file);
 956     temp_str[0]=0;
 957     temp_len = 0;
 958     temp_len = addtoken (temp_str, temp_len, out_str, 0);
 959     executeb (WRITE_ERROR, temp_str, temp_len, mcb_ptr);
 960     return;
 961   }
 962   else if (data_ptr->destination_flags & BFT_NOTIFY)
 963     putbgmes (mcb_ptr, 0, "BFT", "Completed transfer of %s.", data_ptr->destination_file);
 964 
 965 /* reset the buffer and close the file */
 966 
 967   data_ptr->outbuffpos = 0;
 968   close (fp_dest);
 969 
 970 /* clean up the destination and check for any remote to local transfers */
 971 
 972   data_ptr->destination_file[0] = 0;
 973 
 974   return;
 975 }
 976 /* ^L */
 977 /******************************************************************
 978 
 979      READ_ERROR
 980 
 981      PARAMETERS: ARG_STRING - string containing the argument (input)
 982                  ARG_LEN    - length of the arg string (input)
 983                  MCB_PTR    - pointer to the mowse control block (input)
 984                  DATA_PTR   - pointer to BFT data structure (input)
 985 
 986      INFO EXTRACTED FROM ARGLIST:
 987                  ERROR STRING - an error message describing the problem
 988 
 989      FUNCTION:   A reading error has occurred on Multics.  Remove current
 990                  store source from the data_block and initiate a store
 991                  through the remote.
 992 
 993 ********************************************************************/
 994 
 995 read_err (arg_string, arg_len, mcb_ptr, data_ptr)
 996 
 997 char *arg_string;                     /* string containing the argument */
 998 int arg_len;                          /* length of the arg string */
 999 mcb *mcb_ptr;                         /* pointer to the mowse control block */
1000 bft_data_ptr data_ptr;                /* pointer to BFT data structure */
1001 {
1002 char message[MAXARGSTRING];           /* Return message */
1003 int  message_len;                     /* Return message length */
1004 
1005 
1006 /* Display the error */
1007 
1008   message_len = (arg_len > WSPAKSIZ) ? WSPAKSIZ : arg_len;
1009   strncpy (message, arg_string, message_len);
1010   message[message_len] = 0;
1011   putbgmes (mcb_ptr, 0, "BFT", message);
1012 
1013 /* Close the destination file */
1014 
1015   data_ptr->destination_file[0] = 0;
1016 
1017 /* Initiate another store */
1018 
1019   message[0] = 0;
1020   message_len = 0;
1021   executeb (INITIATE_STORE, message, message_len, mcb_ptr);
1022 }
1023 /* ^L */
1024 /******************************************************************
1025 
1026      WRITE_ERROR
1027 
1028      PARAMETERS: ARG_STRING - string containing the argument (input)
1029                  ARG_LEN    - length of the arg string (input)
1030                  MCB_PTR    - pointer to the mowse control block (input)
1031                  DATA_PTR   - pointer to BFT data structure (input)
1032 
1033      INFO EXTRACTED FROM ARGLIST:
1034                  ERROR STRING -  error message describing the problem
1035 
1036      FUNCTION:   clears flags and queues after error, calls putbgmes
1037                  with the error message and calls check store flags
1038                  to see if any other transfers can be initiated.
1039 
1040 ********************************************************************/
1041 
1042 write_err (arg_string, arg_len, mcb_ptr, data_ptr)
1043 
1044 char *arg_string;                     /* string containing the argument */
1045 int arg_len;                          /* length of the arg string */
1046 mcb *mcb_ptr;                         /* pointer to the mowse control block */
1047 bft_data_ptr data_ptr;                /* pointer to BFT data structure */
1048 {
1049 char  message[MAXARGSTRING];          /* Return message */
1050 int   message_len;                    /* Return message length */
1051 
1052 
1053 /* Display the error */
1054 
1055   message_len = (arg_len > WSPAKSIZ) ? WSPAKSIZ : arg_len;
1056   strncpy (message, arg_string, message_len);
1057   message[message_len] = 0;
1058   putbgmes(mcb_ptr, 0, "BFT", message);
1059 
1060 /* Close the source file */
1061 
1062   data_ptr->source_file[0] = 0;
1063 
1064 /* Initiate another fetch */
1065 
1066   message[0] = 0;
1067   message_len = 0;
1068   executeb (INITIATE_FETCH, message, message_len, mcb_ptr);
1069 }
1070 /* ^L */
1071 /*******************************************************************
1072 
1073      SEND_DATA
1074 
1075      PARAMETERS: ARG_STRING - string containing the argument (input)
1076                  ARG_LEN    - length of the arg string (input)
1077                  MCB_PTR    - pointer to the mowse control block (input)
1078                  DATA_PTR   - pointer to BFT data structure (input)
1079 
1080      INFO EXTRACTED FROM ARGLIST: - none.
1081 
1082      FUNCTION:   Read in x number of bytes from the source file.
1083                  if any error has occured then remote read error is called
1084                  otherwise receive_data is called on the remote.
1085 
1086 ********************************************************************/
1087 
1088 send_data (arg_string, arg_len, mcb_ptr, data_ptr)
1089 
1090 int arg_len;                          /* length of the arg string */
1091 char *arg_string;                     /* string containing the argument */
1092 mcb *mcb_ptr;                         /* pointer to the mowse control block */
1093 bft_data_ptr data_ptr;                /* pointer to BFT data structure */
1094 {
1095 int   i;                              /* temporary vars */
1096 char  out_str       [MAXARGSTRING];   /* arguments to remote routines */
1097 int   out_len;                        /* length of out_str */
1098 char  temp_str      [MAXARGSTRING];   /* temp messages */
1099 
1100 
1101 /* read in some of the file from the input buffer */
1102 
1103   i = get_data(out_str,BUFFSIZE,data_ptr);
1104   out_str[i]=0;
1105   out_len = 0;
1106 
1107 /* if there are more characters then call receive data */
1108 
1109   if (i>0)
1110   {
1111     out_len = i;
1112     executeb(REC_DATA,out_str,out_len,mcb_ptr);
1113     return;
1114   }
1115 
1116 /* if there are no more characters then call receive eof */
1117 
1118   else if (i==0)
1119     executeb(REC_EOF,out_str,out_len,mcb_ptr);
1120 
1121 /* if there was an error reading from the buffer call remote read error */
1122 
1123   else
1124   {
1125     sprintf (temp_str, "%s reading %s.", getsyserr (errno), data_ptr->source_file);
1126     out_str[0]=0;
1127     out_len = 0;
1128     out_len = addtoken (out_str, out_len, temp_str, 0);
1129     executeb (READ_ERROR, out_str, out_len, mcb_ptr);
1130   }
1131 
1132   data_ptr->source_file[0]=0;
1133 }
1134 /* ^L */
1135 /******************************************************************
1136 
1137      REQUEST DISCONNECT
1138 
1139      PARAMETERS: DATA_PTR   - pointer to BFT data structure (input)
1140                  SENDER     - major capability number of the calling routine (input)
1141 
1142      INFO EXTRACTED FROM ARGLIST: - none.
1143 
1144      FUNCTION:   Shuts BFT down.
1145 
1146 ********************************************************************/
1147 
1148 disconnect_request (mcb_ptr,sender)
1149 
1150 mcb  *mcb_ptr;                               /* BFT's MOWSE Control Block */
1151 int  sender;                                 /* Who sent this message */
1152 {
1153   disresp (WSACCEPT, sender, mcb_ptr);
1154   destinst (&mcb_ptr);
1155 }
1156 /* ^L */
1157 /******************************************************************
1158 
1159      RESPONSE DISCONNECT
1160 
1161      PARAMETERS: MCB_PTR    - pointer to the mowse control block (input)
1162 
1163      INFO EXTRACTED FROM ARGLIST: - none.
1164 
1165      FUNCTION:   Shuts BFT down.
1166 
1167 ********************************************************************/
1168 
1169 disconnect_response (mcb_ptr)
1170 
1171 mcb  *mcb_ptr;                                /* MOWSE Control block */
1172 {
1173   destinst(&mcb_ptr);
1174 }
1175 /* ^L */
1176 /******************************************************************
1177 
1178      EXECUTE COMMAND REPLY
1179 
1180      PARAMETERS: NONE.
1181 
1182      INFO EXTRACTED FROM ARGLIST: NONE
1183 
1184      FUNCTION:   Handler for the execute command reply. Currently
1185                  ignored.
1186 
1187 ********************************************************************/
1188 
1189 execute_command_reply()
1190 {
1191   return;
1192 }
1193 /* ^L */
1194 /*********************************************************************
1195 
1196      INTERNAL FUNCTIONS
1197 
1198 **********************************************************************/
1199 /* ^L */
1200 /*********************************************************************
1201 
1202      GET_DATA
1203 
1204      PARAMETERS: BUFFER     - Pointer to a character string (input)
1205                  LENGTH     - The number of bytes to try to read in (input)
1206                  DATA_PTR   - pointer to BFT data structure (input)
1207 
1208      FUNCTION:   Tries to read in "length" bytes from the file into
1209                  buffer and returns the actual number of bytes read
1210 
1211      WARNINGS:   If a file is opened as ASCII, then the ^Z character
1212                  indicates to read an EOF.  If there are more characters
1213                  after the ^Z, then they will NOT be transferred.
1214 
1215 **********************************************************************/
1216 
1217 int get_data (buffer, length, data_ptr)
1218 
1219 int length;                           /* the number of bytes to try to read in */
1220 char *buffer;                         /* pointer to a character string */
1221 bft_data_ptr data_ptr;                /* pointer to BFT data structure */
1222 {
1223 int fp_source;                        /* file descriptor to source file */
1224 int status;                           /* error code returned from reads */
1225 int i;                                /* temporary variable*/
1226 int open_mode;                        /* Opening mode of file */
1227 long file_pos;
1228 
1229 
1230 /* if the buffer is empty then read a chunk */
1231 
1232    if (data_ptr->inbuffpos == 0)
1233    {
1234      open_mode = O_RDONLY;
1235      if (data_ptr->source_flags & BFT_BINARY)
1236        open_mode |= O_RAW;
1237      fp_source = open (data_ptr->source_file, open_mode);
1238 
1239 /* if the source file cant be opened return an error */
1240 
1241      if (fp_source == -1)
1242        return (-1);
1243 
1244 /* seek to the correct spot in the file */
1245 
1246     file_pos = lseek (fp_source, data_ptr->inpos, SEEK_START);
1247     if (file_pos == -1L)
1248     {
1249       close (fp_source);
1250       return (-1);
1251     }
1252 
1253 /* if the read fails give an error message */
1254 
1255     status = read (fp_source, data_ptr->inbuffer, DISKBUFF);
1256     if (status < 1)
1257     {
1258       close (fp_source);
1259       return (status);
1260     }
1261 
1262 /* set pointers to correct places and close files */
1263 
1264     data_ptr->inpos = lseek (fp_source, 0L, SEEK_CURRENT);
1265     data_ptr->inbufflen = status;
1266     close (fp_source);
1267   }
1268 
1269 /* determine actual length of the buffer that will be returned */
1270 
1271   if ((data_ptr->inbuffpos + length) > data_ptr->inbufflen)
1272     length = data_ptr->inbufflen - data_ptr->inbuffpos;
1273 
1274 /* copy portion of the file from the input buffer to the arg */
1275 
1276   for (i=0;i<length;i++)
1277     buffer[i] = data_ptr->inbuffer[i+data_ptr->inbuffpos];
1278 
1279 /* set input buffer pointer to point to next portion of the file */
1280 
1281   if ((data_ptr->inbuffpos + length) == data_ptr->inbufflen)
1282     data_ptr->inbuffpos = 0;
1283   else
1284     data_ptr->inbuffpos = data_ptr->inbuffpos + length;
1285 
1286   return (length);
1287 }
1288 /* ^L */
1289 /********************************************************************
1290 
1291      PUT_DATA
1292 
1293      PARAMETERS: BUFFER - Pointer to a character string (input)
1294                  LENGTH - The number of bytes to try to write out (input)
1295                  DATA_PTR   - pointer to BFT data structure (input)
1296 
1297      FUNCTION:   Tries to write out length bytes from the buffer into
1298                  the file and returns the actual number of bytes
1299                  written.
1300 
1301 **********************************************************************/
1302 
1303 put_data (buffer, length, data_ptr)
1304 
1305 int length;                           /* the number of bytes to try to write out */
1306 char *buffer;                         /* pointer to a character string */
1307 bft_data_ptr data_ptr;                /* pointer to BFT data structure */
1308 {
1309 int fp_dest;                          /* file descriptor to source file */
1310 int status;                           /* error code returned from reads */
1311 int i;                                /* temporary variable */
1312 char temp_str[100];
1313 int  open_mode;                       /* Opening modes */
1314 long file_pos;
1315 
1316 
1317 /* if the incoming data will overflow the buffer then write the buffer out */
1318 
1319   if ((data_ptr->outbuffpos+length ) > DISKBUFF)
1320   {
1321     open_mode = O_RDWR;
1322     if (data_ptr->destination_flags & BFT_BINARY)
1323       open_mode |= O_RAW;
1324     fp_dest = open (data_ptr->destination_file, open_mode);
1325     if (fp_dest == -1)
1326       return (-1);
1327 
1328 /* seek to the write position in the file */
1329 
1330     if (data_ptr->outpos == 0)
1331       file_pos = lseek (fp_dest, 0L, SEEK_EOF);
1332     else
1333     {
1334       file_pos = lseek (fp_dest, data_ptr->outpos, SEEK_START);
1335       data_ptr->outpos = 0;
1336     }
1337     if (file_pos == -1L)
1338     {
1339       close (fp_dest);
1340       return (-1);
1341     }
1342 
1343 /* if the write was unsuccessful then return with an error code */
1344 
1345     status = write (fp_dest, data_ptr->outbuffer, data_ptr->outbuffpos);
1346     if (status < 1)
1347     {
1348       close (fp_dest);
1349       return (status);
1350     }
1351 
1352     data_ptr->outbuffpos = 0;
1353     close (fp_dest);
1354   }
1355 
1356 
1357 /* copy data passed to put_data into the output buffer */
1358 
1359   for (i=0;i<length;i++)
1360     data_ptr->outbuffer[i+data_ptr->outbuffpos] = buffer[i];
1361 
1362   data_ptr->outbuffpos += length;
1363 
1364   return (length);
1365 }
1366 /* ^L */
1367 /********************************************************************
1368 
1369      EXECUTEB
1370 
1371      PARAMETERS: MINUM      - Minor capability number to execute (input)
1372                  ARG_STRING - The arguments passed to the minor (input)
1373                  ARG_LEN    - The length of the argument string (input)
1374                  MCB_PTR    - A pointer to the mowse control block (input)
1375 
1376      FUNCTION:   Executes the specified minor capability on the
1377                  specified system with the specified arguments.
1378 
1379 **********************************************************************/
1380 
1381 executeb (minum, arg_string, arg_len, mcb_ptr)
1382 
1383 int minum;                   /* minor capability number to call */
1384 int arg_len;                 /* length of the arg string */
1385 mcb *mcb_ptr;                /* pointer to the mowse control block */
1386 char *arg_string;            /* string containing the arguments */
1387 {
1388 int majnum;
1389 int code;
1390 
1391 
1392   majnum = 0;
1393   if ((code = findnumb ("bft_main_", WSREMOTE, &majnum)) != 0)
1394   {
1395     putbgmes (mcb_ptr, code, "BFT", "Finding Multics BFT capability.");
1396     return(0);
1397   }
1398   else
1399      return (execap (majnum, minum, arg_string, arg_len, mcb_ptr));
1400 }
1401 /* ^L */
1402 /********************************************************************
1403 
1404      EXPAND_PATH
1405 
1406      PARAMETERS:
1407           PATH      - path to breakdown.   (input)
1408           DIRNAME   - directory component. (output)
1409           ENTRYNAME - entry component.     (output)
1410 
1411      FUNCTION:   Initiate a traversal of a directory for pattern matching
1412                  on filenames.
1413 
1414 ********************************************************************/
1415 
1416 expand_path (path, dirname, entryname)
1417 
1418 char *path;                            /* Path to expand */
1419 char *dirname;                         /* Directory component */
1420 char *entryname;                       /* Entryname component */
1421 {
1422 int  i;
1423 int  indx;                             /* Length of directory component */
1424 char token[MU_ENTRYNAME_SIZE];         /* Entryname component component */
1425 char *sp;                              /* String pointer */
1426 
1427 
1428    for (i = 0, indx = 0; path[i] != '\0'; i++)
1429    {
1430       if (path[i] == '\\')
1431          indx = i;
1432    }
1433 
1434 /* Dirname */
1435 
1436    indx = (indx <= PATHNAMESIZE) ? indx : PATHNAMESIZE;
1437    strncpy (dirname, path, indx);
1438 
1439 /* First component of entryname XXX.xxx */
1440 
1441    sp = &(path[indx+1]);
1442    sp = stptok (sp, token, sizeof (token), ".");
1443    strncpy (entryname, token, 8);
1444 
1445 /* Another component? Then copy in the break, and skip the break char */
1446 
1447    if (*sp == '.')
1448    {
1449       sp += 1;
1450       strcat  (entryname, ".");
1451    }
1452 
1453 /* Second component of entryname xxx.XXX */
1454 
1455    sp = stptok (sp, token, sizeof (token), ".");
1456    if (strlen (token) > 0)
1457       strncat (entryname, token, 3);
1458 }
1459 /* ^L */
1460 /********************************************************************
1461 
1462      FINDFIRST
1463 
1464      PARAMETERS: STR - path spec to initiate traversal
1465 
1466      FUNCTION:   Initiate a traversal of a directory for pattern matching
1467                  on filenames.
1468 
1469 ********************************************************************/
1470 
1471 findfirst(str)
1472 
1473 short str;
1474 {
1475 union REGS sysregs;
1476 int code;
1477 
1478    sysregs.h.ah = DOS_STAR_FIRST;
1479    sysregs.x.cx = 0;
1480    sysregs.x.dx = str;
1481    code = intdos (&sysregs,&sysregs);
1482    code &= 01;
1483    return (!code);
1484 }
1485 /* ^L */
1486 /********************************************************************
1487 
1488      FINDNEXT
1489 
1490      FUNCTION:   Continue on traversal of file matching.
1491 
1492 ********************************************************************/
1493 
1494 findnext()
1495 {
1496 union REGS sysregs;
1497 int code;
1498 
1499     sysregs.h.ah = DOS_STAR_NEXT;
1500     code = intdos (&sysregs,&sysregs);
1501     code &= 01;
1502     return (!code);
1503 }
1504 /* ^L */
1505 /********************************************************************
1506 
1507      SET_DTA
1508 
1509      ARGUMENTS: OFFSET - Address of dta structure.
1510 
1511      FUNCTION:  Set the DTA address to mine so I can reference it.
1512 
1513 ********************************************************************/
1514 
1515 set_dta (offset)
1516 
1517 short offset;                          /* DTA structure */
1518 {
1519 union REGS sysregs;
1520 
1521    sysregs.h.ah = DOS_SET_DTA;
1522    sysregs.x.dx = offset;
1523    intdos (&sysregs,&sysregs);
1524 }