#include <stdio.h>
#include <ctype.h>
#include <memory.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/fcntl.h>
#include "disk.h"
#include "misc.h"
#include "user.h"
#include "part.h"
#include "cmd.h"
#include "auto.h"
#define MAX(a, b) ((a) >= (b) ? (a) : (b))
int
Xerase(cmd, disk, mbr, tt, offset)
cmd_t *cmd;
disk_t *disk;
mbr_t *mbr;
mbr_t *tt;
int offset;
{
bzero(mbr->part, sizeof(mbr->part));
mbr->signature = MBR_SIGNATURE;
return (CMD_DIRTY);
}
int
Xreinit(cmd, disk, mbr, tt, offset)
cmd_t *cmd;
disk_t *disk;
mbr_t *mbr;
mbr_t *tt;
int offset;
{
MBR_make(tt);
MBR_parse(disk, offset, 0, mbr);
MBR_init(disk, mbr);
printf("In memory copy is initialized to:\n");
printf("Offset: %d\t", offset);
MBR_print(mbr);
printf("Use 'write' to update disk.\n");
return (CMD_DIRTY);
}
int
Xauto(cmd, disk, mbr, tt, offset)
cmd_t *cmd;
disk_t *disk;
mbr_t *mbr;
mbr_t *tt;
int offset;
{
if (cmd->args[0] == '\0') {
printf("usage: auto <style>\n");
printf(" where style is one of:\n");
AUTO_print_styles(stdout);
return (CMD_CONT);
}
if (AUTO_init(disk, cmd->args, mbr) != AUTO_OK) {
return (CMD_CONT);
}
MBR_make(mbr);
return (CMD_DIRTY);
}
int
Xdisk(cmd, disk, mbr, tt, offset)
cmd_t *cmd;
disk_t *disk;
mbr_t *mbr;
mbr_t *tt;
int offset;
{
int maxcyl = 1024;
int maxhead = 256;
int maxsec = 63;
DISK_printmetrics(disk);
#if defined (__powerpc__) || defined (__mips__)
maxcyl = 9999999;
maxhead = 9999999;
maxsec = 9999999;
#endif
if (ask_yn("Change disk geometry?", 0)) {
disk->real->cylinders = ask_num("BIOS Cylinders", ASK_DEC,
disk->real->cylinders, 1, maxcyl, NULL);
disk->real->heads = ask_num("BIOS Heads", ASK_DEC,
disk->real->heads, 1, maxhead, NULL);
disk->real->sectors = ask_num("BIOS Sectors", ASK_DEC,
disk->real->sectors, 1, maxsec, NULL);
disk->real->size = disk->real->cylinders * disk->real->heads
* disk->real->sectors;
}
return (CMD_CONT);
}
int
Xedit(cmd, disk, mbr, tt, offset)
cmd_t *cmd;
disk_t *disk;
mbr_t *mbr;
mbr_t *tt;
int offset;
{
int pn, num, ret;
prt_t *pp;
ret = CMD_CONT;
if (!isdigit(cmd->args[0])) {
printf("Invalid argument: %s <partition number>\n", cmd->cmd);
return (ret);
}
pn = atoi(cmd->args) - 1;
if (pn < 0 || pn > 3) {
printf("Invalid partition number.\n");
return (ret);
}
pp = &mbr->part[pn];
PRT_print(0, NULL);
PRT_print(pn, pp);
#define EDIT(p, f, v, n, m, h) \
if ((num = ask_num(p, f, v, n, m, h)) != v) \
ret = CMD_DIRTY; \
v = num;
EDIT("Partition id ('0' to disable) ", ASK_HEX, pp->id, 0, 0xFF, PRT_printall);
if (pp->id == DOSPTYP_UNUSED) {
memset(pp, 0, sizeof(*pp));
printf("Partition %d is disabled.\n", pn + 1);
return (ret);
}
if (ask_yn("Do you wish to edit in CHS mode?", 0)) {
int maxcyl, maxhead, maxsect;
maxcyl = disk->real->cylinders - 1;
maxhead = disk->real->heads - 1;
maxsect = disk->real->sectors;
EDIT("BIOS Starting cylinder", ASK_DEC, pp->scyl, 0, maxcyl, NULL);
EDIT("BIOS Starting head", ASK_DEC, pp->shead, 0, maxhead, NULL);
EDIT("BIOS Starting sector", ASK_DEC, pp->ssect, 1, maxsect, NULL);
EDIT("BIOS Ending cylinder", ASK_DEC, pp->ecyl, 0, maxcyl, NULL);
EDIT("BIOS Ending head", ASK_DEC, pp->ehead, 0, maxhead, NULL);
EDIT("BIOS Ending sector", ASK_DEC, pp->esect, 1, maxsect, NULL);
PRT_fix_BN(disk, pp, pn);
PRT_fix_CHS(disk, pp, pn);
} else {
u_int m;
if (pn == 0) {
pp->bs = 63 + offset;
} else {
if (mbr->part[pn-1].id != 0) {
pp->bs = mbr->part[pn-1].bs + mbr->part[pn-1].ns;
}
}
EDIT("Partition offset", ASK_DEC, pp->bs, 0,
disk->real->size, NULL);
m = MAX(pp->ns, disk->real->size - pp->bs);
if ( m > disk->real->size - pp->bs) {
m = disk->real->size - pp->bs;
}
pp->ns = m;
EDIT("Partition size", ASK_DEC, pp->ns, 1,
m, NULL);
PRT_fix_CHS(disk, pp, pn);
}
#undef EDIT
return (ret);
}
int
Xsetpid(cmd, disk, mbr, tt, offset)
cmd_t *cmd;
disk_t *disk;
mbr_t *mbr;
mbr_t *tt;
int offset;
{
int pn, num, ret;
prt_t *pp;
ret = CMD_CONT;
if (!isdigit(cmd->args[0])) {
printf("Invalid argument: %s <partition number>\n", cmd->cmd);
return (ret);
}
pn = atoi(cmd->args) - 1;
if (pn < 0 || pn > 3) {
printf("Invalid partition number.\n");
return (ret);
}
pp = &mbr->part[pn];
PRT_print(0, NULL);
PRT_print(pn, pp);
#define EDIT(p, f, v, n, m, h) \
if ((num = ask_num(p, f, v, n, m, h)) != v) \
ret = CMD_DIRTY; \
v = num;
EDIT("Partition id ('0' to disable) ", ASK_HEX, pp->id, 0, 0xFF, PRT_printall);
#undef EDIT
return (ret);
}
int
Xselect(cmd, disk, mbr, tt, offset)
cmd_t *cmd;
disk_t *disk;
mbr_t *mbr;
mbr_t *tt;
int offset;
{
static int firstoff = 0;
int off;
int pn;
if (!isdigit(cmd->args[0])) {
printf("Invalid argument: %s <partition number>\n", cmd->cmd);
return (CMD_CONT);
}
pn = atoi(cmd->args) - 1;
if (pn < 0 || pn > 3) {
printf("Invalid partition number.\n");
return (CMD_CONT);
}
off = mbr->part[pn].bs;
if ((mbr->part[pn].id != DOSPTYP_EXTEND) &&
(mbr->part[pn].id != DOSPTYP_EXTENDL)) {
printf("Partition %d is not an extended partition.\n", pn + 1);
return (CMD_CONT);
}
if (firstoff == 0)
firstoff = off;
if (!off) {
printf("Loop to offset 0! Not selected.\n");
return (CMD_CONT);
} else {
printf("Selected extended partition %d\n", pn + 1);
printf("New MBR at offset %d.\n", off);
}
USER_modify(disk, tt, off, firstoff);
return (CMD_CONT);
}
int
Xprint(cmd, disk, mbr, tt, offset)
cmd_t *cmd;
disk_t *disk;
mbr_t *mbr;
mbr_t *tt;
int offset;
{
DISK_printmetrics(disk);
printf("Offset: %d\t", offset);
MBR_print(mbr);
return (CMD_CONT);
}
int
Xwrite(cmd, disk, mbr, tt, offset)
cmd_t *cmd;
disk_t *disk;
mbr_t *mbr;
mbr_t *tt;
int offset;
{
int fd;
int shared = 0;
fd = DISK_openshared(disk->name, O_RDWR, &shared);
if(shared) {
if(!ask_yn("Device could not be accessed exclusively.\nA reboot will be needed for changes to take effect. OK?", 0)) {
close(fd);
printf("MBR unchanged\n");
return (CMD_CONT);
}
}
printf("Writing MBR at offset %d.\n", offset);
MBR_make(mbr);
MBR_write(fd, mbr);
close(fd);
return (CMD_CLEAN);
}
int
Xquit(cmd, disk, r, tt, offset)
cmd_t *cmd;
disk_t *disk;
mbr_t *r;
mbr_t *tt;
int offset;
{
return (CMD_SAVE);
}
int
Xabort(cmd, disk, mbr, tt, offset)
cmd_t *cmd;
disk_t *disk;
mbr_t *mbr;
mbr_t *tt;
int offset;
{
exit(0);
return (CMD_CONT);
}
int
Xexit(cmd, disk, mbr, tt, offset)
cmd_t *cmd;
disk_t *disk;
mbr_t *mbr;
mbr_t *tt;
int offset;
{
return (CMD_EXIT);
}
int
Xhelp(cmd, disk, mbr, tt, offset)
cmd_t *cmd;
disk_t *disk;
mbr_t *mbr;
mbr_t *tt;
int offset;
{
cmd_table_t *cmd_table = cmd->table;
int i;
for (i = 0; cmd_table[i].cmd != NULL; i++)
printf("\t%s\t\t%s\n", cmd_table[i].cmd, cmd_table[i].help);
return (CMD_CONT);
}
int
Xupdate(cmd, disk, mbr, tt, offset)
cmd_t *cmd;
disk_t *disk;
mbr_t *mbr;
mbr_t *tt;
int offset;
{
extern char *mbr_binary;
memcpy(mbr->code, mbr_binary, MBR_CODE_SIZE);
printf("Machine code updated.\n");
return (CMD_DIRTY);
}
int
Xflag(cmd, disk, mbr, tt, offset)
cmd_t *cmd;
disk_t *disk;
mbr_t *mbr;
mbr_t *tt;
int offset;
{
int i, pn = -1;
if (!isdigit(cmd->args[0])) {
printf("Invalid argument: %s <partition number>\n", cmd->cmd);
return (CMD_CONT);
}
pn = atoi(cmd->args) - 1;
if (pn < 0 || pn > 3) {
printf("Invalid partition number.\n");
return (CMD_CONT);
}
for (i = 0; i < 4; i++) {
if (i == pn)
mbr->part[i].flag = DOSACTIVE;
else
mbr->part[i].flag = 0x00;
}
printf("Partition %d marked active.\n", pn + 1);
return (CMD_DIRTY);
}
int
Xmanual(cmd, disk, mbr, tt, offset)
cmd_t *cmd;
disk_t *disk;
mbr_t *mbr;
mbr_t *tt;
int offset;
{
char *pager = "/usr/bin/less";
char *p;
sig_t opipe;
extern char manpage[];
FILE *f;
opipe = signal(SIGPIPE, SIG_IGN);
if ((p = getenv("PAGER")) != NULL && (*p != '\0'))
pager = p;
f = popen(pager, "w");
if (f) {
(void) fwrite(manpage, strlen(manpage), 1, f);
pclose(f);
}
(void)signal(SIGPIPE, opipe);
return (CMD_CONT);
}