summaryrefslogtreecommitdiff
path: root/lib/Sys/Hostname/Long.pm
blob: 975afdba0416c959329ce3b0c9f4cde153dd943e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
package Sys::Hostname::Long;
use strict;
use Carp;

require Exporter;
use Sys::Hostname;

# Use perl < 5.6 compatible methods for now, change to 'use base' soon
@Sys::Hostname::Long::ISA     = qw/ Exporter Sys::Hostname /;

# Use perl < 5.6 compatible methods for now, change to 'our' soon.
use vars qw(@EXPORT $VERSION $hostlong %dispatch $lastdispatch);
@EXPORT  = qw/ hostname_long /;
$VERSION = '1.5';

%dispatch = (

	'gethostbyname' => {
		'title' => 'Get Host by Name',
		'description' => '',
		'exec' => sub {
			return gethostbyname('localhost');
		},
	},

	'exec_hostname' => {
		'title' => 'Execute "hostname"',
		'description' => '',
		'exec' => sub {
			my $tmp = `hostname`;
			$tmp =~ tr/\0\r\n//d;
			return $tmp;
		},
	},

	'win32_registry1' => {
		'title' => 'WIN32 Registry',
		'description' => 'LMachine/System/CurrentControlSet/Service/VxD/MSTCP/Domain',
		'exec' => sub {
			return eval q{
				use Win32::TieRegistry ( TiedHash => '%RegistryHash' );
				$RegistryHash{'LMachine'}{'System'}{'CurrentControlSet'}{'Services'}{'VxD'}{'MSTCP'}{'Domain'};
			};
		},
	},

	'uname' => {
		'title' => 'POSIX::uname',
		'description' => '',
		'exec' => sub {
			return eval {
				local $SIG{__DIE__};
				require POSIX;
				(POSIX::uname())[1];
			};
		},
	},

	# XXX This is the same as above - what happened to the other one !!!
	'win32_registry2' => {
		'title' => 'WIN32 Registry',
		'description' => 'LMachine/System/CurrentControlSet/Services/VxD/MSTCP/Domain',
		'exec' => sub {
			return eval q{
				use Win32::TieRegistry ( TiedHash => '%RegistryHash' );
				$RegistryHash{'LMachine'}{'System'}{'CurrentControlSet'}{'Services'}{'VxD'}{'MSTCP'}{'Domain'};
			};
		},
	},

	'exec_hostname_fqdn' => {
		'title' => 'Execute "hostname --fqdn"',
		'description' => '',
		'exec' => sub {
			# Skip for Solaris, and only run as non-root
			# Skip for darwin (Mac OS X), RT#28894
			my $tmp;
			if ( $^O ne 'darwin' ) {
				if ($< == 0) {
					$tmp = `su nobody -c "hostname --fqdn"`;
				} else {
					$tmp = `hostname --fqdn`;
				}
				$tmp =~ tr/\0\r\n//d;
			}
			return $tmp;
		},
	},

	'exec_hostname_domainname' => {
		'title' => 'Execute "hostname" and "domainname"',
		'description' => '',
		'exec' => sub {
			my $tmp = `hostname` . '.' . `domainname`;
			$tmp =~ tr/\0\r\n//d;
			return $tmp;
		},
	},


	'network' => {
		'title' => 'Network Socket hostname (not DNS)',
		'description' => '',
		'exec' => sub {
			return eval q{
				use IO::Socket;
				my $s = IO::Socket::INET->new(
					# m.root-servers.net (a remote IP number)
					PeerAddr => '202.12.27.33',
					# random safe port
					PeerPort => 2000,
					# We don't actually want to connect
					Proto => 'udp',
				) or die "Faile socket - $!";
				gethostbyaddr($s->sockaddr(), AF_INET);
			};
		},
	},

	'ip' => {
		'title' => 'Network Socket IP then Hostname via DNS',
		'description' => '',
		'exec' => sub {
			return eval q{
				use IO::Socket;
				my $s = IO::Socket::INET->new(
					# m.root-servers.net (a remote IP number)
					PeerAddr => '202.12.27.33',
					# random safe port
					PeerPort => 2000,
					# We don't actually want to connect
					Proto => 'udp',
				) or die "Faile socket - $!";
				$s->sockhost;
			};
		},
	},

);

