/
niceSOFT
/
inetutils
Обзор
Документация
Войти
/
niceSOFT
/
inetutils
Код
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
src/hostname.c
425 строк
10 KB
Simon Josefsson
maint: Run 'make update-copyright'
20 янв 2026, 11:50
Не верифицирован
20 янв 2026, 11:50
1ce61cd
Код
Авторство
О чём код?
/* Copyright (C) 2008-2026 Free Software Foundation, Inc. This file is part of GNU Inetutils. GNU Inetutils is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. GNU Inetutils is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see `http://www.gnu.org/licenses/'. */ #include <config.h> #include <argp.h> #include <error.h> #include <netdb.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <netinet/in.h> #include <arpa/inet.h> #include <progname.h> #include "libinetutils.h" #include "xalloc.h" #include "xgethostname.h" #include "xgetdomainname.h" typedef struct { const char *hostname_file; char *hostname_new; short int hostname_alias; short int hostname_fqdn; short int hostname_ip_address; short int hostname_dns_domain; short int hostname_short; } hostname_arguments; static char *(*get_name_action) (void) = NULL; static int (*set_name_action) (const char *name, size_t size) = NULL; const char args_doc[] = "[NAME]"; const char doc[] = "Show or set the system's host name."; const char *program_authors[] = { "Debarshi Ray", NULL }; static struct argp_option argp_options[] = { #define GRP 0 {"aliases", 'a', NULL, 0, "alias names", GRP + 1}, {"domain", 'd', NULL, 0, "DNS domain name", GRP + 1}, {"file", 'F', "FILE", 0, "set host name or NIS domain name from FILE", GRP + 1}, {"fqdn", 'f', NULL, 0, "DNS host name or FQDN", GRP + 1}, {"long", 'f', NULL, OPTION_ALIAS, "DNS host name or FQDN", GRP + 1}, {"ip-addresses", 'i', NULL, 0, "addresses for the host name", GRP + 1}, {"short", 's', NULL, 0, "short host name", GRP + 1}, {"yp", 'y', NULL, 0, "NIS/YP domain name", GRP + 1}, {"nis", 0, NULL, OPTION_ALIAS, NULL, GRP + 1}, #undef GRP {NULL, 0, NULL, 0, NULL, 0} }; static error_t parse_opt (int key, char *arg, struct argp_state *state) { hostname_arguments *const args = (hostname_arguments * const) state->input; switch (key) { case 'a': get_name_action = xgethostname; args->hostname_alias = 1; break; case 'd': get_name_action = xgethostname; args->hostname_fqdn = 1; args->hostname_dns_domain = 1; break; case 'F': set_name_action = (void *) sethostname; args->hostname_file = arg; break; case 'f': get_name_action = xgethostname; args->hostname_fqdn = 1; break; case 'i': get_name_action = xgethostname; args->hostname_ip_address = 1; break; case 's': get_name_action = xgethostname; args->hostname_fqdn = 1; args->hostname_short = 1; break; case 'y': get_name_action = xgetdomainname; break; case ARGP_KEY_ARG: set_name_action = (void *) sethostname; args->hostname_new = strdup (arg); if (args->hostname_new == NULL) error (EXIT_FAILURE, errno, "strdup"); break; default: return ARGP_ERR_UNKNOWN; } return 0; } static struct argp argp = { argp_options, parse_opt, args_doc, doc, NULL, NULL, NULL }; static void get_name (const hostname_arguments * const args); static void set_name (const hostname_arguments * const args); static char *get_aliases (const char *const host_name); static char *get_fqdn (const char *const host_name); static char *get_ip_addresses (const char *const host_name); static char *get_dns_domain_name (const char *const host_name); static char *get_short_hostname (const char *const host_name); static char *parse_file (const char *const file_name); int main (int argc, char *argv[]) { hostname_arguments args; set_program_name (argv[0]); memset ((void *) &args, 0, sizeof (args)); /* Parse command line */ iu_argp_init ("hostname", program_authors); argp_parse (&argp, argc, argv, 0, NULL, (void *) &args); /* Set default action */ if (get_name_action == NULL && set_name_action == NULL) get_name_action = xgethostname; if (get_name_action == xgetdomainname || get_name_action == xgethostname) get_name (&args); else if ((void *) set_name_action == (void *) sethostname) set_name (&args); return 0; } static void get_name (const hostname_arguments *const args) { char *sname, *name; sname = (*get_name_action) (); if (!sname) error (EXIT_FAILURE, errno, "cannot determine name"); if (args->hostname_alias == 1) name = get_aliases (sname); else if (args->hostname_fqdn == 1) { name = get_fqdn (sname); if (args->hostname_dns_domain == 1 || args->hostname_short == 1) { /* Eliminate empty replies, as well as `(none)'. */ if (name && *name && *name != '(') { free (sname); sname = name; name = NULL; } else if (name && *name == '(') { free (name); name = NULL; } } if (args->hostname_dns_domain == 1) name = get_dns_domain_name (sname); else if (args->hostname_short == 1) name = get_short_hostname (sname); } else if (args->hostname_ip_address == 1) name = get_ip_addresses (sname); else { name = strdup (sname); if (name == NULL) error (EXIT_FAILURE, errno, "strdup"); } if (name && *name) puts (name); free (name); free (sname); return; } static void set_name (const hostname_arguments *const args) { char *hostname_new; int status; size_t size; if (args->hostname_file != NULL) hostname_new = parse_file (args->hostname_file); else hostname_new = args->hostname_new; size = hostname_new ? strlen (hostname_new) : 0; if (!size) error (EXIT_FAILURE, 0, "Empty hostname"); status = (*set_name_action) (hostname_new, size); if (status == -1) error (EXIT_FAILURE, errno, "sethostname"); free (hostname_new); return; } static char * get_aliases (const char *const host_name) { char *aliases; unsigned int count = 0; unsigned int i; unsigned int size = 256; struct hostent *ht; aliases = xmalloc (sizeof (char) * size); aliases[0] = '\0'; ht = gethostbyname (host_name); if (ht == NULL) strcpy (aliases, ""); /* Be honest about missing aliases. */ else { for (i = 0; ht->h_aliases[i] != NULL; i++) { /* Aliases should be blankspace separated. */ if (ht->h_aliases[i + 1] != NULL) count++; count += strlen (ht->h_aliases[i]); if (count >= size) { size *= 2; aliases = xrealloc (aliases, size); } strcat (aliases, ht->h_aliases[i]); strcat (aliases, " "); } } return aliases; } static char * get_fqdn (const char *const host_name) { char *fqdn; struct hostent *ht; ht = gethostbyname (host_name); if (ht == NULL) fqdn = strdup (host_name); /* Fall back to system name. */ else fqdn = strdup (ht->h_name); if (fqdn == NULL) error (EXIT_FAILURE, errno, "strdup"); return fqdn; } static char * get_ip_addresses (const char *const host_name) { char address[16]; char *addresses; unsigned int count = 0; unsigned int i; unsigned int size = 256; struct hostent *ht; addresses = xmalloc (sizeof (char) * size); addresses[0] = '\0'; ht = gethostbyname (host_name); if (ht == NULL) #if HAVE_HSTRERROR error (EXIT_FAILURE, 0, "gethostbyname: %s", hstrerror (h_errno)); #else strcpy (addresses, "(none)"); #endif else { for (i = 0; ht->h_addr_list[i] != NULL; i++) { inet_ntop (ht->h_addrtype, (void *) ht->h_addr_list[i], address, sizeof (address)); /* IP addresses should be blankspace separated. */ if (ht->h_addr_list[i + 1] != NULL) count++; count += strlen (address); if (count >= size) { size *= 2; addresses = xrealloc (addresses, size); } strcat (addresses, address); /* Insert a separating space character. */ if (ht->h_addr_list[i + 1] != NULL) strcat (addresses, " "); } } return addresses; } static char * get_dns_domain_name (const char *const host_name) { char *domain_name; const char *pos; pos = strchr (host_name, '.'); if (pos == NULL) domain_name = strdup ("(none)"); else domain_name = strdup (pos + 1); if (domain_name == NULL) error (EXIT_FAILURE, errno, "strdup"); return domain_name; } static char * get_short_hostname (const char *const host_name) { size_t size; char *short_hostname; const char *pos; pos = strchr (host_name, '.'); if (pos == NULL) short_hostname = strdup (host_name); else { size = pos - host_name; short_hostname = strndup (host_name, size); } if (short_hostname == NULL) error (EXIT_FAILURE, errno, "strdup"); return short_hostname; } static char * parse_file (const char *const file_name) { char *buffer = NULL; char *name = NULL; FILE *file; ssize_t nread; size_t size = 0; file = fopen (file_name, "r"); if (file == NULL) error (EXIT_FAILURE, errno, "fopen"); errno = 0; /* Portability issue! */ do { nread = getline (&buffer, &size, file); if (nread == -1) error (EXIT_FAILURE, errno, "getline%s", errno ? "" : ": No text"); if (buffer[0] != '#') { name = (char *) xmalloc (sizeof (char) * (nread + 1)); if (sscanf (buffer, "%s", name) == 1) break; free (name); name = NULL; } } while (feof (file) == 0); free (buffer); fclose (file); return name; }