talideon.com

...and then she cut it open...

February 5, 2007 at 2:18PM Getting a list of hostnames associated with a host.

I needed something for a shell script over the weekend to get a list the primary hostname and any aliases, all of them, I couldn’t think of any commands, and hostname doesn’t do quite what I wanted, so I knocked this out. It might be of use to somebody:

/*
 * hostnames.c
 * by Keith Gaughan (http://talideon.com/)
 *
 * Lists all the names associated with a given host (or the current one if
 * non is specified.
 *
 * Copyleft (k) Keith Gaughan, 2007.
 * All rights reversed. Do what you will with it, just don't come crying to
 * me if something bad happens.
 *
 * To compile, type: gcc -lc -Os -Wall -o hostnames hostnames.c
 * You might need an implementation of strlcpy().
 */

#include <stdio.h>
#include <unistd.h>
#include <netdb.h>
#include <string.h>

/* Sigh... */
#ifndef FALSE
#define FALSE 0
#define TRUE (!(FALSE))
#endif

static int quiet = FALSE;

static void echo(char* key, char* val) {
    if (quiet) {
        printf("%s\n", val);
    } else {
        printf("%s: %s\n", key, val);
    }
}

int main(int argc, char** argv) {
    char buf[250];
    struct hostent* h;
    char** aliases;
    int arg = 1;

    /* Check for quiet flag */
    if (argc > 1 && strcmp(argv[arg], "-q") == 0) {
        argc--;
        arg++;
        quiet = TRUE;
    }

    if (argc > 1) {
        /* Use the one passed in on the command line. */
        strlcpy(buf, argv[arg], sizeof buf);
    } else if (gethostname(buf, sizeof buf) != 0) {
        perror("Could not read host name");
        return 1;
    }

    h = gethostbyname(buf);
    if (h == NULL) {
        herror("Could not fetch host details");
        return 2;
    }
    echo("Official hostname", h->h_name);
    aliases = h->h_aliases;
    while (*aliases) {
        echo("Alias", *aliases);
        aliases++;
    }

    return 0;
}

Watch for the use of strlcpy(): you’ll need a copy, Linux boy.

Technorati Search Technorati Search Irish Bloggers

Comments

1 On February 6, 2007 at 13:38, Revence 27 wrote:

You also use those global vars to toggle states? May concurrency eat you raw.

Otherwise, I love the look of the code. And I hate that you do ... wait, lemme talk. I’m not getting billed. And it’s a long time since I flamed witcha.

Presenting, bit’s I’d re-write or copy (you’ll have to clean this up - Textuality is quite elusive, and no preview): #define TRUE (!(FALSE)) Eh! Neat! But I like this better: #if !defined(cplusplus) && !defined(REVBOOLDEF) #define REVBOOLDEF #define false 0 #define true (!(false)) / Shameless plagiary!/ #endif

No global vars. Concurrency can massacre you.

/ In check for quiet flag, I’d .../ if (argc > 1 && !strcmp(argv[arg], “-q”)) / ... /; It’s good for freaking little ones out into running over to the shop for you, after they’ve peered over your shoulder ...

Still at the check for the quiet flag, after the if block ... else printf(”Usage:nhostname [something]n”); You don’t lose too many calories, and it keeps being helpful even to the kinds of people who would never use it.

2 On February 6, 2007 at 13:40, Revence 27 wrote:

You also use those global vars to toggle states? May concurrency eat you raw.

Otherwise, I love the look of the code. And I hate that you do ... wait, lemme talk. I’m not getting billed. And it’s a long time since I flamed witcha.

Presenting, bit’s I’d re-write or copy (you’ll have to clean this up - Textuality is quite elusive, and no preview): #define TRUE (!(FALSE)) Eh! Neat! But I like this better: #if !defined(cplusplus) && !defined(REVBOOLDEF) #define REVBOOLDEF #define false 0 #define true (!(false)) / Shameless plagiary!/ #endif