# Dispatch from table
sub dispatcher {
	my ($method, @rest) = @_;
	$lastdispatch = $method;
	return $dispatch{$method}{exec}(@rest);
}

sub dispatch_keys {
	return sort keys %dispatch;
}

sub dispatch_title {
	return $dispatch{$_[0]}{title};
}

sub dispatch_description {
	return $dispatch{$_[0]}{description};
}

sub hostname_long {
	return $hostlong if defined $hostlong; 	# Cached copy (takes a while to lookup sometimes)
	my ($ip, $debug) = @_;

	$hostlong = dispatcher('uname');

	unless ($hostlong =~ m|.*\..*|) {
		if ($^O eq 'MacOS') {
			# http://bumppo.net/lists/macperl/1999/03/msg00282.html
			#	suggests that it will work (checking localhost) on both
			#	Mac and Windows.
			#	Personally this makes no sense what so ever as
			$hostlong = dispatcher('gethostbyname');

		} elsif ($^O eq 'IRIX') {	# XXX Patter match string !
			$hostlong = dispatcher('exec_hostname');

		} elsif ($^O eq 'cygwin') {
			$hostlong = dispatcher('win32_registry1');

		} elsif ($^O eq 'MSWin32') {
			$hostlong = dispatcher('win32_registry2');

		} elsif ($^O =~ m/(bsd|nto)/i) {
			$hostlong = dispatcher('exec_hostname');

		# (covered above) } elsif ($^O eq "darwin") {
		#	$hostlong = dispatcher('uname');

		} elsif ($^O eq 'solaris') {
			$hostlong = dispatcher('exec_hostname_domainname');

		} else {
			$hostlong = dispatcher('exec_hostname_fqdn');
		}

		if (!defined($hostlong) || $hostlong eq "") {
			# FALL BACK - Requires working internet and DNS and reverse
			# lookups of your IP number.
			$hostlong = dispatcher('network');
		}

		if ($ip && !defined($hostlong) || $hostlong eq "") {
			$hostlong = dispatcher('ip');
		}
	}
	warn "Sys::Hostname::Long - Last Dispatch method = $lastdispatch" if ($debug);
	return $hostlong;
}

1;

__END__

=head1 NAME

Sys::Hostname::Long - Try every conceivable way to get full hostname

=head1 SYNOPSIS

    use Sys::Hostname::Long;
    $host_long = hostname_long;

=head1 DESCRIPTION

How to get the host full name in perl on multiple operating systems (mac,
windows, unix* etc)

=head1 DISCUSSION

This is the SECOND release of this code. It has an improved set of tests and
improved interfaces - but it is still often failing to get a full host name.
This of course is the reason I wrote the module, it is difficult to get full
host names accurately on each system. On some systems (eg: Linux) it is
dependent on the order of the entries in /etc/hosts.

To make it easier to test I have testall.pl to generate an output list of all
methods. Thus even if the logic is incorrect, it may be possible to get the
full name.

Attempt via many methods to get the systems full name. The L<Sys::Hostname>
class is the best and standard way to get the system hostname. However it is
missing the long hostname.

Special thanks to B<David Sundstrom> and B<Greg Bacon> for the original
L<Sys::Hostname>

=head1 SUPPORT

This is the original list of platforms tested.

	MacOS		Macintosh Classic		OK
	Win32		MS Windows (95,98,nt,2000...)
			98				OK
	MacOS X		Macintosh 10			OK
			(other darwin)			Probably OK (not tested)
	Linux 		Linux UNIX OS			OK
			Sparc				OK
	HPUX		H.P. Unix 10?			Not Tested
	Solaris		SUN Solaris 7?			OK (now)
	Irix		SGI Irix 5?			Not Tested
	FreeBSD		FreeBSD				OK

A new list has now been compiled of all the operating systems so that I can
individually keep information on their success.

THIS IS IN NEED OF AN UPDATE AFTER NEXT RELEASE.

=over 4

=item Acorn - Not yet tested

=item AIX - Not yet tested

=item Amiga - Not yet tested

=item Atari - Not yet tested

=item AtheOS - Not yet tested

=item BeOS - Not yet tested

=item BSD - Not yet tested

=item BSD/OS - Not yet tested

=item Compaq - Not yet tested

=item Cygwin - Not yet tested

=item Concurrent - Not yet tested

