Logo Search packages:      
Sourcecode: cbmlink version File versions  Download package

int main ( int  argc,
char **  argv 
)

The main function

Parameters:
argc argument count
argv argument vector
Returns:
0 if successful

end-of-data pointer for strtoul calls

Definition at line 770 of file cbmlink.c.

References B128, B256, bank, hostinfo::basic, buffer, cbmname(), device, drive_image_read(), drive_image_write(), drive_memory_load(), drive_memory_save(), hostinfo::driver, establish(), hostinfo::host, interleave, jump(), jump_cart(), load_file(), qdisk_format(), qdisk_install(), qdisk_read(), qdisk_remove(), qdisk_write(), rdfile(), rdfile_directory(), rdfile_install(), rdfile_remove(), resolve_addr(), run(), save_file(), secondary, sig(), terminate(), VERSION, wrfile(), wrfile_install(), and wrfile_remove().

{
  char** param;

  atexit (terminate);
#ifndef NO_SIGNAL
  signal (SIGINT, sig);
  signal (SIGTERM, sig);
#endif /* NO_SIGNAL */

  /* process the command-line parameters */
  for (param = argv; ++param < &argv[argc]; ) {
    /** end-of-data pointer for strtoul calls */
    char* endp;
    if (**param != '-')
      goto Unrecognized;

    switch ((*param)[1]) {
    case 'b':
      if ((*param)[2])
      goto Unrecognized;
      if (param + 1 >= &argv[argc]) {
      Missing:
      fprintf (stderr, "%s: argument missing\n", *param);
      goto Usage;
      }
      bank = strtoul (*++param, &endp, 0);
      if (!*param || *endp || bank > 255) {
      fprintf (stderr, "-b %s: memory bank out of range\n", *param);
      return 1;
      }
      break;
    case 'c':
      if ((*param)[2])
      goto Unrecognized;
      if (param + 2 >= &argv[argc])
      goto Missing;
      if (hostinfo)
      terminate ();
      if (!(hostinfo = establish (param[1], param[2], &comm)))
      return 2;
      if (!bank && (hostinfo->host == B128 || hostinfo->host == B256))
      bank = 1; /* the default bank is 1 for the CBM 600/700 series */
      param += 2;
      fputs ("cbmlink: Commodore ", stderr);
      fputs (cbmname (hostinfo->host), stderr);
      fputs (" detected.\n", stderr);
      fprintf (stderr,
             "cbmlink: Driver address %#04x, BASIC start address %#04x.\n",
             hostinfo->driver, hostinfo->basic);

      break;
    case 'l':
      if (param + 1 >= &argv[argc])
      goto Missing;
      if (!hostinfo)
      goto Disconnected;
      switch (load_file (*param, param[1])) {
      case 0:
      break;
      case -1:
      goto Unrecognized;
      default:
      return 2;
      }
      param++;
      break;
    case 's':
      if (param + 1 >= &argv[argc])
      goto Missing;
      if (!hostinfo)
      goto Disconnected;
      switch (save_file (*param, param[1])) {
      case 0:
      break;
      case -1:
      goto Unrecognized;
      default:
      return 2;
      }
      param++;
      break;
    case 'r':
      if ((*param)[2])
      goto Unrecognized;
      if (!hostinfo) {
      Disconnected:
      fprintf (stderr, "%s: connection not established\n", *param);
      goto Usage;
      }
      if (run (comm))
      return 2;
      break;
    case 'j':
      switch ((*param)[2]) {
      case ',': /* jump to specified address */
      break;
      case 'c': /* jump to cartridge, specify restart address */
      if ((*param)[3] == ',')
        break;
      /* fall through */
      default:
      goto Unrecognized;
      }
      if (!hostinfo)
      goto Disconnected;
      else {
      unsigned addr;
      const char* addrspec = (*param)[2] == ','
        ? (*param) + 3
        : (*param) + 4;
      addr = resolve_addr (addrspec, &endp);
      if (*endp) {
        fprintf (stderr, "%s: invalid address\n", *param);
        return 1;
      }
      if (((*param)[2] == 'c') ? jump_cart (addr) : jump (comm, bank, addr))
        return 2;
      }
      break;
    case 'd':
      if ((*param)[2] != 's' && param + 1 >= &argv[argc])
      goto Missing;
      switch ((*param)[2]) {
      case 0: /* specify device number and secondary address */
      device = strtoul (param[1], &endp, 0);
      if (!param[1] || (*endp && *endp != ',') || device > 31) {
        fprintf (stderr, "-d %s: device number out of range\n", param[1]);
        return 1;
      }
      else if (*endp) {
        if (!*++endp || (secondary = strtol (endp + 1, &endp, 0)) < 0 ||
            secondary > 15) {
          fprintf (stderr, "-d %s: secondary address out of range\n",
                 param[1]);
          return 1;
        }
      }
      param++;
      continue;
      case 'm':
      switch ((*param)[3]) {
      default:
        goto Unrecognized;
      case 'l':
        if (!hostinfo)
          goto Disconnected;
        switch (drive_memory_load (*param, param[1])) {
        case 0:
          break;
        case -1:
          goto Unrecognized;
        default:
          return 2;
        }
      case 's':
      case 'c':
        if (!hostinfo)
          goto Disconnected;
        switch (drive_memory_save (*param, param[1])) {
        case 0:
          break;
        case -1:
          goto Unrecognized;
        default:
          return 2;
        }
      }
      param++;
      continue;
      case 'r':
      case 'w':
      if (!hostinfo)
        goto Disconnected;
      switch ((*param)[2] == 'r'
            ? drive_image_read (*param, param[1])
            : drive_image_write (*param, param[1])) {
      case 0:
        break;
      case -1:
        goto Unrecognized;
      default:
        return 2;
      }
      param++;
      continue;
      case 's':
      if ((*param)[3])
        goto Unrecognized;
      break;
      case 'c':
      case 'd':
      if ((*param)[3])
        goto Unrecognized;
      break;
      default:
      goto Unrecognized;
      }

      if (!hostinfo)
      goto Disconnected;

      if (rdfile_install (comm, hostinfo, device,
                    (*param)[2] == 'd' ? 0 : 15)) {
      fputs ("rdfile: installation failed\n", stderr);
      return 2;
      }

      switch ((*param)[2]) {
      case 's':
      if (rdfile (comm, "", stdout, buffer)) {
      rdfile_fail:
        fputs ("rdfile: rdfile failed\n", stderr);
        goto rdfile_failed;
      }
      putchar ('\n');
      break;
      case 'c':
      if (rdfile (comm, param[1], stdout, buffer))
        goto rdfile_fail;
      putchar ('\n');
      param++;
      break;
      case 'd':
      if (rdfile_directory (comm, param[1], stdout, buffer)) {
        fputs ("rdfile: directory failed\n", stderr);
      rdfile_failed:
        if (rdfile_remove (comm)) {
          fputs ("rdfile: removal failed\n", stderr);
          return 2;
        }
        return 1;
      }
      param++;
      break;
      }

    rdfile_remove:
      if (rdfile_remove (comm)) {
      fputs ("rdfile: removal failed\n", stderr);
      return 2;
      }
      break;
    case 'f':
      switch ((*param)[2]) {
      case 'r':
      case 'w':
      if (!(*param)[3])
        break;
      default:
      goto Unrecognized;
      }

      if (param + 1 >= &argv[argc])
      goto Missing;

      if (!hostinfo)
      goto Disconnected;

      switch ((*param)[2]) {
      case 'r':
      if (rdfile_install (comm, hostinfo, device,
                      secondary == -1 ? 0 : secondary)) {
        fputs ("rdfile: installation failed\n", stderr);
        return 2;
      }

      while (++param < &argv[argc]) {
        FILE* f = fopen (*param, "wb");
        if (!f) {
          fputs (*param, stderr), perror (": fopen");
          goto rdfile_failed;
        }
        else if (rdfile (comm, *param, f, buffer)) {
          fclose (f);
          goto rdfile_fail;
        }
        fclose (f);
      }
      goto rdfile_remove;
      case 'w':
      if (wrfile_install (comm, hostinfo, device,
                      secondary == -1 ? 1 : secondary)) {
        fputs ("wrfile: installation failed\n", stderr);
        return 2;
      }

      while (++param < &argv[argc]) {
        FILE* f = fopen (*param, "rb");
        if (!f) {
          fputs (*param, stderr), perror (": fopen");
        wrfile_failed:
          if (wrfile_remove (comm)) {
            fputs ("wrfile: removal failed\n", stderr);
            return 2;
          }
          return 1;
        }
        else if (wrfile (comm, *param, f, buffer)) {
          fclose (f);
          fputs ("wrfile: wrfile failed\n", stderr);
          goto wrfile_failed;
        }
        fclose (f);
      }

      if (wrfile_remove (comm)) {
        fputs ("wrfile: removal failed\n", stderr);
        return 2;
      }

      return 0;
      }

      break;
    case 'q':
      switch ((*param)[2]) {
      default:
      goto Unrecognized;
      case 'f':
      case 'r':
      if ((*param)[3])
        goto Unrecognized;
      break;
      case 'w':
      switch ((*param)[3]) {
      default:
        goto Unrecognized;
      case 0:
        interleave = 5;
        break;
      case ',':
        interleave = strtoul ((*param) + 4, &endp, 0);
        if (*endp || interleave > 999) {
          fputs (*param, stderr);
          fputs (": invalid interleave factor\n", stderr);
          goto Unrecognized;
        }
        break;
      }
      break;
      }
      if (param + 1 >= &argv[argc])
      goto Missing;
      if (!hostinfo)
      goto Disconnected;

      if (rdfile_install (comm, hostinfo, device, 15)) {
      fputs (*param, stderr);
      fputs (": rdfile installation failed\n", stderr);
      return 2;
      }
      else if ((*param)[2] == 'f') {
      /* quick format */
      unsigned i;
      char name[16], id1, id2;
      /* fill the name with shifted spaces */
      memset (name, 0xa0, sizeof name);
      for (i = 0; param[1][i] && param[1][i] != ','; i++);
      memcpy (name, param[1], i < 16 ? i : 16);
      if ((id2 = id1 = param[1][i] == ',' ? param[1][++i] : 0))
        id2 = param[1][++i];
      if (qdisk_format (comm, stdout, name, id1, id2)) {
        fputs ("-qf: communication failure\n", stderr);
        goto rdfile_failed;
      }
      putchar ('\n');
      param++;
      goto rdfile_remove;
      }
      else {
      FILE* f = fopen (param[1], (*param)[2] == 'r' ? "wb" : "rb");
      if (!f) {
        fputs (param[1], stderr), perror (": fopen");
        goto rdfile_failed;
      }
      if (qdisk_install (comm, hostinfo)) {
        fclose (f);
        goto rdfile_failed;
      }
      if ((*param)[2] == 'r'
          ? qdisk_read (comm, f, buffer)
          : qdisk_write (comm, f, interleave, buffer)) {
        fclose (f);
        if (qdisk_remove (comm))
          fputs ("qdisk: removal failed\n", stderr);
        return 2;
      }
      if (qdisk_remove (comm)) {
        fputs ("qdisk: removal failed\n", stderr);
        return 2;
      }
      fclose (f);
      param++;
      }
      break;

    case '?':
    case 'h':
      if ((*param)[2])
      goto Unrecognized;
      fputs ("CBMLINK " VERSION ": data communications and remote management "
           "for Commodore computers.\n"
           "Options:\n"
           "-h\t"
           "Get this help message\n"
           "-c protocol device\t"
           "Specify the communication protocol and interface\n"
           "-b bank\t"
           "Specify the memory bank (default=1 for 600/700, 0 for others)\n"
           "-l[p] file.prg\t"
           "Load a program at its specified absolute address\n"
           "-l[p]b file.prg\t"
           "Load a program, relocated to the start of BASIC\n"
           "-l[p]r,address file.prg\t"
           "Load and relocate a program to the specified address\n"
           "-l[p]o,address file.bin\t"
           "Load a binary file to the specified address\n"
           "-s,address,address file.prg\t"
           "Save memory area to a program file\n"
           "-so,address,address file.bin\t"
           "Save memory area to a binary file\n"
           "-r\t"
           "Disable the server and perform a RUN command\n"
           "-j,address\t"
           "Disable the server and jump to the specified address\n"
           "-jc,restart_address\t"
           "Launch a VIC-20 cartridge\n"
           "-d drive[,secondary]\t"
           "Specify the device number and secondary address (default=8)\n"
           "-dr[0|1][,interleave] file.d64\t"
           "Read a disk in unit 0 or 1 to an image file\n"
           "-dw[0|1][,interleave] file.d64\t"
           "Write an image file to a disk in unit 0 or 1\n"
           "-dmc,address,address file.prg\t"
           "Save drive controller memory area to a program file\n"
           "-dmco,address,address file.bin\t"
           "Save drive controller memory area to a binary file\n"
           "-dml file.prg\t"
           "Load a program to drive memory\n"
           "-dmlr,address file.prg\t"
           "Load a program to the specified address in drive memory\n"
           "-dmlo,address file.bin\t"
           "Load a binary file to the specified address in drive memory\n"
           "-dms,address,address file.prg\t"
           "Save drive memory area to a program file\n"
           "-dmso,address,address file.bin\t"
           "Save drive memory area to a binary file\n"
           "-dc command\t"
           "Execute a disk drive command\n"
           "-ds\t"
           "Query disk drive status\n"
           "-dd pattern\t"
           "Fetch the disk directory\n"
           "-fr file ...\t"
           "Read files from disk\n"
           "-fw file ...\t"
           "Write files to disk\n"
           "-qf name,id\t"
           "Quick format a 1541 disk\n"
           "-qr file.d64\t"
           "Quick read a 1541 disk\n"
           "-qw[,interleave] file.d64\t"
           "Quick write a 1541 disk\n"
           "\n"
           "Indirect addresses are prefixed with @, e.g. @0x2d or @45.\n",
           stderr);
      return 0;

    default:
    Unrecognized:
      fprintf (stderr, "cbmlink: unrecognized option `%s'\n", *param);
    Usage:
      fputs ("Type \"cbmlink -h\" to get help.\n", stderr);
      return 1;
    }
  }

  if (!hostinfo)
    goto Usage;

  return 0;
}


Generated by  Doxygen 1.6.0   Back to index