No global vars. Concurrency can massacre you.

/ In check for quiet flag, I’d .../ if (argc > 1 && !strcmp(argv[arg], “-q”)) / ... /; It’s good for freaking little ones out into running over to the shop for you, after they’ve peered over your shoulder ...

Still at the check for the quiet flag, after the if block ... else printf(”Usage:nhostname [something]n”); You don’t lose too many calories, and it keeps being helpful even to the kinds of people who would never use it.

3 On February 7, 2007 at 9:28, Keith wrote:

Textuality is hardly all that hard. You just start preformatted blocks with =pre and end them with =/pre, just as stated in the documentation.

Global variables are just fine in this state. It’s global state, and considering that (a) the app is single threaded and (b) it’s C and there’s no way to encapsulate global state.

On the topic of how the boolean is defined, remember that this is C and traditionally in C, constants are given uppercase names and anyway, the way you’re doing it, you’d also have to give a typedef for bool or you’ll get warnings when you compile the code with a C++ compiler. I’m not doing anything different from the code for just about any C program written over the last 35 years.

That little bit for checking for the quiet flag could be bundled up in a macro, but I didn’t see the point, hence the comment.

Your else showing usage info doesn’t make sense. -q isn’t a required flag. Your way of doing things, the message would get shown regardless of whether it’s justified or not. Now, if there was a help flag, it’d make sense to check for that and print the usage info, but there isn’t. And anyway, you’re asking me to write usage info out to stdout rather than stderr, which is a big no-no.

Note to self: catch duplicate posts.

4 On February 7, 2007 at 10:10, Revence 27 wrote:

Yeah, catch duplicates. I thought it is one way you trap spam.

Okay, it’s just Textuality si too divorced from the usual tomfoolery I usually do. But ‘tis powerful, as well. I once knew it better than you. Then you blacked out. Think of a preview button. A few more lines ...

Yeah, on the TRUE/FALSE thing ... I like my non-C stuff to lose itself into my C++ stuff. Without being C++. I mean, C-99 has bool. So, by putting it there, I am closer to C-99 (in ANSI ‘89). Just thought it’d look neat. It’s neat, hell! I hate tradition, pal. And that stuff, on top of looking a hell of a lot more intelligible and neater, it is good with C++. Very coherent.

Yeah, but if you haven’t yet written checkforconcurrencyrisk.pl, mine doesn’t differentiate between what will be end up as a.out and what will end up as lib.o. So, global vars are forbidden everywhere. If you can’t pass them to funcs, the ideology says, you can’t be trusted with them in global.

Well, the else makes sense, because you don’t deal with many args. Just one, which should be -q’ or the hostname. More than that can throw an error, if it wants.

But this was neat, nonetheless. Undeniably. Did you send for your Solaris 10? So I may be putting the FreeBSD things on the hind for a while ...

5 On February 7, 2007 at 10:13, Revence 27 wrote:

Oh, frig! I messed it up again! Please, Gaga, remove this bugger, and the duplicate, and clean up behind me, pleease! I promise to recite the Textuality manual before I format again. Mwa! Kiss for being good.

6 On February 7, 2007 at 14:27, Keith wrote:

Problem is, C99 isn’t widely implemented, so I’ll be sticking with C89, thank you very much.

And on Solaris, nope. Not going near it, and even if I was, I could just burn an ISO.

7 On February 7, 2007 at 14:28, Keith wrote:

Oh, and read through the code again, the usage isn’t

hostnames [-q | hostname]
hostnames [-q] [hostname]

Post a comment

All form information is optional, but it’s a good idea to fill in your name and email address if you want me to take your comment seriously.

Spammers, don’t bother posting crap down here. The site is set up so that legitimate search engines (Google, for instance) won’t index pages with comments on them. Posting crud here only means you’re wasting my time and patience. Shoo!

Real names, please. Please include!
Won’t be displayed. Please include!
Displayed, if present.