display(fp, &label);
display(fp, &label, 0);
editor(lp, f, dev, fstabfile)	struct disklabel *lp;	int f;	char *dev;	char *fstabfile;{	struct disklabel lastlabel, tmplabel, label = *lp;	struct disklabel *disk_geop, *bios_geop;	struct partition *pp;	u_int32_t freesectors;	FILE *fp;	char buf[BUFSIZ], *cmd, *arg;	char **mountpoints = NULL, **omountpoints = NULL, **tmpmountpoints = NULL;	/* Alloc and init mount point info */	if (fstabfile) {		if (!(mountpoints = calloc(MAXPARTITIONS, sizeof(char *))) ||		    !(omountpoints = calloc(MAXPARTITIONS, sizeof(char *))) ||		    !(tmpmountpoints = calloc(MAXPARTITIONS, sizeof(char *))))			errx(4, "out of memory");	}	/* Don't allow disk type of "unknown" */	getdisktype(&label, "You need to specify a type for this disk.", dev);	/* Get the on-disk and BIOS geometries if possible */	get_geometry(f, &disk_geop, &bios_geop);	/* How big is the OpenBSD portion of the disk?  */	find_bounds(&label, bios_geop);	/* Set freesectors based on bounds and initial label */	editor_countfree(&label, &freesectors);	/* Make sure there is no partition overlap. */	if (has_overlap(&label, &freesectors, 1))		errx(1, "can't run when there is partition overlap.");	/* If we don't have a 'c' partition, create one. */	pp = &label.d_partitions[RAW_PART];	if (label.d_npartitions < 3 || pp->p_size == 0) {		puts("No 'c' partition found, adding one that spans the disk.");		if (label.d_npartitions < 3)			label.d_npartitions = 3;		pp->p_offset = 0;		pp->p_size = label.d_secperunit;		pp->p_fstype = FS_UNUSED;		pp->p_fsize = pp->p_frag = pp->p_cpg = 0;	}#ifdef CYLCHECK	puts("This platform requires that partition offsets/sizes be on cylinder boundaries.\nPartition offsets/sizes will be rounded to the nearest cylinder automatically.");#endif	/* Set d_bbsize and d_sbsize as necessary */	if (label.d_bbsize == 0)		label.d_bbsize = BBSIZE;	if (label.d_sbsize == 0)		label.d_sbsize = SBSIZE;	/* Interleave must be >= 1 */	if (label.d_interleave == 0)		label.d_interleave = 1;	puts("\nInitial label editor (enter '?' for help at any prompt)");	lastlabel = label;	for (;;) {		fputs("> ", stdout);		if (fgets(buf, sizeof(buf), stdin) == NULL) {			putchar('\n');			buf[0] = 'q';			buf[1] = '\0';		}		if ((cmd = strtok(buf, " \t\r\n")) == NULL)			continue;		arg = strtok(NULL, " \t\r\n");		switch (*cmd) {		case '?':		case 'h':			editor_help(arg ? arg : "");			break;		case 'a':			tmplabel = lastlabel;			lastlabel = label;			if (mountpoints != NULL) {				mpcopy(tmpmountpoints, omountpoints);				mpcopy(omountpoints, mountpoints);			}			editor_add(&label, mountpoints, &freesectors, arg);			if (memcmp(&label, &lastlabel, sizeof(label)) == 0)				lastlabel = tmplabel;			if (mountpoints != NULL && mpequal(omountpoints, tmpmountpoints))				mpcopy(omountpoints, tmpmountpoints);			break;		case 'b':			tmplabel = lastlabel;			lastlabel = label;			set_bounds(&label, &freesectors);			if (memcmp(&label, &lastlabel, sizeof(label)) == 0)				lastlabel = tmplabel;			break;		case 'c':			tmplabel = lastlabel;			lastlabel = label;			editor_change(&label, &freesectors, arg);			if (memcmp(&label, &lastlabel, sizeof(label)) == 0)				lastlabel = tmplabel;			break;		case 'D':			tmplabel = lastlabel;			lastlabel = label;			if (ioctl(f, DIOCGPDINFO, &label) == 0)				editor_countfree(&label, &freesectors);			else {				warn("unable to get default partition table");				lastlabel = tmplabel;			}			break;		case 'd':			tmplabel = lastlabel;			lastlabel = label;			if (mountpoints != NULL) {				mpcopy(tmpmountpoints, omountpoints);				mpcopy(omountpoints, mountpoints);			}			editor_delete(&label, mountpoints, &freesectors, arg);			if (memcmp(&label, &lastlabel, sizeof(label)) == 0)				lastlabel = tmplabel;			if (mountpoints != NULL && mpequal(omountpoints, tmpmountpoints))				mpcopy(omountpoints, tmpmountpoints);			break;		case 'e':			tmplabel = lastlabel;			lastlabel = label;			edit_parms(&label, &freesectors);			if (memcmp(&label, &lastlabel, sizeof(label)) == 0)				lastlabel = tmplabel;			break;		case 'g':			tmplabel = lastlabel;			lastlabel = label;			set_geometry(&label, disk_geop, bios_geop, lp, arg);			if (memcmp(&label, &lastlabel, sizeof(label)) == 0)				lastlabel = tmplabel;			break;		case 'm':			tmplabel = lastlabel;			lastlabel = label;			if (mountpoints != NULL) {				mpcopy(tmpmountpoints, omountpoints);				mpcopy(omountpoints, mountpoints);			}			editor_modify(&label, mountpoints, &freesectors, arg);			if (memcmp(&label, &lastlabel, sizeof(label)) == 0)				lastlabel = tmplabel;			if (mountpoints != NULL && mpequal(omountpoints, tmpmountpoints))				mpcopy(omountpoints, tmpmountpoints);			break;		case 'n':			if (mountpoints == NULL) {				fputs("This option is not valid when run "				    "without the -f flag.\n", stderr);				break;			}			mpcopy(tmpmountpoints, omountpoints);			mpcopy(omountpoints, mountpoints);			editor_name(&label, mountpoints, arg);			if (mpequal(omountpoints, tmpmountpoints))				mpcopy(omountpoints, tmpmountpoints);			break;		case 'p':			editor_display(&label, mountpoints, &freesectors,			    arg ? *arg : 0);			break;		case 'M': {			sig_t opipe = signal(SIGPIPE, SIG_IGN);			char *pager;			extern char manpage[];			if ((pager = getenv("PAGER")) == NULL || *pager == '\0')				pager = _PATH_LESS;			if ((fp = popen(pager, "w")) != NULL) {				(void) fwrite(manpage, strlen(manpage), 1, fp);				pclose(fp);			} else				warn("unable to execute %s", pager);			(void)signal(SIGPIPE, opipe);			break;		}		case 'q':			if (donothing) {				puts("In no change mode, not writing label.");				return(1);			}			/* Save mountpoint info if there is any. */			if (mountpoints != NULL)				mpsave(&label, mountpoints, dev, fstabfile);			if (memcmp(lp, &label, sizeof(label)) == 0) {				puts("No label changes.");				return(1);			}			do {				arg = getstring("Write new label?",				    "Write the modified label to disk?",				    "y");			} while (arg && tolower(*arg) != 'y' && tolower(*arg) != 'n');			if (arg && tolower(*arg) == 'y') {				if (writelabel(f, bootarea, &label) == 0) {					*lp = label;					return(0);				}				warnx("unable to write label");			}			return(1);			/* NOTREACHED */			break;		case 'r':		    /* Recalculate free space */		    editor_countfree(&label, &freesectors);		    puts("Recalculated free space.");		    break;		case 's':			if (arg == NULL) {				arg = getstring("Filename",				    "Name of the file to save label into.",				    NULL);				if (arg == NULL && *arg == '\0')					break;			}			if ((fp = fopen(arg, "w")) == NULL) {				warn("cannot open %s", arg);			} else {				display(fp, &label);				(void)fclose(fp);			}			break;		case 'u':			if (memcmp(&label, &lastlabel, sizeof(label)) == 0 &&			    mountpoints != NULL &&			    mpequal(mountpoints, omountpoints)) {				puts("Nothing to undo!");			} else {				tmplabel = label;				label = lastlabel;				lastlabel = tmplabel;				/* Recalculate free space */				editor_countfree(&label, &freesectors);				/* Restore mountpoints */				if (mountpoints != NULL)					mpcopy(mountpoints, omountpoints);				puts("Last change undone.");			}			break;		case 'w':			if (donothing)  {				puts("In no change mode, not writing label.");				break;			}			/* Save mountpoint info if there is any. */			if (mountpoints != NULL)				mpsave(&label, mountpoints, dev, fstabfile);			/* Save label if it has changed. */			if (memcmp(lp, &label, sizeof(label)) == 0)				puts("No label changes.");			else if (writelabel(f, bootarea, &label) != 0)				warnx("unable to write label");			else				*lp = label;			break;		case 'X':			expert = !expert;			printf("%s expert mode\n", expert ? "Entering" :			    "Exiting");			break;		case 'x':			return(1);			break;		case 'z':			tmplabel = lastlabel;			lastlabel = label;			zero_partitions(&label, &freesectors);			break;		case '\n':			break;		default:			printf("Unknown option: %c ('?' for help)\n", *cmd);			break;		}	}}