1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
13 #include "alloc-util.h"
14 #include "architecture.h"
16 #include "bus-common-errors.h"
17 #include "bus-error.h"
18 #include "bus-locator.h"
19 #include "bus-map-properties.h"
20 #include "format-table.h"
21 #include "hostname-setup.h"
22 #include "hostname-util.h"
24 #include "main-func.h"
25 #include "parse-argument.h"
26 #include "pretty-print.h"
27 #include "socket-util.h"
28 #include "spawn-polkit-agent.h"
29 #include "terminal-util.h"
32 static bool arg_ask_password
= true;
33 static BusTransport arg_transport
= BUS_TRANSPORT_LOCAL
;
34 static char *arg_host
= NULL
;
35 static bool arg_transient
= false;
36 static bool arg_pretty
= false;
37 static bool arg_static
= false;
38 static JsonFormatFlags arg_json_format_flags
= JSON_FORMAT_OFF
;
40 typedef struct StatusInfo
{
42 const char *static_hostname
;
43 const char *pretty_hostname
;
44 const char *icon_name
;
46 const char *deployment
;
48 const char *kernel_name
;
49 const char *kernel_release
;
50 const char *os_pretty_name
;
51 const char *os_cpe_name
;
52 usec_t os_support_end
;
53 const char *virtualization
;
54 const char *architecture
;
56 const char *hardware_vendor
;
57 const char *hardware_model
;
58 const char *firmware_version
;
60 sd_id128_t machine_id
;
62 const char *hardware_serial
;
63 sd_id128_t product_uuid
;
67 static const char* chassis_string_to_glyph(const char *chassis
) {
68 if (streq_ptr(chassis
, "laptop"))
69 return u8
"💻"; /* Personal Computer */
70 if (streq_ptr(chassis
, "desktop"))
71 return u8
"🖥️"; /* Desktop Computer */
72 if (streq_ptr(chassis
, "server"))
73 return u8
"🖳"; /* Old Personal Computer */
74 if (streq_ptr(chassis
, "tablet"))
75 return u8
"具"; /* Ideograph tool, implement; draw up, write, looks vaguely tabletty */
76 if (streq_ptr(chassis
, "watch"))
77 return u8
"⌚"; /* Watch */
78 if (streq_ptr(chassis
, "handset"))
79 return u8
"🕻"; /* Left Hand Telephone Receiver */
80 if (streq_ptr(chassis
, "vm"))
81 return u8
"🖴"; /* Hard disk */
82 if (streq_ptr(chassis
, "container"))
83 return u8
"☐"; /* Ballot Box */
87 static const char *os_support_end_color(usec_t n
, usec_t eol
) {
90 /* If the end of support is over, color output in red. If only a month is left, color output in
91 * yellow. If more than a year is left, color green. In between just show in regular color. */
94 return ANSI_HIGHLIGHT_RED
;
96 if (left
< USEC_PER_MONTH
)
97 return ANSI_HIGHLIGHT_YELLOW
;
98 if (left
> USEC_PER_YEAR
)
99 return ANSI_HIGHLIGHT_GREEN
;
104 static int print_status_info(StatusInfo
*i
) {
105 _cleanup_(table_unrefp
) Table
*table
= NULL
;
111 table
= table_new_vertical();
115 assert_se(cell
= table_get_cell(table
, 0, 0));
116 (void) table_set_ellipsize_percent(table
, cell
, 100);
118 table_set_ersatz_string(table
, TABLE_ERSATZ_UNSET
);
120 r
= table_add_many(table
,
121 TABLE_FIELD
, "Static hostname",
122 TABLE_STRING
, i
->static_hostname
);
124 return table_log_add_error(r
);
126 if (!isempty(i
->pretty_hostname
) &&
127 !streq_ptr(i
->pretty_hostname
, i
->static_hostname
)) {
128 r
= table_add_many(table
,
129 TABLE_FIELD
, "Pretty hostname",
130 TABLE_STRING
, i
->pretty_hostname
);
132 return table_log_add_error(r
);
135 if (!isempty(i
->hostname
) &&
136 !streq_ptr(i
->hostname
, i
->static_hostname
)) {
137 r
= table_add_many(table
,
138 TABLE_FIELD
, "Transient hostname",
139 TABLE_STRING
, i
->hostname
);
141 return table_log_add_error(r
);
144 if (!isempty(i
->icon_name
)) {
145 r
= table_add_many(table
,
146 TABLE_FIELD
, "Icon name",
147 TABLE_STRING
, i
->icon_name
);
149 return table_log_add_error(r
);
152 if (!isempty(i
->chassis
)) {
153 /* Possibly add a pretty symbol. Let's not bother with non-unicode fallbacks, because this is
154 * just a prettification and we can't really express this with ASCII anyway. */
155 const char *v
= chassis_string_to_glyph(i
->chassis
);
157 v
= strjoina(i
->chassis
, " ", v
);
159 r
= table_add_many(table
,
160 TABLE_FIELD
, "Chassis",
161 TABLE_STRING
, v
?: i
->chassis
);
163 return table_log_add_error(r
);
166 if (!isempty(i
->deployment
)) {
167 r
= table_add_many(table
,
168 TABLE_FIELD
, "Deployment",
169 TABLE_STRING
, i
->deployment
);
171 return table_log_add_error(r
);
174 if (!isempty(i
->location
)) {
175 r
= table_add_many(table
,
176 TABLE_FIELD
, "Location",
177 TABLE_STRING
, i
->location
);
179 return table_log_add_error(r
);
182 if (!sd_id128_is_null(i
->machine_id
)) {
183 r
= table_add_many(table
,
184 TABLE_FIELD
, "Machine ID",
185 TABLE_ID128
, i
->machine_id
);
187 return table_log_add_error(r
);
190 if (!sd_id128_is_null(i
->boot_id
)) {
191 r
= table_add_many(table
,
192 TABLE_FIELD
, "Boot ID",
193 TABLE_ID128
, i
->boot_id
);
195 return table_log_add_error(r
);
198 if (!sd_id128_is_null(i
->product_uuid
)) {
199 r
= table_add_many(table
,
200 TABLE_FIELD
, "Product UUID",
201 TABLE_UUID
, i
->product_uuid
);
203 return table_log_add_error(r
);
206 if (i
->vsock_cid
!= VMADDR_CID_ANY
) {
207 r
= table_add_many(table
,
208 TABLE_FIELD
, "AF_VSOCK CID",
209 TABLE_UINT32
, i
->vsock_cid
);
211 return table_log_add_error(r
);
214 if (!isempty(i
->virtualization
)) {
215 r
= table_add_many(table
,
216 TABLE_FIELD
, "Virtualization",
217 TABLE_STRING
, i
->virtualization
);
219 return table_log_add_error(r
);
222 if (!isempty(i
->os_pretty_name
)) {
223 r
= table_add_many(table
,
224 TABLE_FIELD
, "Operating System",
225 TABLE_STRING
, i
->os_pretty_name
,
226 TABLE_SET_URL
, i
->home_url
);
228 return table_log_add_error(r
);
231 if (!isempty(i
->os_cpe_name
)) {
232 r
= table_add_many(table
,
233 TABLE_FIELD
, "CPE OS Name",
234 TABLE_STRING
, i
->os_cpe_name
);
236 return table_log_add_error(r
);
239 if (i
->os_support_end
!= USEC_INFINITY
) {
240 usec_t n
= now(CLOCK_REALTIME
);
242 r
= table_add_many(table
,
243 TABLE_FIELD
, "OS Support End",
244 TABLE_TIMESTAMP_DATE
, i
->os_support_end
,
245 TABLE_FIELD
, n
< i
->os_support_end
? "OS Support Remaining" : "OS Support Expired",
246 TABLE_TIMESPAN_DAY
, n
< i
->os_support_end
? i
->os_support_end
- n
: n
- i
->os_support_end
,
247 TABLE_SET_COLOR
, os_support_end_color(n
, i
->os_support_end
));
249 return table_log_add_error(r
);
252 if (!isempty(i
->kernel_name
) && !isempty(i
->kernel_release
)) {
255 v
= strjoina(i
->kernel_name
, " ", i
->kernel_release
);
256 r
= table_add_many(table
,
257 TABLE_FIELD
, "Kernel",
260 return table_log_add_error(r
);
263 if (!isempty(i
->architecture
)) {
264 r
= table_add_many(table
,
265 TABLE_FIELD
, "Architecture",
266 TABLE_STRING
, i
->architecture
);
268 return table_log_add_error(r
);
271 if (!isempty(i
->hardware_vendor
)) {
272 r
= table_add_many(table
,
273 TABLE_FIELD
, "Hardware Vendor",
274 TABLE_STRING
, i
->hardware_vendor
);
276 return table_log_add_error(r
);
279 if (!isempty(i
->hardware_model
)) {
280 r
= table_add_many(table
,
281 TABLE_FIELD
, "Hardware Model",
282 TABLE_STRING
, i
->hardware_model
);
284 return table_log_add_error(r
);
287 if (!isempty(i
->hardware_serial
)) {
288 r
= table_add_many(table
,
289 TABLE_FIELD
, "Hardware Serial",
290 TABLE_STRING
, i
->hardware_serial
);
292 return table_log_add_error(r
);
295 if (!isempty(i
->firmware_version
)) {
296 r
= table_add_many(table
,
297 TABLE_FIELD
, "Firmware Version",
298 TABLE_STRING
, i
->firmware_version
);
300 return table_log_add_error(r
);
303 if (timestamp_is_set(i
->firmware_date
)) {
304 usec_t n
= now(CLOCK_REALTIME
);
306 r
= table_add_many(table
,
307 TABLE_FIELD
, "Firmware Date",
308 TABLE_TIMESTAMP_DATE
, i
->firmware_date
);
310 return table_log_add_error(r
);
312 if (i
->firmware_date
< n
) {
313 r
= table_add_many(table
,
314 TABLE_FIELD
, "Firmware Age",
315 TABLE_TIMESPAN_DAY
, n
- i
->firmware_date
,
316 TABLE_SET_COLOR
, n
- i
->firmware_date
> USEC_PER_YEAR
*2 ? ANSI_HIGHLIGHT_YELLOW
: NULL
);
318 return table_log_add_error(r
);
322 r
= table_print(table
, NULL
);
324 return table_log_print_error(r
);
329 static int get_one_name(sd_bus
*bus
, const char* attr
, char **ret
) {
330 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
331 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
338 /* This obtains one string property, and copy it if 'ret' is set, or print it otherwise. */
340 r
= bus_get_property(bus
, bus_hostname
, attr
, &error
, &reply
, "s");
342 return log_error_errno(r
, "Could not get property: %s", bus_error_message(&error
, r
));
344 r
= sd_bus_message_read(reply
, "s", &s
);
346 return bus_log_parse_error(r
);
362 static int show_all_names(sd_bus
*bus
) {
364 .vsock_cid
= VMADDR_CID_ANY
,
367 static const struct bus_properties_map hostname_map
[] = {
368 { "Hostname", "s", NULL
, offsetof(StatusInfo
, hostname
) },
369 { "StaticHostname", "s", NULL
, offsetof(StatusInfo
, static_hostname
) },
370 { "PrettyHostname", "s", NULL
, offsetof(StatusInfo
, pretty_hostname
) },
371 { "IconName", "s", NULL
, offsetof(StatusInfo
, icon_name
) },
372 { "Chassis", "s", NULL
, offsetof(StatusInfo
, chassis
) },
373 { "Deployment", "s", NULL
, offsetof(StatusInfo
, deployment
) },
374 { "Location", "s", NULL
, offsetof(StatusInfo
, location
) },
375 { "KernelName", "s", NULL
, offsetof(StatusInfo
, kernel_name
) },
376 { "KernelRelease", "s", NULL
, offsetof(StatusInfo
, kernel_release
) },
377 { "OperatingSystemPrettyName", "s", NULL
, offsetof(StatusInfo
, os_pretty_name
) },
378 { "OperatingSystemCPEName", "s", NULL
, offsetof(StatusInfo
, os_cpe_name
) },
379 { "OperatingSystemSupportEnd", "t", NULL
, offsetof(StatusInfo
, os_support_end
) },
380 { "HomeURL", "s", NULL
, offsetof(StatusInfo
, home_url
) },
381 { "HardwareVendor", "s", NULL
, offsetof(StatusInfo
, hardware_vendor
) },
382 { "HardwareModel", "s", NULL
, offsetof(StatusInfo
, hardware_model
) },
383 { "FirmwareVersion", "s", NULL
, offsetof(StatusInfo
, firmware_version
) },
384 { "FirmwareDate", "t", NULL
, offsetof(StatusInfo
, firmware_date
) },
385 { "MachineID", "ay", bus_map_id128
, offsetof(StatusInfo
, machine_id
) },
386 { "BootID", "ay", bus_map_id128
, offsetof(StatusInfo
, boot_id
) },
387 { "VSockCID", "u", NULL
, offsetof(StatusInfo
, vsock_cid
) },
390 { "Virtualization", "s", NULL
, offsetof(StatusInfo
, virtualization
) },
391 { "Architecture", "s", NULL
, offsetof(StatusInfo
, architecture
) },
395 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*host_message
= NULL
, *manager_message
= NULL
;
396 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
399 r
= bus_map_all_properties(bus
,
400 "org.freedesktop.hostname1",
401 "/org/freedesktop/hostname1",
408 return log_error_errno(r
, "Failed to query system properties: %s", bus_error_message(&error
, r
));
410 r
= bus_map_all_properties(bus
,
411 "org.freedesktop.systemd1",
412 "/org/freedesktop/systemd1",
419 return log_error_errno(r
, "Failed to query system properties: %s", bus_error_message(&error
, r
));
421 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*product_uuid_reply
= NULL
;
422 r
= bus_call_method(bus
,
430 log_full_errno(sd_bus_error_has_names(
432 BUS_ERROR_NO_PRODUCT_UUID
,
433 SD_BUS_ERROR_INTERACTIVE_AUTHORIZATION_REQUIRED
,
434 SD_BUS_ERROR_UNKNOWN_METHOD
) ? LOG_DEBUG
: LOG_WARNING
,
435 r
, "Failed to query product UUID, ignoring: %s", bus_error_message(&error
, r
));
436 sd_bus_error_free(&error
);
438 r
= bus_message_read_id128(product_uuid_reply
, &info
.product_uuid
);
440 return bus_log_parse_error(r
);
443 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*hardware_serial_reply
= NULL
;
444 r
= bus_call_method(bus
,
448 &hardware_serial_reply
,
451 log_full_errno(sd_bus_error_has_names(
453 BUS_ERROR_NO_HARDWARE_SERIAL
,
454 SD_BUS_ERROR_INTERACTIVE_AUTHORIZATION_REQUIRED
,
455 SD_BUS_ERROR_UNKNOWN_METHOD
) ? LOG_DEBUG
: LOG_WARNING
,
456 r
, "Failed to query hardware serial, ignoring: %s", bus_error_message(&error
, r
));
458 r
= sd_bus_message_read_basic(hardware_serial_reply
, 's', &info
.hardware_serial
);
460 return bus_log_parse_error(r
);
463 /* For older version of hostnamed. */
465 if (sd_id128_is_null(info
.machine_id
))
466 (void) sd_id128_get_machine(&info
.machine_id
);
467 if (sd_id128_is_null(info
.boot_id
))
468 (void) sd_id128_get_boot(&info
.boot_id
);
471 return print_status_info(&info
);
474 static int get_hostname_based_on_flag(sd_bus
*bus
) {
477 if (!!arg_static
+ !!arg_pretty
+ !!arg_transient
> 1)
478 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
479 "Cannot query more than one name type at a time");
481 attr
= arg_pretty
? "PrettyHostname" :
482 arg_static
? "StaticHostname" : "Hostname";
484 return get_one_name(bus
, attr
, NULL
);
487 static int show_status(int argc
, char **argv
, void *userdata
) {
488 sd_bus
*bus
= userdata
;
491 if (arg_json_format_flags
!= JSON_FORMAT_OFF
) {
492 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
493 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
494 _cleanup_(json_variant_unrefp
) JsonVariant
*v
= NULL
;
495 const char *text
= NULL
;
497 r
= bus_call_method(bus
, bus_hostname
, "Describe", &error
, &reply
, NULL
);
499 return log_error_errno(r
, "Could not get description: %s", bus_error_message(&error
, r
));
501 r
= sd_bus_message_read(reply
, "s", &text
);
503 return bus_log_parse_error(r
);
505 r
= json_parse(text
, 0, &v
, NULL
, NULL
);
507 return log_error_errno(r
, "Failed to parse JSON: %m");
509 json_variant_dump(v
, arg_json_format_flags
, NULL
, NULL
);
513 if (arg_pretty
|| arg_static
|| arg_transient
)
514 return get_hostname_based_on_flag(bus
);
516 return show_all_names(bus
);
520 static int set_simple_string_internal(sd_bus
*bus
, sd_bus_error
*error
, const char *target
, const char *method
, const char *value
) {
521 _cleanup_(sd_bus_error_free
) sd_bus_error e
= SD_BUS_ERROR_NULL
;
524 polkit_agent_open_if_enabled(arg_transport
, arg_ask_password
);
529 r
= bus_call_method(bus
, bus_hostname
, method
, error
, NULL
, "sb", value
, arg_ask_password
);
531 return log_error_errno(r
, "Could not set %s: %s", target
, bus_error_message(error
, r
));
536 static int set_simple_string(sd_bus
*bus
, const char *target
, const char *method
, const char *value
) {
537 return set_simple_string_internal(bus
, NULL
, target
, method
, value
);
540 static int set_hostname(int argc
, char **argv
, void *userdata
) {
541 _cleanup_free_
char *h
= NULL
;
542 const char *hostname
= argv
[1];
543 sd_bus
*bus
= userdata
;
544 bool implicit
= false, show_hint
= false;
547 if (!arg_pretty
&& !arg_static
&& !arg_transient
)
548 arg_pretty
= arg_static
= arg_transient
= implicit
= true;
550 if (!implicit
&& !arg_static
&& arg_transient
) {
551 _cleanup_free_
char *source
= NULL
;
553 r
= get_one_name(bus
, "HostnameSource", &source
);
557 if (hostname_source_from_string(source
) == HOSTNAME_STATIC
)
558 log_info("Hint: static hostname is already set, so the specified transient hostname will not be used.");
562 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
565 /* If the passed hostname is already valid, then assume the user doesn't know anything about pretty
566 * hostnames, so let's unset the pretty hostname, and just set the passed hostname as static/dynamic
568 if (implicit
&& hostname_is_valid(hostname
, VALID_HOSTNAME_TRAILING_DOT
))
569 p
= ""; /* No pretty hostname (as it is redundant), just a static one */
571 p
= hostname
; /* Use the passed name as pretty hostname */
573 r
= set_simple_string_internal(bus
, &error
, "pretty hostname", "SetPrettyHostname", p
);
576 sd_bus_error_has_names(&error
,
577 BUS_ERROR_FILE_IS_PROTECTED
,
578 BUS_ERROR_READ_ONLY_FILESYSTEM
)) {
585 /* Now that we set the pretty hostname, let's clean up the parameter and use that as static
586 * hostname. If the hostname was already valid as static hostname, this will only chop off the trailing
587 * dot if there is one. If it was not valid, then it will be made fully valid by truncating, dropping
588 * multiple dots, and dropping weird chars. Note that we clean the name up only if we also are
589 * supposed to set the pretty name. If the pretty name is not being set we assume the user knows what
590 * they are doing and pass the name as-is. */
591 h
= strdup(hostname
);
595 hostname
= hostname_cleanup(h
); /* Use the cleaned up name as static hostname */
599 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
601 r
= set_simple_string_internal(bus
, &error
, "static hostname", "SetStaticHostname", hostname
);
604 sd_bus_error_has_names(&error
,
605 BUS_ERROR_FILE_IS_PROTECTED
,
606 BUS_ERROR_READ_ONLY_FILESYSTEM
)) {
615 r
= set_simple_string(bus
, "transient hostname", "SetHostname", hostname
);
621 log_info("Hint: use --transient option when /etc/machine-info or /etc/hostname cannot be modified (e.g. located in read-only filesystem).");
626 static int get_or_set_hostname(int argc
, char **argv
, void *userdata
) {
627 return argc
== 1 ? get_hostname_based_on_flag(userdata
) :
628 set_hostname(argc
, argv
, userdata
);
631 static int get_or_set_icon_name(int argc
, char **argv
, void *userdata
) {
632 return argc
== 1 ? get_one_name(userdata
, "IconName", NULL
) :
633 set_simple_string(userdata
, "icon", "SetIconName", argv
[1]);
636 static int get_or_set_chassis(int argc
, char **argv
, void *userdata
) {
637 return argc
== 1 ? get_one_name(userdata
, "Chassis", NULL
) :
638 set_simple_string(userdata
, "chassis", "SetChassis", argv
[1]);
641 static int get_or_set_deployment(int argc
, char **argv
, void *userdata
) {
642 return argc
== 1 ? get_one_name(userdata
, "Deployment", NULL
) :
643 set_simple_string(userdata
, "deployment", "SetDeployment", argv
[1]);
646 static int get_or_set_location(int argc
, char **argv
, void *userdata
) {
647 return argc
== 1 ? get_one_name(userdata
, "Location", NULL
) :
648 set_simple_string(userdata
, "location", "SetLocation", argv
[1]);
651 static int help(void) {
652 _cleanup_free_
char *link
= NULL
;
655 r
= terminal_urlify_man("hostnamectl", "1", &link
);
659 printf("%s [OPTIONS...] COMMAND ...\n\n"
660 "%sQuery or change system hostname.%s\n"
662 " status Show current hostname settings\n"
663 " hostname [NAME] Get/set system hostname\n"
664 " icon-name [NAME] Get/set icon name for host\n"
665 " chassis [NAME] Get/set chassis type for host\n"
666 " deployment [NAME] Get/set deployment environment for host\n"
667 " location [NAME] Get/set location for host\n"
669 " -h --help Show this help\n"
670 " --version Show package version\n"
671 " --no-ask-password Do not prompt for password\n"
672 " -H --host=[USER@]HOST Operate on remote host\n"
673 " -M --machine=CONTAINER Operate on local container\n"
674 " --transient Only set transient hostname\n"
675 " --static Only set static hostname\n"
676 " --pretty Only set pretty hostname\n"
677 " --json=pretty|short|off\n"
678 " Generate JSON output\n"
679 " -j Same as --json=pretty on tty, --json=short otherwise\n"
680 "\nSee the %s for details.\n",
681 program_invocation_short_name
,
689 static int verb_help(int argc
, char **argv
, void *userdata
) {
693 static int parse_argv(int argc
, char *argv
[]) {
704 static const struct option options
[] = {
705 { "help", no_argument
, NULL
, 'h' },
706 { "version", no_argument
, NULL
, ARG_VERSION
},
707 { "transient", no_argument
, NULL
, ARG_TRANSIENT
},
708 { "static", no_argument
, NULL
, ARG_STATIC
},
709 { "pretty", no_argument
, NULL
, ARG_PRETTY
},
710 { "host", required_argument
, NULL
, 'H' },
711 { "machine", required_argument
, NULL
, 'M' },
712 { "no-ask-password", no_argument
, NULL
, ARG_NO_ASK_PASSWORD
},
713 { "json", required_argument
, NULL
, ARG_JSON
},
722 while ((c
= getopt_long(argc
, argv
, "hH:M:j", options
, NULL
)) >= 0)
733 arg_transport
= BUS_TRANSPORT_REMOTE
;
738 arg_transport
= BUS_TRANSPORT_MACHINE
;
743 arg_transient
= true;
754 case ARG_NO_ASK_PASSWORD
:
755 arg_ask_password
= false;
759 r
= parse_json_argument(optarg
, &arg_json_format_flags
);
766 arg_json_format_flags
= JSON_FORMAT_PRETTY_AUTO
|JSON_FORMAT_COLOR_AUTO
;
773 assert_not_reached();
779 static int hostnamectl_main(sd_bus
*bus
, int argc
, char *argv
[]) {
781 static const Verb verbs
[] = {
782 { "status", VERB_ANY
, 1, VERB_DEFAULT
, show_status
},
783 { "hostname", VERB_ANY
, 2, 0, get_or_set_hostname
},
784 { "set-hostname", 2, 2, 0, get_or_set_hostname
}, /* obsolete */
785 { "icon-name", VERB_ANY
, 2, 0, get_or_set_icon_name
},
786 { "set-icon-name", 2, 2, 0, get_or_set_icon_name
}, /* obsolete */
787 { "chassis", VERB_ANY
, 2, 0, get_or_set_chassis
},
788 { "set-chassis", 2, 2, 0, get_or_set_chassis
}, /* obsolete */
789 { "deployment", VERB_ANY
, 2, 0, get_or_set_deployment
},
790 { "set-deployment", 2, 2, 0, get_or_set_deployment
}, /* obsolete */
791 { "location", VERB_ANY
, 2, 0, get_or_set_location
},
792 { "set-location", 2, 2, 0, get_or_set_location
}, /* obsolete */
793 { "help", VERB_ANY
, VERB_ANY
, 0, verb_help
}, /* Not documented, but supported since it is created. */
797 return dispatch_verb(argc
, argv
, verbs
, bus
);
800 static int run(int argc
, char *argv
[]) {
801 _cleanup_(sd_bus_flush_close_unrefp
) sd_bus
*bus
= NULL
;
804 setlocale(LC_ALL
, "");
807 r
= parse_argv(argc
, argv
);
811 r
= bus_connect_transport(arg_transport
, arg_host
, RUNTIME_SCOPE_SYSTEM
, &bus
);
813 return bus_log_connect_error(r
, arg_transport
);
815 return hostnamectl_main(bus
, argc
, argv
);
818 DEFINE_MAIN_FUNCTION(run
);