summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hostname/hostname.c62
1 files changed, 59 insertions, 3 deletions
diff --git a/hostname/hostname.c b/hostname/hostname.c
index 3dc1224..d19e4b8 100644
--- a/hostname/hostname.c
+++ b/hostname/hostname.c
@@ -18,6 +18,18 @@
#include <sys/socket.h>
#include <netdb.h>
+/* open, read, close */
+#include <sys/stat.h>
+#include <fcntl.h>
+
+int sethostname(const char *value,
+#ifdef __linux__
+ size_t
+#else
+ int
+#endif
+ namelen);
+
int do_print_nodename(bool verbose, bool domain, bool fqdn, bool address, bool shorten)
{
long hostname = sysconf(_SC_HOST_NAME_MAX);
@@ -113,9 +125,53 @@ int do_print_nodename(bool verbose, bool domain, bool fqdn, bool address, bool s
int do_set_nodename(bool file, const char *value)
{
- fprintf(stderr, "setting nodenamet to %s %s not yet supported\n",
- (file ? "contents of file" : "literal string"), value);
- return 1;
+ size_t len;
+
+ if(file)
+ {
+ /* This is insane. There is no validation whatsoever.
+ * However, strace on net-tools hostname(1) shows this to be
+ * the exact algorithm used, so... */
+ char buf[1024];
+ int fildes = open(value, O_RDONLY);
+ ssize_t result = 0;
+
+ if(fildes == -1)
+ {
+ perror("open");
+ return EXIT_FAILURE;
+ }
+
+ while(true)
+ {
+ char *curr = buf;
+ result = read(fildes, buf, sizeof buf);
+ switch(result)
+ {
+ case -1:
+ perror("read");
+ close(fildes);
+ return EXIT_FAILURE;
+ case 0:
+ close(fildes);
+ return EXIT_SUCCESS;
+ }
+ do
+ {
+ len = result;
+ char *pos = strchr(curr, '\n');
+ if(pos)
+ {
+ len = pos - curr;
+ }
+ sethostname(curr, (len > 63) ? 63 : len);
+ } while((curr = strchr(curr, '\n')));
+ }
+ }
+
+ len = strlen(value);
+ sethostname(value, len);
+ return EXIT_SUCCESS;
}
void usage()