=item DG/UX - Not yet tested

=item Digital - Not yet tested

=item DEC OSF/1 - Not yet tested

=item Digital UNIX - Not yet tested

=item DYNIX/ptx - Not yet tested

=item EPOC - Not yet tested

=item FreeBSD - Not yet tested

=item Fujitsu-Siemens - Not yet tested

=item Guardian - Not yet tested

=item HP - Not yet tested

=item HP-UX - Not yet tested

=item IBM - Not yet tested

=item IRIX - Not yet tested - 3rd hand information might be ok.

=item Japanese - Not yet tested

=item JPerl - Not yet tested

=item Linux

=over 8

=item Debian - Not yet tested

=item Gentoo - Not yet tested

=item Mandrake - Not yet tested

=item Red Hat- Not yet tested

=item Slackware - Not yet tested

=item SuSe - Not yet tested

=item Yellowdog - Not yet tested

=back

=item LynxOS - Not yet tested

=item Mac OS - Not yet tested

=item Mac OS X - OK 20040315 (v1.1)

=item MachTen - Not yet tested

=item Minix - Not yet tested

=item MinGW - Not yet tested

=item MiNT - Not yet tested

=item MPE/iX - Not yet tested

=item MS-DOS - Not yet tested

=item MVS - Not yet tested

=item NetBSD - Not yet tested

=item NetWare - Not yet tested

=item NEWS-OS - Not yet tested

=item NextStep - Not yet tested

=item Novell - Not yet tested

=item NonStop - Not yet tested

=item NonStop-UX - Not yet tested

=item OpenBSD - Not yet tested

=item ODT - Not yet tested

=item OpenVMS - Not yet tested

=item Open UNIX - Not yet tested

=item OS/2 - Not yet tested

=item OS/390 - Not yet tested

=item OS/400 - Not yet tested

=item OSF/1 - Not yet tested

=item OSR - Not yet tested

=item Plan 9 - Not yet tested

=item Pocket PC - Not yet tested

=item PowerMAX - Not yet tested

=item Psion - Not yet tested

=item QNX

=over 8

=item 4 - Not yet tested

=item 6 (Neutrino) - Not yet tested

=back

=item Reliant UNIX - Not yet tested

=item RISCOS - Not yet tested

=item SCO - Not yet tested

=item SGI - Not yet tested

=item Symbian - Not yet tested

=item Sequent - Not yet tested

=item Siemens - Not yet tested

=item SINIX - Not yet tested

=item Solaris - Not yet tested

=item SONY - Not yet tested

=item Sun - Not yet tested

=item Stratus - Not yet tested

=item Tandem - Not yet tested

=item Tru64 - Not yet tested

=item Ultrix - Not yet tested

=item UNIX - Not yet tested

=item U/WIN - Not yet tested

=item Unixware - Not yet tested

=item VMS - Not yet tested

=item VOS - Not yet tested

=item Windows

=over 8

=item CE - Not yet tested

=item 3.1 - Not yet tested

=item 95 - Not yet tested

=item 98 - Not yet tested

=item Me - Not yet tested

=item NT - Not yet tested

=item 2000 - Not yet tested

=item XP - Not yet tested

=back

=item z/OS - Not yet tested

=back

=head1 KNOWN LIMITATIONS

=head2 Unix

Most unix systems have trouble working out the fully qualified domain name as
it to be configured somewhere in the system correctly. For example in most
linux systems (debian, ?) the fully qualified name should be the first entry
next to the ip number in /etc/hosts

	192.168.0.1	fred.somwhere.special	fred

If it is the other way around, it will fail.

=head2 Mac

=head1 TODO

Contributions

	David Dick
	Graeme Hart
	Piotr Klaban

	* Extra code from G
	* Dispatch table
	* List of all operating systems.

Solaris
	* Fall back 2 - TCP with DNS works ok
	* Also can read /etc/defaultdomain file

=head1 SEE ALSO

	L<Sys::Hostname>

=head1 AUTHOR

Originally by Scott Penrose E<lt>F<scottp@dd.com.au>E<gt>

Contributions: Michiel Beijen E<lt>F<michiel.beijen@gmail.com>E<gt>


=head1 COPYRIGHT

Copyright (c) 2001,2004,2005,2015 Scott Penrose. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the same terms as Perl itself.

=cut