home *** CD-ROM | disk | FTP | other *** search
/ Lion Share / lionsharecd.iso / utils_mz / pfdisktc.zip / PFDISKAZ.C < prev    next >
C/C++ Source or Header  |  1992-04-15  |  18KB  |  606 lines

  1. /*
  2.  * pfdisk - Partition a Fixed DISK
  3.  *    by Gordon W. Ross, Jan. 1990
  4.  *
  5.  * See the file "pfdisk.doc" for user instructions.
  6.  *
  7.  * This program uses a simple, line-oriented interpreter,
  8.  * designed for both interactive and non-interactive use.
  9.  * To facilitate non-interactive use, the output from the
  10.  * 'L' (list partitions) command is carefully arranged so it
  11.  * can be used directly as command input.  Neat trick, eh?
  12.  */
  13.  
  14. char *versionString =
  15.   "# pfdisk version 1.2.1 by Gordon W. Ross  Aug. 1990\nModified by S. Lubkin  Oct. 1991\n";
  16.  
  17. /* These don't really matter.  The user is asked to set them. */
  18. #define DEFAULT_CYLS 306
  19. #define DEFAULT_HEADS 4
  20. #define DEFAULT_SECTORS 17
  21. #define PROMPT_STRING "pfdisk> "
  22.  
  23. #include <stdio.h>
  24. #include <string.h>
  25. #include <ctype.h>
  26. #include "sysdep.h"
  27. #include "syscodes.h"
  28.  
  29. typedef unsigned char uchar;
  30. typedef unsigned int uint;
  31. typedef unsigned long ulong;
  32.  
  33. struct part {    /* An entry in the partition table */
  34.   uchar    active;        /* active flag (0x80 or 0) */
  35.   uchar    b_head;        /* begin head */
  36.   uchar    b_sec;        /*      sector */
  37.   uchar    b_cyl;        /*     cylinder */
  38.   uchar    sysid;        /* system id (see sysid.c) */
  39.   uchar    e_head;        /* end  head */
  40.   uchar    e_sec;        /* end    sector */
  41.   uchar    e_cyl;        /* end    cylinder */
  42.   /* These two are just longs, but this way is machine independent. */
  43.   /* uchar    lsBeg[4];    /* logical sectors, beginning Saul */
  44.   ulong    lsBeg;    /* logical sectors, beginning Saul */
  45.   /* uchar    lsLen[4];    /* logical sectors, length Saul */
  46.   ulong    lsLen;    /* logical sectors, length Saul */
  47. };
  48.  
  49. #define LOC_PT        0x1BE
  50. #define LOC_NT        0x1AA /* Saul */
  51. /* #define LOC_NT        0x180 Saul */
  52. /* #define LOC_GWR        0x1A0 Saul */
  53. #define LOC_GWR        0x1A9 /* Saul */
  54. #define MAGIC_LOC    0x1FE
  55. #define MAGIC_0        0x55
  56. #define MAGIC_1        0xAA
  57. #define MAX_LINE    80
  58. #define NT_ENTRY_SIZE    5 /* Saul */
  59. /* Note:  Entry in "printf" command, should be manually changed, to
  60. "%-NT_ENTRY_SIZE.NT_ENTRY_SIZEs" Saul */
  61. /* And header printf line should have blanks adjusted Saul */
  62.  
  63. char s[22];   /* For holding error string */
  64. char    buffer[SECSIZE];    /* The boot block buffer */
  65. int    bufmod=0;        /* buffer modified... */
  66.         /* (zero means buffer is unmodified) */
  67. int    useNTable;        /* boot sector uses name table */
  68.  
  69. /* device parameters (force someone to set them!) */
  70. unsigned cyls = DEFAULT_CYLS;
  71. unsigned heads = DEFAULT_HEADS;
  72. unsigned sectors = DEFAULT_SECTORS;
  73.  
  74. char    *devname;        /* device name */
  75. char    cmdline[MAX_LINE];
  76. char    filename[80];        /* used by r/w commands */
  77. char    *prompt;        /* null if no tty input */
  78.  
  79. /* Some of these strings are used in more than one place.
  80.  * For consistency, I put a newline on all of them.
  81.  */
  82. char h_h[] = "? <enter>             : Help summary\n";
  83. char h_l[] = "L                     : List partition table\n";
  84. char h_1[] = "1 id first last [name]: set partition 1\n";
  85. char h_2[] = "2,3,4 ... (like 1)    : set respective partition\n";
  86. char h_a[] = "A n [m, ...]          : Activate partition(s) n [m, ...]\n";
  87. char h_g[] = "G cyls heads sectors  : set disk Geometry\n";
  88. char h_i[] = "I                     : list known ID numbers\n";
  89. char h_r[] = "R [optional-file]     : Read  device (or specified file)\n";
  90. char h_w[] = "W [optional-file]     : Write device (or specified file)\n";
  91. char h_q[] = "Q[!]                  : Quit (! means force)\n";
  92.  
  93. char * helpTable[] = {
  94. h_h, h_l, h_1, h_2, h_a, h_g, h_i, h_r, h_w, h_q,
  95. "# (All command letters have lower-case equivalents.)\n",
  96. (char *) 0 }; /* This MUST have a zero as the last element */
  97.  
  98. char *BadArg="Error: bad argument: %s\n";
  99. char *WarnNotSaved =
  100.     "Warning, modified partition table not saved.\n";
  101.  
  102. help()
  103. {
  104.   char ** p;
  105.   for (p = helpTable; *p; p++)
  106.     printf(*p);
  107. }
  108.  
  109. /* forward declarations */
  110. void    checkValidity();
  111. char *    setPartition();
  112. char *    makeActive();
  113. char *    setGeometry();
  114. ulong    chs2long();
  115. char *    nameID();
  116. int    printIDs();
  117.  
  118. main(argc,argv)
  119. int    argc;
  120. char    *argv[];
  121. {
  122.   char    *cmdp;        /* points to command word */
  123.   char    *argp;        /* points to command args */
  124.  
  125.   /* check command line args (device name) */
  126.   if (argc != 2) {
  127.     usage(argv[0]);    /* See s-sysname.c */
  128.     exit(1);
  129.   }
  130.   devname = argv[1];
  131.  
  132.   /* Should we prompt? */
  133.   prompt = (isatty(fileno(stdin))) ? PROMPT_STRING : (char *) 0;
  134.  
  135.   /* Print version name. */
  136.   fputs(versionString, stderr);
  137.  
  138.   /* get disk parameters */
  139.   getGeometry(devname,&cyls,&heads,§ors);
  140.  
  141.   /* Get the boot block. */
  142.   if (getBBlk(devname, buffer) < 0)
  143.     fprintf(stderr,"%s: read failed\n", devname);
  144.   checkValidity();
  145.  
  146.   if (prompt) fprintf(stderr,"For help, enter: '?'\n");
  147.  
  148.  
  149.   /* Read and process commands a line at a time. */
  150.   while (1) {
  151.     if (prompt) fputs(prompt,stdout);
  152.     if (! fgets(cmdline, MAX_LINE, stdin)) break;
  153.  
  154.     /* Find beginning of command word */
  155.     cmdp = cmdline;
  156.     while (isspace(*cmdp)) cmdp++;
  157.  
  158.     /* find beginning of args */
  159.     argp = cmdp;
  160.     while (*argp && !isspace(*argp)) argp++;
  161.     while (isspace(*argp) || *argp=='=') argp++;
  162.  
  163.     switch (*cmdp) {
  164.  
  165.     case '\0':        /* blank line */
  166.     case '#':        /* line comment */
  167.       break;
  168.  
  169.     case '?': case 'h': case 'H':
  170.       help();
  171.       break;
  172.  
  173.     case '1':    /* set partition entry */
  174.     case '2': case '3': case '4':
  175.       argp = setPartition(cmdp, argp);
  176.       if (argp) {    /* arg list error */
  177.     fprintf(stderr,BadArg,argp);
  178.     fprintf(stderr,h_1);
  179.     fprintf(stderr,h_2);
  180.     break;
  181.       }
  182.       bufmod = 1;
  183.       break;
  184.  
  185.     case 'a': case 'A':    /* activate partition */
  186.       argp = makeActive(argp);
  187.       if (argp) {
  188.     fprintf(stderr,BadArg,argp);
  189.     fprintf(stderr,h_a);
  190.     break;
  191.       }
  192.       bufmod = 1;
  193.       break;
  194.  
  195.     case 'g': case 'G':    /* set disk parameters (Geometry) */
  196.       argp = setGeometry(argp);
  197.       if (argp) {    /* arg list error */
  198.     fprintf(stderr,BadArg,argp);
  199.     fprintf(stderr,h_g);
  200.       }
  201.       break;
  202.  
  203.     case 'i': case 'I':    /* List known ID numbers */
  204.       printIDs();
  205.       break;
  206.  
  207.     case 'l': case 'L':    /* List the partition table */
  208.       listPTable();
  209.       break;
  210.  
  211.     case 'q': case 'Q':    /* Quit */
  212.       if (bufmod && (cmdp[1]  != '!')) {
  213.     fprintf(stderr,"\007%s%s\n", WarnNotSaved,
  214.         "Use 'wq' or 'q!' (enter ? for help).");
  215.     break;
  216.       }
  217.       exit(0);
  218.       /*NOTREACHED*/
  219.  
  220.     case 'r': case 'R':    /* read from device or file */
  221.       if (sscanf(argp,"%80s",filename) == 1) {
  222.     /* Arg specified, read from filename */
  223.     if (getFile(filename, buffer, SECSIZE) < 0)
  224.       fprintf(stderr,"%s: read failed\n", filename);
  225.     bufmod = 1;
  226.       } else {
  227.     /* No arg, use device. */
  228.     if (getBBlk(devname, buffer) < 0)
  229.       fprintf(stderr,"%s: read failed\n", devname);
  230.     bufmod = 0;
  231.       }
  232.       checkValidity();
  233.       break;
  234.  
  235.     case 'w': case 'W':    /* Write to file or device */
  236.       if (sscanf(argp,"%80s",filename) == 1) {
  237.     /* Arg specified, write to filename */
  238.     if (putFile(filename, buffer, SECSIZE) < 0)
  239.       fprintf(stderr, "%s: write failed\n", filename);
  240.       } else {  /* No arg, use device. */
  241.     if (putBBlk(devname, buffer) < 0)
  242.       fprintf(stderr, "%s: write failed\n", devname);
  243.     bufmod = 0;
  244.       }
  245.       if (cmdp[1] == 'q' || cmdp[1] == 'Q') exit(0);
  246.       break;
  247.  
  248.     default:
  249.       fprintf(stderr,"'%c': unrecognized.  Enter '?' for help.\n", *cmdp);
  250.       break;
  251.  
  252.     } /* switch */
  253.   } /* while */
  254.   if (bufmod) fprintf(stderr, WarnNotSaved);
  255.   exit(0);
  256. } /* main */
  257.  
  258.  
  259. /* Check for valid boot block (magic number in last two bytes).
  260.  * Also, check for presence of partition name table.
  261.  */
  262. void checkValidity()
  263. {
  264.   /* Check the magic number. */
  265.   if ((buffer[MAGIC_LOC] & 0xFF) != MAGIC_0 ||
  266.       (buffer[MAGIC_LOC+1] & 0xFF) != MAGIC_1 ) {
  267.     /* The boot sector is not valid -- Fix it. */
  268.     buffer[MAGIC_LOC] = MAGIC_0;
  269.     buffer[MAGIC_LOC+1] = MAGIC_1;
  270.     bufmod = 1;
  271.     fprintf(stderr,
  272. "\n\tWarning:  The boot sector has an invalid magic number.\n\
  273. \tThe magic number has been fixed, but the other contents\n\
  274. \tare probably garbage.  Initialize using the command:\n\
  275. \t\tR boot-program-file    (i.e. bootmenu.bin)\n\
  276. \tthen set each partition entry if necessary.\n");
  277.   }
  278.  
  279.   /* Does it use a name table (for a boot menu)?
  280.    * My boot program does, and can be identified by
  281.    * finding my name in a particular (unused) area.
  282.    */
  283.   useNTable = ( buffer[LOC_GWR] == (char)0x3A ); /* Saul */
  284.   /* useNTable = !strcmp(&buffer[LOC_GWR], "Gordon W. Ross"); Saul */
  285.  
  286. }
  287.  
  288. char * setPartition(cmdp,argp)    /* return string on error */
  289. char    *cmdp,*argp;
  290. {
  291.   struct part *pp;    /* partition entry */
  292.   char *    np;        /* name table pointer */
  293.   char          tmpname[20];
  294.   char *    newname = tmpname;    /* name field */
  295.   int    index;        /* partition index (0..3) */
  296.   uint    id;        /* ID code (see syscodes.c) */
  297.   uint    first,last;    /* user supplied cylinders */
  298.   uint    c,h,s;        /* working cyl,head,sect, */
  299.   int    i;        /* returned by sscanf */
  300.   ulong    lsbeg, lslen;    /* logical begin, length */
  301.  
  302.   /* Value check the index */
  303.   index = *cmdp - '1';
  304.   if (index < 0 || index > 3)
  305.     return("index");
  306.   pp = (struct part *) &buffer[LOC_PT + index * 16];
  307.   np = &buffer[LOC_NT + index * NT_ENTRY_SIZE]; /* Saul */
  308.   /* np = &buffer[LOC_NT + index * 8]; Saul */
  309.  
  310.   /* Read System ID */
  311.   if ((i=sscanf(argp,"%d%d%d%s", &id, &first, &last, newname)) < 1)
  312.     return("id");
  313.  
  314.   /* If ID==0, just clear out the entry and return. */
  315.   if (id == 0) {
  316.     strncpy( (char *) pp, "", 16);
  317.     if (useNTable) strncpy( np, "", NT_ENTRY_SIZE); /* Saul */
  318.     /* if (useNTable) strncpy( np, "", 8); Saul */
  319.     return((char *)0);
  320.   }
  321.  
  322.   /* Read first and last cylinder */
  323.   if (i < 3)
  324.     return("first last (missing)");
  325.  
  326.   /* Reasonable start,end cylinder numbers? */
  327.   if (first > last)    return("first > last");
  328.   if (first > 1023)    return("first > 1023");
  329.   if (last >= cyls)    return("last >= cyls");
  330.  
  331.   /* Get (optional) system name. */
  332.   if (i == 3) {    /* no name given, use default */
  333.     newname = nameID(id);
  334.   }
  335.     else useNTable = 1;
  336.  
  337.   /* Set the ID and name. */
  338.   pp->sysid = id;
  339.   if (useNTable) {
  340.     strncpy(np, newname, NT_ENTRY_SIZE); /* Saul */
  341.     /* strncpy(np, newname, 8); Saul */
  342.     /* strcpy(&buffer[LOC_GWR], "Gordon W. Ross"); Saul */
  343.     buffer[LOC_GWR] = (char)0x3A; /* Saul */
  344.   }
  345.  
  346.   /* set beginning c,h,s */
  347.   c = first;
  348.   /* if c == 0, head == 1 (reserve track 0) */
  349.   h = (first) ? 0 : 1;
  350.   s = 1;
  351.   pp->b_cyl = c & 0xFF;
  352.   pp->b_head = h;
  353.   pp->b_sec = s | ((c >> 2) & 0xC0);
  354.   /* Set the logical sector begin field */
  355.   lsbeg = lslen = chs2long(c,h,s); /* using lslen as temp. */
  356.   /* pp->lsBeg[0] = lslen & 0xff; lslen >>= 8;
  357.   pp->lsBeg[1] = lslen & 0xff; lslen >>= 8;
  358.   pp->lsBeg[2] = lslen & 0xff; lslen >>= 8;
  359.   pp->lsBeg[3] = lslen & 0xff; lslen >>= 8; Saul */
  360.   pp->lsBeg = lslen; /* Saul */
  361.  
  362.   /* set ending c,h,s (last may be larger than 1023) */
  363.   c = (last>1023) ? 1023 : last; /* limit c to 1023 */
  364.   h = heads - 1; s = sectors;
  365.   pp->e_cyl = c & 0xFF;
  366.   pp->e_head = h;
  367.   pp->e_sec = s | ((c >> 2) & 0xC0);
  368.   /* Set the logical sector length field (using REAL end cylinder) */
  369.   lslen = chs2long(last,h,s) + 1 - lsbeg;
  370.   /* pp->lsLen[0] = lslen & 0xff; lslen >>= 8;
  371.   pp->lsLen[1] = lslen & 0xff; lslen >>= 8;
  372.   pp->lsLen[2] = lslen & 0xff; lslen >>= 8;
  373.   pp->lsLen[3] = lslen & 0xff; lslen >>= 8; Saul */
  374.   pp->lsLen = lslen; /* Saul */
  375.  
  376.   return((char *)0);    /* success */
  377. } /* setPartition() */
  378.  
  379. char * makeActive(argp)    /* return error string or zero */
  380. char    *argp;
  381. {
  382.   struct part *pp;    /* partition entry */
  383.   int    i,act1,act2,act3,act4,act5;        /* which one becomes active */
  384.  
  385.   act1=0;
  386.   act2=0;
  387.   act3=0;
  388.   act4=0;
  389.   if ((i=sscanf(argp,"%d%d%d%d%d", &act1, &act2, &act3, &act4, &act5)) < 1)
  390.     return("missing partition number");
  391.   if ( i > 4)
  392.     return("at most four partition numbers");
  393.   act1--;            /* make it zero-origin */
  394.   act2--;            /* make it zero-origin */
  395.   act3--;            /* make it zero-origin */
  396.   act4--;            /* make it zero-origin */
  397.  
  398.   i=0; pp = (struct part *) &buffer[LOC_PT];
  399.   while (i<4) {
  400.     if (pp->sysid == 0 && (i == act1|| i == act2 || i == act3 || i == act4)) {
  401.          sprintf(s, "partition %d empty", i+1);
  402.          return(s);
  403.          }
  404.     i++; pp++;
  405.   }
  406.   i=0; pp -= 4;
  407.   while (i<4) {
  408.     if (i == act1|| i == act2 || i == act3 || i == act4)
  409.       pp->active = 0x80;
  410.     else
  411.       pp->active = 0;
  412.     i++; pp++;
  413.   }
  414.   return((char *)0);
  415. }
  416.  
  417. char * setGeometry(argp)    /* return string on error */
  418. char    *argp;
  419. {
  420.   int    c,h,s;
  421.  
  422.   if (sscanf(argp,"%d%d%d", &c, &h, &s) < 3)
  423.     return("(missing)");
  424.   if (c<1) return("cyls");
  425.   if (h<1) return("heads");
  426.   if (s<1) return("sectors");
  427.   cyls=c; heads=h; sectors=s;
  428.   return((char *)0);
  429. }
  430.  
  431. listPTable()        /* print out partition table */
  432. {
  433.   struct part * pp;    /* partition table entry */
  434.   char    *name;
  435.   int    i;        /* partition number */
  436.   /* int    numActive=0;    /* active partition [1-4], 0==none */
  437.   char Active[20]; /* active partitions [1-4], 0==none */
  438.   uint    pbc,pbh,pbs;    /* physical beginning  c,h,s */
  439.   uint    pec,peh,pes;    /* physical ending     c,h,s */
  440.   uint    lbc,lbh,lbs;    /* logical beginning   c,h,s */
  441.   uint    lec,leh,les;    /* logical ending      c,h,s */
  442.   ulong    lsbeg,lslen;    /* logical sectors: begin, length */
  443.  
  444.   strcpy(Active, "active:");
  445.   printf("# Partition table on device: %s\n", devname);
  446.   printf("geometry %d %d %d (cyls heads sectors)\n",
  447.      cyls, heads, sectors);
  448.   /* printf("#  ID  First(cyl)  Last(cyl)  Name     "); Saul */
  449.   printf("#  ID  First(cyl)  Last(cyl)  Name  "); /* Saul */
  450.   printf("# start, length (sectors)\n");
  451.  
  452.   for (i=0; i<4; i++) {
  453.     pp = (struct part *) &buffer[LOC_PT + i * 16];
  454.  
  455.     if (pp->active) {
  456.       char s[3];
  457.       sprintf(s, " %d", i+1);
  458.       strcat(Active,s);
  459.       if (pp->active != 0x80)
  460.           fprintf(stderr, "Warning:  Partition %d is active, with the illegal activity byte %d.\nCorrect with the \"A\" command.\n", i+1, pp->active);
  461.    /* if(numActive)
  462.     fprintf(stderr,"Error: multiple active partitions.\n");
  463.       else numActive = i+1; */
  464.     }
  465.  
  466.     /* physical beginning c,h,s */
  467.     pbc = pp->b_cyl & 0xff | (pp->b_sec << 2) & 0x300;
  468.     pbh = pp->b_head;
  469.     pbs = pp->b_sec & 0x3F;
  470.  
  471.     /* physical ending c,h,s */
  472.     pec = pp->e_cyl & 0xff | (pp->e_sec << 2) & 0x300;
  473.     peh = pp->e_head;
  474.     pes = pp->e_sec & 0x3F;
  475.  
  476.     /* compute logical beginning (c,h,s) */
  477.     /* lsbeg = ((((((pp->lsBeg[3] ) << 8 )
  478.         | pp->lsBeg[2] ) << 8 )
  479.         | pp->lsBeg[1] ) << 8 )
  480.         | pp->lsBeg[0] ; Saul */
  481.     lsbeg = pp->lsBeg; /* Saul */
  482.     long2chs(lsbeg, &lbc, &lbh, &lbs);
  483.     /* compute logical ending (c,h,s) */
  484.     /* lslen = ((((((pp->lsLen[3]) << 8 )
  485.         | pp->lsLen[2]) << 8 )
  486.         | pp->lsLen[1]) << 8 )
  487.         | pp->lsLen[0] ; Saul */
  488.     lslen = pp->lsLen; /* Saul*/
  489.     /* keep beginning <= end ... */
  490.     if (lslen > 0) long2chs(lsbeg+lslen-1, &lec, &leh, &les);
  491.     else       long2chs(lsbeg,       &lec, &leh, &les);
  492.  
  493.     if (useNTable)
  494.       name = &buffer[LOC_NT + i * NT_ENTRY_SIZE ]; /* Saul */
  495.       /* name = &buffer[LOC_NT + i * 8]; Saul */
  496.     else
  497.       name = nameID((uint) pp->sysid);
  498.  
  499.     /* show physical begin, logical end (works for cyl>1023) */
  500.     /*      #  ID  First(cyl)  Last(cyl)  Name... # ... */
  501.     /* printf("%d %3d   %4d       %4d       %-8.8s # %ld, %ld\n",  Saul */
  502.     printf("%d %3d   %4d       %4d       %-5.5s # %ld, %ld\n", /* Saul */
  503.        i+1, pp->sysid, pbc, lec, name, lsbeg, lslen );
  504.  
  505.     /* That's all, for an empty partition. */
  506.     if (pp->sysid == 0) continue;
  507.  
  508.     /*
  509.      * Now do some consistency checks...
  510.      */
  511.  
  512.     /* Same physical / logical beginning? */
  513.     if (pbc != lbc || pbh != lbh || pbs != lbs ) {
  514.       printf("# note: first(%d): ", i+1);
  515.       printf("phys=(%d,%d,%d) ",    pbc, pbh, pbs);
  516.       printf("logical=(%d,%d,%d)\n",lbc, lbh, lbs);
  517.     }
  518.     /* Same physical / logical ending? */
  519.     if (pec != lec || peh != leh || pes != les ) {
  520.       printf("# note:  last(%d): ", i+1);
  521.       printf("phys=(%d,%d,%d) ",    pec, peh, pes);
  522.       printf("logical=(%d,%d,%d)\n",lec, leh, les);
  523.     }
  524.  
  525.     /* Beginning on cylinder boundary? */
  526.     if (pbc == 0) { /* exception: start on head 1 */
  527.       if (pbh != 1 || pbs != 1) {
  528.     printf("# note: first(%i): ", i+1);
  529.     printf("phys=(%d,%d,%d) ", pbc, pbh, pbs);
  530.     printf("should be (%d,1,1)\n", pbc);
  531.       }
  532.     } else { /* not on cyl 0 */
  533.       if (pbh != 0 || pbs != 1) {
  534.     printf("# note: first(%i): ", i+1);
  535.     printf("phys=(%d,%d,%d) ", pbc, pbh, pbs);
  536.     printf("should be (%d,0,1)\n", pbc);
  537.       }
  538.     }
  539.  
  540.     /* Ending on cylinder boundary? */
  541.     if (peh != (heads-1) || pes != sectors) {
  542.       printf("# note: last(%i): ", i+1);
  543.       printf("phys=(%d,%d,%d) ", pec, peh, pes);
  544.       printf("should be (%d,%d,%d)\n",
  545.          pec, heads-1, sectors);
  546.     }
  547.  
  548.   } /* for */
  549.   if ( !Active[7] ) /* No active partitions */
  550.     strcat(Active, " 0 (none)");
  551.   strcat(Active, "\n");
  552.   printf(Active);
  553. /* printf("active: %d  %s\n", numActive,
  554.      (numActive) ? "" : "(none)"); */
  555. } /* listPTable() */
  556.  
  557. ulong chs2long(c,h,s)
  558. uint c,h,s;
  559. {
  560.   ulong    l;
  561.   if (s<1) s=1;
  562.   l  = c; l *= heads;
  563.   l += h; l *= sectors;
  564.   l += (s - 1);
  565.   return(l);
  566. }
  567.  
  568. long2chs(ls, c, h, s)    /* convert logical sec-num to c,h,s */
  569. ulong    ls;        /* Logical Sector number */
  570. uint    *c,*h,*s;    /* cyl, head, sector */
  571. {
  572.   int    spc = heads * sectors;
  573.   *c = ls / spc;
  574.   ls = ls % spc;
  575.   *h = ls / sectors;
  576.   *s = ls % sectors + 1;    /* sectors count from 1 */
  577. }
  578.  
  579. char * nameID(n)
  580. unsigned int n;
  581. {
  582.   struct intString *is;
  583.  
  584.   is = sysCodes;
  585.   while (is->i) {
  586.     if (is->i == n) return(is->s);
  587.     is++;
  588.   }
  589.   if (!n) return(is->s);
  590.   return("unknown");
  591. }
  592.  
  593. int printIDs()        /* print the known system IDs */
  594. {
  595.   struct intString * is = sysCodes;
  596.  
  597.   /* This might need to do more processing eventually, i.e.
  598.    * if (prompt) { ... do more processing ... }
  599.    */
  600.   printf("_ID_\t__Name__ ____Description____\n");
  601.   while (is->i) {
  602.     printf("%3d\t%s\n", is->i, is->s);
  603.     is++;
  604.   }
  605. }
  606.