Compare commits
3 Commits
adcf11944f
...
e9d9eabb6e
Author | SHA1 | Date |
---|---|---|
Jonas 'Sortie' Termansen | e9d9eabb6e | |
Jonas 'Sortie' Termansen | b029127df5 | |
Jonas 'Sortie' Termansen | c77745e447 |
|
@ -6,7 +6,10 @@
|
||||||
.Nd disk editor
|
.Nd disk editor
|
||||||
.Sh SYNOPSIS
|
.Sh SYNOPSIS
|
||||||
.Nm disked
|
.Nm disked
|
||||||
|
.Op Fl in
|
||||||
.Op Fl \-fstab Ns "=" Ns Ar path
|
.Op Fl \-fstab Ns "=" Ns Ar path
|
||||||
|
.Op Ar device
|
||||||
|
.Op Ar command ...
|
||||||
.Sh DESCRIPTION
|
.Sh DESCRIPTION
|
||||||
.Nm
|
.Nm
|
||||||
is an interactive program that manages partition tables.
|
is an interactive program that manages partition tables.
|
||||||
|
@ -19,17 +22,22 @@ supports the Master Boot Record and GUID Partition Table partitioning schemes.
|
||||||
.Pp
|
.Pp
|
||||||
.Nm
|
.Nm
|
||||||
provides an interactive command line.
|
provides an interactive command line.
|
||||||
Its prompt shows the currently selected device (defaulting to the first device
|
Its prompt shows the currently selected
|
||||||
alphabetically) or
|
.Ar device
|
||||||
|
(defaulting to the first device alphabetically if any) or
|
||||||
.Li (disked)
|
.Li (disked)
|
||||||
if none is selected.
|
if none is selected.
|
||||||
|
If a
|
||||||
|
.Ar command
|
||||||
|
is specified on the command line, then that command is run with its arguments
|
||||||
|
non-interactively instead of reading from the standard input.
|
||||||
|
.Pp
|
||||||
Commands perform their actions when run rather than waiting for the user to
|
Commands perform their actions when run rather than waiting for the user to
|
||||||
write out changes.
|
write out changes.
|
||||||
.Nm
|
.Nm
|
||||||
only creates partitions aligned to 1 MiB boundaries whose size is a multiple of
|
only creates partitions aligned to 1 MiB boundaries whose size is a multiple of
|
||||||
1 MiB.
|
1 MiB.
|
||||||
Unused regions are aligned and those smaller than the alignment are not shown.
|
Unused regions are aligned and those smaller than the alignment are not shown.
|
||||||
.Pp
|
|
||||||
The options are as follows:
|
The options are as follows:
|
||||||
.Bl -tag -width "12345678"
|
.Bl -tag -width "12345678"
|
||||||
.It Fl \-fstab Ns "=" Ns Ar path
|
.It Fl \-fstab Ns "=" Ns Ar path
|
||||||
|
@ -39,6 +47,17 @@ instead of
|
||||||
.Pa /etc/fstab
|
.Pa /etc/fstab
|
||||||
as
|
as
|
||||||
.Xr fstab 5 .
|
.Xr fstab 5 .
|
||||||
|
.It Fl i
|
||||||
|
Run in interactive mode with prompt with line editing.
|
||||||
|
Commands will ask for missing parameters.
|
||||||
|
This is the default if the standard input and output are terminals and a
|
||||||
|
.Ar command
|
||||||
|
is not specified on the command line.
|
||||||
|
.It Fl n
|
||||||
|
Run in non-interactive mode reading commands from the standard input.
|
||||||
|
Commands will not ask for missing parameters and
|
||||||
|
.Nm
|
||||||
|
will immediately exit unsuccessfully if any command fail.
|
||||||
.El
|
.El
|
||||||
.Pp
|
.Pp
|
||||||
The following commands are supported:
|
The following commands are supported:
|
||||||
|
@ -78,14 +97,19 @@ Partitions are counted from 1.
|
||||||
Display this manual page if no operands are given, otherwise run
|
Display this manual page if no operands are given, otherwise run
|
||||||
.Xr man 1
|
.Xr man 1
|
||||||
with the given command line.
|
with the given command line.
|
||||||
.It Sy mkpart
|
.It Sy mkpart Ar hole Ar offset Ar length Ar filesystem Ar mountpoint
|
||||||
Create a partition on the current device.
|
Create a partition on the current device.
|
||||||
If the partition table has multiple unused regions
|
If the partition table has multiple unused regions
|
||||||
.Pq holes ,
|
.Pq holes ,
|
||||||
.Nm
|
.Nm
|
||||||
asks you which one to use.
|
asks you which
|
||||||
You need to specify the offset into the hole where the partition is created and
|
.Ar hole
|
||||||
then the length of the partition.
|
(counting from 1) to use.
|
||||||
|
You need to specify the
|
||||||
|
.Ar offset
|
||||||
|
into the hole where the partition is created and
|
||||||
|
then the
|
||||||
|
.Ar length of the partition.
|
||||||
See
|
See
|
||||||
.Sx QUANTITIES
|
.Sx QUANTITIES
|
||||||
below on the possible partition offset and length values.
|
below on the possible partition offset and length values.
|
||||||
|
@ -106,7 +130,9 @@ Use the existing disk data.
|
||||||
.El
|
.El
|
||||||
.Pp
|
.Pp
|
||||||
If you format a mountable filesystem, then you will be asked if you want to
|
If you format a mountable filesystem, then you will be asked if you want to
|
||||||
create a mountpoint for the partition, which will be added to
|
create a
|
||||||
|
.Ar mountpoint
|
||||||
|
for the partition, which will be added to
|
||||||
.Xr fstab 5 .
|
.Xr fstab 5 .
|
||||||
.It Sy mktable Oo mbr "|" gpt Oc
|
.It Sy mktable Oo mbr "|" gpt Oc
|
||||||
Create a partition table on the current device of the specified type.
|
Create a partition table on the current device of the specified type.
|
||||||
|
|
145
disked/disked.c
145
disked/disked.c
|
@ -240,6 +240,8 @@ static const char* device_name(const char* name)
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool interactive;
|
||||||
|
|
||||||
static void display_rows_columns(char* (*format)(void*, size_t, size_t),
|
static void display_rows_columns(char* (*format)(void*, size_t, size_t),
|
||||||
void* ctx, size_t rows, size_t columns)
|
void* ctx, size_t rows, size_t columns)
|
||||||
{
|
{
|
||||||
|
@ -395,6 +397,8 @@ static void prompt(char* buffer,
|
||||||
const char* question,
|
const char* question,
|
||||||
const char* answer)
|
const char* answer)
|
||||||
{
|
{
|
||||||
|
if ( !interactive )
|
||||||
|
errx(1, "Cannot ask question in non-interactive mode: %s", question);
|
||||||
while ( true )
|
while ( true )
|
||||||
{
|
{
|
||||||
printf("\e[1m");
|
printf("\e[1m");
|
||||||
|
@ -599,7 +603,6 @@ bool rewrite_finish(struct rewrite* rewr)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool interactive;
|
|
||||||
static bool quitting;
|
static bool quitting;
|
||||||
static struct harddisk** hds;
|
static struct harddisk** hds;
|
||||||
static size_t hds_count;
|
static size_t hds_count;
|
||||||
|
@ -1132,6 +1135,25 @@ static void switch_device(struct harddisk* hd)
|
||||||
scan_device();
|
scan_device();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool lookup_harddisk_by_string(struct harddisk** out,
|
||||||
|
const char* argv0,
|
||||||
|
const char* name)
|
||||||
|
{
|
||||||
|
for ( size_t i = 0; i < hds_count; i++ )
|
||||||
|
{
|
||||||
|
char buf[sizeof(i) * 3];
|
||||||
|
snprintf(buf, sizeof(buf), "%zu", i);
|
||||||
|
if ( strcmp(name, hds[i]->path) != 0 &&
|
||||||
|
strcmp(name, device_name(hds[i]->path)) != 0 &&
|
||||||
|
strcmp(name, buf) != 0 )
|
||||||
|
continue;
|
||||||
|
*out = hds[i];
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
command_errorx("%s: No such device `%s'", argv0, name);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static bool lookup_partition_by_string(struct partition** out,
|
static bool lookup_partition_by_string(struct partition** out,
|
||||||
const char* argv0,
|
const char* argv0,
|
||||||
const char* numstr)
|
const char* numstr)
|
||||||
|
@ -1573,8 +1595,6 @@ static char* display_hole_format(void* ctx, size_t row, size_t column)
|
||||||
|
|
||||||
static void on_mkpart(size_t argc, char** argv)
|
static void on_mkpart(size_t argc, char** argv)
|
||||||
{
|
{
|
||||||
(void) argc;
|
|
||||||
(void) argv;
|
|
||||||
size_t num_holes = 0;
|
size_t num_holes = 0;
|
||||||
struct device_area* hole = NULL;
|
struct device_area* hole = NULL;
|
||||||
for ( size_t i = 0; i < current_areas_count; i++ )
|
for ( size_t i = 0; i < current_areas_count; i++ )
|
||||||
|
@ -1598,8 +1618,11 @@ static void on_mkpart(size_t argc, char** argv)
|
||||||
char answer[sizeof(size_t) * 3];
|
char answer[sizeof(size_t) * 3];
|
||||||
while ( true )
|
while ( true )
|
||||||
{
|
{
|
||||||
prompt(answer, sizeof(answer),
|
if ( 2 <= argc )
|
||||||
"Which hole to create the partition inside?", "1");
|
strlcpy(answer, argv[1], sizeof(answer));
|
||||||
|
else
|
||||||
|
prompt(answer, sizeof(answer),
|
||||||
|
"Which hole to create the partition inside?", "1");
|
||||||
char* end;
|
char* end;
|
||||||
unsigned long num = strtoul(answer, &end, 10);
|
unsigned long num = strtoul(answer, &end, 10);
|
||||||
if ( *end || num_holes < num )
|
if ( *end || num_holes < num )
|
||||||
|
@ -1618,7 +1641,8 @@ static void on_mkpart(size_t argc, char** argv)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
printf("\n");
|
if ( argc < 2 )
|
||||||
|
printf("\n");
|
||||||
}
|
}
|
||||||
unsigned int slot = 0;
|
unsigned int slot = 0;
|
||||||
if ( current_pt_type == PARTITION_TABLE_TYPE_MBR && hole->inside_extended )
|
if ( current_pt_type == PARTITION_TABLE_TYPE_MBR && hole->inside_extended )
|
||||||
|
@ -1678,54 +1702,68 @@ static void on_mkpart(size_t argc, char** argv)
|
||||||
assert(start_str); // TODO: Error handling.
|
assert(start_str); // TODO: Error handling.
|
||||||
char* length_str = format_bytes_amount((uintmax_t) hole->length);
|
char* length_str = format_bytes_amount((uintmax_t) hole->length);
|
||||||
assert(length_str); // TODO: Error handling.
|
assert(length_str); // TODO: Error handling.
|
||||||
printf("Creating partition inside hole at %s of length %s (100%%)\n",
|
if ( argc < 3 )
|
||||||
start_str, length_str);
|
printf("Creating partition inside hole at %s of length %s (100%%)\n",
|
||||||
|
start_str, length_str);
|
||||||
free(start_str);
|
free(start_str);
|
||||||
free(length_str);
|
free(length_str);
|
||||||
off_t start;
|
off_t start;
|
||||||
while ( true )
|
while ( true )
|
||||||
{
|
{
|
||||||
char answer[256];
|
char answer[256];
|
||||||
prompt(answer, sizeof(answer),
|
if ( 3 <= argc )
|
||||||
"Free space before partition? (42%/15G/...)", "0%");
|
strlcpy(answer, argv[2], sizeof(answer));
|
||||||
|
else
|
||||||
|
prompt(answer, sizeof(answer),
|
||||||
|
"Free space before partition? (42%/15G/...)", "0%");
|
||||||
if ( !parse_disk_quantity(&start, answer, hole->length) )
|
if ( !parse_disk_quantity(&start, answer, hole->length) )
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Invalid quantity `%s'.\n", answer);
|
command_errorx("%s: %s: Invalid quantity: %s",
|
||||||
|
argv[0], device_name(current_hd->path), answer);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if ( start == hole->length )
|
if ( start == hole->length )
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Answer was all free space, but need space for the "
|
command_errorx("%s: %s: Answer was all free space, but need space "
|
||||||
"partition itself.\n");
|
"for the partition itself",
|
||||||
|
argv[0], device_name(current_hd->path));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
printf("\n");
|
if ( argc < 3 )
|
||||||
|
printf("\n");
|
||||||
off_t max_length = hole->length - start;
|
off_t max_length = hole->length - start;
|
||||||
off_t length;
|
off_t length;
|
||||||
length_str = format_bytes_amount((uintmax_t) max_length);
|
length_str = format_bytes_amount((uintmax_t) max_length);
|
||||||
assert(length_str);
|
assert(length_str);
|
||||||
printf("Partition size can be at most %s (100%%).\n", length_str);
|
if ( argc < 4 )
|
||||||
|
printf("Partition size can be at most %s (100%%).\n", length_str);
|
||||||
free(length_str);
|
free(length_str);
|
||||||
while ( true )
|
while ( true )
|
||||||
{
|
{
|
||||||
char answer[256];
|
char answer[256];
|
||||||
prompt(answer, sizeof(answer),
|
if ( 4 <= argc )
|
||||||
"Partition size? (42%/15G/...)", "100%");
|
strlcpy(answer, argv[3], sizeof(answer));
|
||||||
|
else
|
||||||
|
prompt(answer, sizeof(answer),
|
||||||
|
"Partition size? (42%/15G/...)", "100%");
|
||||||
if ( !parse_disk_quantity(&length, answer, max_length) )
|
if ( !parse_disk_quantity(&length, answer, max_length) )
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Invalid quantity `%s'.\n", answer);
|
command_errorx("%s: %s: Invalid quantity: %s",
|
||||||
|
argv[0], device_name(current_hd->path), answer);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if ( length == 0 )
|
if ( length == 0 )
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Answer was zero (or rounded down to zero).\n");
|
command_errorx("%s: %s: Length was zero (or rounded down to zero)",
|
||||||
|
argv[0], device_name(current_hd->path));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
printf("\n");
|
if ( argc < 4 )
|
||||||
|
printf("\n");
|
||||||
char fstype[256];
|
char fstype[256];
|
||||||
while ( true )
|
while ( true )
|
||||||
{
|
{
|
||||||
|
@ -1736,13 +1774,17 @@ static void on_mkpart(size_t argc, char** argv)
|
||||||
question = "Format a filesystem? (no/ext2/extended)";
|
question = "Format a filesystem? (no/ext2/extended)";
|
||||||
else if ( is_gpt )
|
else if ( is_gpt )
|
||||||
question = "Format a filesystem? (no/ext2/biosboot)";
|
question = "Format a filesystem? (no/ext2/biosboot)";
|
||||||
prompt(fstype, sizeof(fstype), question, "ext2");
|
if ( 5 <= argc )
|
||||||
|
strlcpy(fstype, argv[4], sizeof(fstype));
|
||||||
|
else
|
||||||
|
prompt(fstype, sizeof(fstype), question, "ext2");
|
||||||
if ( strcmp(fstype, "no") != 0 &&
|
if ( strcmp(fstype, "no") != 0 &&
|
||||||
strcmp(fstype, "ext2") != 0 &&
|
strcmp(fstype, "ext2") != 0 &&
|
||||||
(!is_mbr || strcmp(fstype, "extended") != 0) &&
|
(!is_mbr || strcmp(fstype, "extended") != 0) &&
|
||||||
(!is_gpt || strcmp(fstype, "biosboot") != 0) )
|
(!is_gpt || strcmp(fstype, "biosboot") != 0) )
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Invalid filesystem choice `%s'.\n", fstype);
|
command_errorx("%s: %s: Invalid filesystem choice: %s",
|
||||||
|
argv[0], device_name(current_hd->path), fstype);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if ( !strcmp(fstype, "extended") )
|
if ( !strcmp(fstype, "extended") )
|
||||||
|
@ -1762,27 +1804,27 @@ static void on_mkpart(size_t argc, char** argv)
|
||||||
bool mountable = !strcmp(fstype, "ext2");
|
bool mountable = !strcmp(fstype, "ext2");
|
||||||
while ( mountable )
|
while ( mountable )
|
||||||
{
|
{
|
||||||
prompt(mountpoint, sizeof(mountpoint),
|
if ( 6 <= argc )
|
||||||
"Where to mount partition? (mountpoint or 'no')", "no");
|
strlcpy(mountpoint, argv[5], sizeof(mountpoint));
|
||||||
|
else
|
||||||
|
prompt(mountpoint, sizeof(mountpoint),
|
||||||
|
"Where to mount partition? (mountpoint or 'no')", "no");
|
||||||
if ( !strcmp(mountpoint, "no") )
|
if ( !strcmp(mountpoint, "no") )
|
||||||
{
|
{
|
||||||
mountpoint[0] = '\0';
|
mountpoint[0] = '\0';
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if ( !strcmp(mountpoint, "mountpoint") )
|
|
||||||
{
|
|
||||||
printf("Then answer which mountpoint.\n");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if ( !verify_mountpoint(mountpoint) )
|
if ( !verify_mountpoint(mountpoint) )
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Invalid mountpoint `%s'.\n", fstype);
|
command_errorx("%s: %s: Invalid mountpoint: %s",
|
||||||
|
argv[0], device_name(current_hd->path), mountpoint);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
simplify_mountpoint(mountpoint);
|
simplify_mountpoint(mountpoint);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
printf("\n");
|
if ( mountable && argc < 6 )
|
||||||
|
printf("\n");
|
||||||
size_t renumbered_partitions = 0;
|
size_t renumbered_partitions = 0;
|
||||||
if ( current_pt_type == PARTITION_TABLE_TYPE_MBR && hole->inside_extended )
|
if ( current_pt_type == PARTITION_TABLE_TYPE_MBR && hole->inside_extended )
|
||||||
{
|
{
|
||||||
|
@ -2696,14 +2738,8 @@ static const struct command commands[] =
|
||||||
};
|
};
|
||||||
static const size_t commands_count = sizeof(commands) / sizeof(commands[0]);
|
static const size_t commands_count = sizeof(commands) / sizeof(commands[0]);
|
||||||
|
|
||||||
void execute(char* cmd)
|
static void execute_argv(int argc, char** argv)
|
||||||
{
|
{
|
||||||
size_t argc = 0;
|
|
||||||
char* argv[256];
|
|
||||||
split_arguments(cmd, &argc, argv, 255);
|
|
||||||
if ( argc < 1 )
|
|
||||||
return;
|
|
||||||
argv[argc] = NULL;
|
|
||||||
for ( size_t i = 0; i < commands_count; i++ )
|
for ( size_t i = 0; i < commands_count; i++ )
|
||||||
{
|
{
|
||||||
if ( strcmp(argv[0], commands[i].name) != 0 )
|
if ( strcmp(argv[0], commands[i].name) != 0 )
|
||||||
|
@ -2738,6 +2774,17 @@ void execute(char* cmd)
|
||||||
"Try `help' for more information.\n", argv[0]);
|
"Try `help' for more information.\n", argv[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void execute(char* cmd)
|
||||||
|
{
|
||||||
|
size_t argc = 0;
|
||||||
|
char* argv[256];
|
||||||
|
split_arguments(cmd, &argc, argv, 255);
|
||||||
|
if ( argc < 1 )
|
||||||
|
return;
|
||||||
|
argv[argc] = NULL;
|
||||||
|
execute_argv(argc, argv);
|
||||||
|
}
|
||||||
|
|
||||||
static void compact_arguments(int* argc, char*** argv)
|
static void compact_arguments(int* argc, char*** argv)
|
||||||
{
|
{
|
||||||
for ( int i = 0; i < *argc; i++ )
|
for ( int i = 0; i < *argc; i++ )
|
||||||
|
@ -2766,6 +2813,8 @@ int main(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
setlocale(LC_ALL, "");
|
setlocale(LC_ALL, "");
|
||||||
|
|
||||||
|
bool set_interactive = false;
|
||||||
|
|
||||||
const char* argv0 = argv[0];
|
const char* argv0 = argv[0];
|
||||||
for ( int i = 1; i < argc; i++ )
|
for ( int i = 1; i < argc; i++ )
|
||||||
{
|
{
|
||||||
|
@ -2780,6 +2829,8 @@ int main(int argc, char* argv[])
|
||||||
char c;
|
char c;
|
||||||
while ( (c = *++arg) ) switch ( c )
|
while ( (c = *++arg) ) switch ( c )
|
||||||
{
|
{
|
||||||
|
case 'i': interactive = true; set_interactive = true; break;
|
||||||
|
case 'n': interactive = false; set_interactive = true; break;
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "%s: unknown option -- '%c'\n", argv0, c);
|
fprintf(stderr, "%s: unknown option -- '%c'\n", argv0, c);
|
||||||
help(stderr, argv0);
|
help(stderr, argv0);
|
||||||
|
@ -2813,20 +2864,30 @@ int main(int argc, char* argv[])
|
||||||
|
|
||||||
compact_arguments(&argc, &argv);
|
compact_arguments(&argc, &argv);
|
||||||
|
|
||||||
interactive = isatty(0) && isatty(1);
|
if ( !set_interactive )
|
||||||
|
interactive = isatty(0) && isatty(1) && argc < 3;
|
||||||
|
|
||||||
if ( !devices_open_all(&hds, &hds_count) )
|
if ( !devices_open_all(&hds, &hds_count) )
|
||||||
err(1, "iterating devices");
|
err(1, "iterating devices");
|
||||||
|
|
||||||
qsort(hds, hds_count, sizeof(struct harddisk*), harddisk_compare_path);
|
qsort(hds, hds_count, sizeof(struct harddisk*), harddisk_compare_path);
|
||||||
|
|
||||||
if ( 1 <= hds_count )
|
if ( 2 <= argc )
|
||||||
|
{
|
||||||
|
struct harddisk* hd;
|
||||||
|
if ( !lookup_harddisk_by_string(&hd, argv[0], argv[1]) )
|
||||||
|
exit(1);
|
||||||
|
switch_device(hd);
|
||||||
|
}
|
||||||
|
else if ( 1 <= hds_count )
|
||||||
switch_device(hds[0]);
|
switch_device(hds[0]);
|
||||||
|
|
||||||
char* line = NULL;
|
char* line = NULL;
|
||||||
size_t line_size = 0;
|
size_t line_size = 0;
|
||||||
ssize_t line_length;
|
ssize_t line_length;
|
||||||
while ( !quitting )
|
if ( 3 <= argc )
|
||||||
|
execute_argv(argc - 2, argv + 2);
|
||||||
|
else while ( !quitting )
|
||||||
{
|
{
|
||||||
if ( interactive )
|
if ( interactive )
|
||||||
{
|
{
|
||||||
|
@ -2855,4 +2916,6 @@ int main(int argc, char* argv[])
|
||||||
for ( size_t i = 0; i < hds_count; i++ )
|
for ( size_t i = 0; i < hds_count; i++ )
|
||||||
harddisk_close(hds[i]);
|
harddisk_close(hds[i]);
|
||||||
free(hds);
|
free(hds);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,19 +20,21 @@
|
||||||
.Op Fl \-height Ns "=" Ns Ar height
|
.Op Fl \-height Ns "=" Ns Ar height
|
||||||
.Op Fl \-min-height Ns "=" Ns Ar min-height
|
.Op Fl \-min-height Ns "=" Ns Ar min-height
|
||||||
.Op Fl \-max-height Ns "=" Ns Ar max-height
|
.Op Fl \-max-height Ns "=" Ns Ar max-height
|
||||||
.Op Ar command ...
|
.Op Ar videomode
|
||||||
.Sh DESCRIPTION
|
.Sh DESCRIPTION
|
||||||
.Nm
|
.Nm
|
||||||
changes the video mode by displaying an interactive menu containing a list of
|
changes the video mode by displaying an interactive menu containing a list of
|
||||||
available modes, with an additional entry for entering a custom mode (if
|
available modes, with an additional entry for entering a custom mode (if
|
||||||
supported by the driver).
|
supported by the driver).
|
||||||
If the mode change succeeds and
|
|
||||||
.Ar command
|
|
||||||
is specified,
|
|
||||||
.Ar command
|
|
||||||
is executed.
|
|
||||||
If the mode change fails, the menu is redisplayed until cancellation or a
|
If the mode change fails, the menu is redisplayed until cancellation or a
|
||||||
successful mode change.
|
successful mode change.
|
||||||
|
If the
|
||||||
|
.Ar videomode
|
||||||
|
argument is specified in the
|
||||||
|
.Ar width Ns x Ns Ar height Ns x Ns Ar bits-per-pixel
|
||||||
|
format per
|
||||||
|
.Xr videomode 5 ,
|
||||||
|
then the video mode is immediately set non-interactively.
|
||||||
.Pp
|
.Pp
|
||||||
By default,
|
By default,
|
||||||
.Nm
|
.Nm
|
||||||
|
@ -142,17 +144,9 @@ inclusive.
|
||||||
.Nm
|
.Nm
|
||||||
exits with an exit status of 10 if the menu is quit, 11 if no modes are
|
exits with an exit status of 10 if the menu is quit, 11 if no modes are
|
||||||
available, 12 if no modes are available after filtering, 13 if the terminal has
|
available, 12 if no modes are available after filtering, 13 if the terminal has
|
||||||
no associated video devices, 127 if
|
no associated video devices, or 1 on any other error.
|
||||||
.Ar command
|
|
||||||
failed to run, or 1 on any other error.
|
|
||||||
If
|
|
||||||
.Nm
|
.Nm
|
||||||
changes the video mode successfully,
|
exits 0 if the video mode is successfully changed.
|
||||||
.Nm
|
|
||||||
exits with the exit status of
|
|
||||||
.Ar command
|
|
||||||
if specified,
|
|
||||||
or 0 otherwise.
|
|
||||||
.Sh SEE ALSO
|
.Sh SEE ALSO
|
||||||
.Xr chkblayout 1 ,
|
.Xr chkblayout 1 ,
|
||||||
.Xr dispmsg_issue 2 ,
|
.Xr dispmsg_issue 2 ,
|
||||||
|
|
|
@ -299,6 +299,17 @@ int main(int argc, char* argv[])
|
||||||
|
|
||||||
compact_arguments(&argc, &argv);
|
compact_arguments(&argc, &argv);
|
||||||
|
|
||||||
|
unsigned int xres = 0;
|
||||||
|
unsigned int yres = 0;
|
||||||
|
unsigned int bpp = 0;
|
||||||
|
if ( 2 <= argc )
|
||||||
|
{
|
||||||
|
if ( 2 < argc )
|
||||||
|
error(1, 0, "Unexpected extra operand");
|
||||||
|
if ( sscanf(argv[1], "%ux%ux%u", &xres, &yres, &bpp) != 3 )
|
||||||
|
error(1, 0, "Invalid video mode: %s", argv[1]);
|
||||||
|
}
|
||||||
|
|
||||||
int tty_fd = open("/dev/tty", O_RDWR);
|
int tty_fd = open("/dev/tty", O_RDWR);
|
||||||
if ( tty_fd < 0 )
|
if ( tty_fd < 0 )
|
||||||
error(1, errno, "/dev/tty");
|
error(1, errno, "/dev/tty");
|
||||||
|
@ -349,6 +360,34 @@ retry_pick_mode:
|
||||||
decided = false;
|
decided = false;
|
||||||
first_render = true;
|
first_render = true;
|
||||||
memset(&render_at, 0, sizeof(render_at));
|
memset(&render_at, 0, sizeof(render_at));
|
||||||
|
if ( 2 <= argc )
|
||||||
|
{
|
||||||
|
bool found_other = true;
|
||||||
|
size_t other_selection = 0;
|
||||||
|
for ( size_t i = 0; i < num_modes; i++ )
|
||||||
|
{
|
||||||
|
if ( modes[i].view_xres == xres &&
|
||||||
|
modes[i].view_yres == yres &&
|
||||||
|
modes[i].fb_format == bpp )
|
||||||
|
{
|
||||||
|
selection = i;
|
||||||
|
decided = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if ( modes[i].control & DISPMSG_CONTROL_OTHER_RESOLUTIONS )
|
||||||
|
{
|
||||||
|
found_other = true;
|
||||||
|
other_selection = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( !decided )
|
||||||
|
{
|
||||||
|
if ( found_other )
|
||||||
|
selection = other_selection;
|
||||||
|
else
|
||||||
|
error(1, 0, "No such available resolution: %s", argv[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
while ( !decided )
|
while ( !decided )
|
||||||
{
|
{
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
|
@ -495,10 +534,10 @@ retry_pick_mode:
|
||||||
struct dispmsg_crtc_mode mode = modes[selection];
|
struct dispmsg_crtc_mode mode = modes[selection];
|
||||||
if ( mode.control & DISPMSG_CONTROL_OTHER_RESOLUTIONS )
|
if ( mode.control & DISPMSG_CONTROL_OTHER_RESOLUTIONS )
|
||||||
{
|
{
|
||||||
uintmax_t req_bpp;
|
uintmax_t req_bpp = bpp;
|
||||||
uintmax_t req_width;
|
uintmax_t req_width = xres;
|
||||||
uintmax_t req_height;
|
uintmax_t req_height = yres;
|
||||||
while ( true )
|
while ( argc < 2 )
|
||||||
{
|
{
|
||||||
printf("Enter video mode [BPP x WIDTH x HEIGHT]: ");
|
printf("Enter video mode [BPP x WIDTH x HEIGHT]: ");
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
|
@ -527,11 +566,5 @@ retry_pick_mode:
|
||||||
goto retry_pick_mode;
|
goto retry_pick_mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( 1 < argc )
|
|
||||||
{
|
|
||||||
execvp(argv[1], argv + 1);
|
|
||||||
error(127, errno, "`%s'", argv[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
.Nd change user password
|
.Nd change user password
|
||||||
.Sh SYNOPSIS
|
.Sh SYNOPSIS
|
||||||
.Nm
|
.Nm
|
||||||
|
.Op Fl H
|
||||||
.Op Fl c Ar cipher
|
.Op Fl c Ar cipher
|
||||||
.Op Ar user
|
.Op Ar user
|
||||||
.Sh DESCRIPTION
|
.Sh DESCRIPTION
|
||||||
|
@ -19,6 +20,11 @@ The options are as follows:
|
||||||
.It Fl c Ar cipher
|
.It Fl c Ar cipher
|
||||||
Hash the password using the specified
|
Hash the password using the specified
|
||||||
.Ar cipher .
|
.Ar cipher .
|
||||||
|
.It Fl H
|
||||||
|
Read a password from the standard input and write the
|
||||||
|
.Xr crypt_newpass 3
|
||||||
|
hash to the standard output.
|
||||||
|
The password database is unchanged.
|
||||||
.El
|
.El
|
||||||
.Sh FILES
|
.Sh FILES
|
||||||
.Bl -tag -width "/etc/passwd" -compact
|
.Bl -tag -width "/etc/passwd" -compact
|
||||||
|
|
109
utils/passwd.c
109
utils/passwd.c
|
@ -34,79 +34,67 @@
|
||||||
static void password(char* buffer,
|
static void password(char* buffer,
|
||||||
size_t buffer_size,
|
size_t buffer_size,
|
||||||
const char* whose,
|
const char* whose,
|
||||||
const char* question)
|
const char* question,
|
||||||
|
bool require_tty)
|
||||||
{
|
{
|
||||||
if ( !isatty(0) )
|
bool is_tty = isatty(0);
|
||||||
|
if ( !require_tty && is_tty )
|
||||||
errx(1, "Input is not a terminal");
|
errx(1, "Input is not a terminal");
|
||||||
unsigned int termmode;
|
unsigned int termmode = 0;
|
||||||
gettermmode(0, &termmode);
|
if ( is_tty )
|
||||||
settermmode(0, termmode & ~TERMMODE_ECHO);
|
{
|
||||||
if ( whose )
|
gettermmode(0, &termmode);
|
||||||
printf("%s's ", whose);
|
settermmode(0, termmode & ~TERMMODE_ECHO);
|
||||||
printf("%s ", question);
|
if ( whose )
|
||||||
fflush(stdout);
|
printf("%s's ", whose);
|
||||||
fflush(stdin);
|
printf("%s ", question);
|
||||||
|
fflush(stdout);
|
||||||
|
fflush(stdin);
|
||||||
|
}
|
||||||
// TODO: This may leave a copy of the password in the stdio buffer.
|
// TODO: This may leave a copy of the password in the stdio buffer.
|
||||||
fgets(buffer, buffer_size, stdin);
|
fgets(buffer, buffer_size, stdin);
|
||||||
fflush(stdin);
|
if ( is_tty )
|
||||||
printf("\n");
|
{
|
||||||
|
fflush(stdin);
|
||||||
|
printf("\n");
|
||||||
|
settermmode(0, termmode);
|
||||||
|
}
|
||||||
size_t buffer_length = strlen(buffer);
|
size_t buffer_length = strlen(buffer);
|
||||||
if ( buffer_length && buffer[buffer_length-1] == '\n' )
|
if ( buffer_length && buffer[buffer_length-1] == '\n' )
|
||||||
buffer[--buffer_length] = '\0';
|
buffer[--buffer_length] = '\0';
|
||||||
settermmode(0, termmode);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void compact_arguments(int* argc, char*** argv)
|
|
||||||
{
|
|
||||||
for ( int i = 0; i < *argc; i++ )
|
|
||||||
{
|
|
||||||
while ( i < *argc && !(*argv)[i] )
|
|
||||||
{
|
|
||||||
for ( int n = i; n < *argc; n++ )
|
|
||||||
(*argv)[n] = (*argv)[n+1];
|
|
||||||
(*argc)--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char* argv[])
|
int main(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
const char* cipher = "blowfish,a";
|
const char* cipher = "blowfish,a";
|
||||||
|
bool hash_password = false;
|
||||||
|
|
||||||
for ( int i = 1; i < argc; i++ )
|
int opt;
|
||||||
|
while ( (opt = getopt(argc, argv, "c:H")) != -1 )
|
||||||
{
|
{
|
||||||
const char* arg = argv[i];
|
switch ( opt )
|
||||||
if ( arg[0] != '-' || !arg[1] )
|
|
||||||
continue;
|
|
||||||
argv[i] = NULL;
|
|
||||||
if ( !strcmp(arg, "--") )
|
|
||||||
break;
|
|
||||||
if ( arg[1] != '-' )
|
|
||||||
{
|
{
|
||||||
char c;
|
case 'c': cipher = optarg; break;
|
||||||
while ( (c = *++arg) ) switch ( c )
|
case 'H': hash_password = true; break;
|
||||||
{
|
default: return 1;
|
||||||
case 'c':
|
|
||||||
if ( !*(cipher = arg + 1) )
|
|
||||||
{
|
|
||||||
if ( i + 1 == argc )
|
|
||||||
errx(125, "option requires an argument -- 'c'");
|
|
||||||
cipher = argv[i+1];
|
|
||||||
argv[++i] = NULL;
|
|
||||||
}
|
|
||||||
arg = "c";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
errx(1, "unknown option -- '%c'", c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
errx(1, "unrecognized option: %s", arg);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
compact_arguments(&argc, &argv);
|
if ( hash_password )
|
||||||
|
{
|
||||||
|
if ( argc - optind )
|
||||||
|
errx(1, "Unexpected extra operand");
|
||||||
|
char pass[128];
|
||||||
|
password(pass, sizeof(pass), NULL, "Enter password (will not echo)",
|
||||||
|
false);
|
||||||
|
fgets(pass, sizeof(pass), stdin);
|
||||||
|
char newhash[128];
|
||||||
|
if ( crypt_newhash(pass, cipher, newhash, sizeof(newhash)) < 0 )
|
||||||
|
err(1, "crypt_newhash");
|
||||||
|
if ( printf("%s\n", newhash) < 0 || fflush(stdout) == EOF )
|
||||||
|
err(1, "stdout");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
uid_t my_uid = getuid();
|
uid_t my_uid = getuid();
|
||||||
char* my_username = getlogin();
|
char* my_username = getlogin();
|
||||||
|
@ -116,9 +104,9 @@ int main(int argc, char* argv[])
|
||||||
err(1, "stdup");
|
err(1, "stdup");
|
||||||
|
|
||||||
const char* username;
|
const char* username;
|
||||||
if ( argc <= 1 )
|
if ( argc - optind <= 1 )
|
||||||
username = my_username;
|
username = my_username;
|
||||||
else if ( argc <= 2 )
|
else if ( argc - optind <= 2 )
|
||||||
username = argv[1];
|
username = argv[1];
|
||||||
else
|
else
|
||||||
errx(1, "Unexpected extra operand");
|
errx(1, "Unexpected extra operand");
|
||||||
|
@ -139,16 +127,17 @@ int main(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
char current[128];
|
char current[128];
|
||||||
password(current, sizeof(current), pwd->pw_name,
|
password(current, sizeof(current), pwd->pw_name,
|
||||||
"current password (will not echo)");
|
"current password (will not echo)", true);
|
||||||
if ( crypt_checkpass(current, pwd->pw_passwd) < 0 )
|
if ( crypt_checkpass(current, pwd->pw_passwd) < 0 )
|
||||||
errx(1, "Wrong password for '%s'", pwd->pw_name);
|
errx(1, "Wrong password for '%s'", pwd->pw_name);
|
||||||
explicit_bzero(current, sizeof(current));
|
explicit_bzero(current, sizeof(current));
|
||||||
}
|
}
|
||||||
|
|
||||||
char first[128];
|
char first[128];
|
||||||
password(first, sizeof(first), NULL, "Enter new password (will not echo)");
|
password(first, sizeof(first), NULL, "Enter new password (will not echo)",
|
||||||
|
true);
|
||||||
char second[128];
|
char second[128];
|
||||||
password(second, sizeof(second), NULL, "Enter new password (again)");
|
password(second, sizeof(second), NULL, "Enter new password (again)", true);
|
||||||
if ( strcmp(first, second) != 0 )
|
if ( strcmp(first, second) != 0 )
|
||||||
errx(1, "Passwords don't match");
|
errx(1, "Passwords don't match");
|
||||||
explicit_bzero(second, sizeof(second));
|
explicit_bzero(second, sizeof(second));
|
||||||
|
|
Loading…
Reference in New Issue