Created
December 18, 2010 05:09
-
-
Save atr000/746179 to your computer and use it in GitHub Desktop.
nice util to aid shell/home scripts on finding the remote ip over a ssh connection
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* $Id: //websites/unixwiz/unixwiz.net/webroot/tools/whoamip.c#1 $ | |
* | |
* written by : Stephen J. Friedl | |
* Software Consultant | |
* Tustin, California USA | |
* http://www.unixwiz.net/tools/ | |
* | |
* *********************************************************** | |
* ** ** | |
* ** This program is in the public domain, and can be used ** | |
* ** by anybody, for any purpose. Have fun. ** | |
* ** ** | |
* *********************************************************** | |
* | |
* This program is used to make the best guess at a user's remote | |
* IP address. We do not have a good mechanism to obtain it directly, | |
* but given the user's tty (usually a pts), we can look in the | |
* utmpx file where it's recorded. | |
* | |
* The "who" program reads from /var/adm/utmpx, but sadly does not | |
* seem to have a way to report the hostname, so we have written | |
* this program to do so. | |
* | |
* Playing on the "whoami" program, we've named it "whoamip". | |
* | |
* WHAT'S THE HOSTNAME? | |
* -------------------- | |
* | |
* We're not able to directly discover the IP address of the other | |
* end of this connection, because our program doesn't have any | |
* access to the direct socket in order to run getpeername(). An | |
* intermediate pseudo-tty isolates us from the socket, so we have | |
* no trivial way to learn this straightway. | |
* | |
* Some operating systems probably provide some kernel-based mechanism | |
* for digging into the network stack, but this is troublesome and | |
* highly non-portable. It's probably nearly unsolvable on many | |
* platforms. | |
* | |
* Instead, we'll get the information indirectly: the init and/or login | |
* program typically maintains this in the utmpx file (in /etc/ or | |
* /var/adm), associating the remote host with the current logged-in | |
* pseudo-tty. | |
* | |
* We locate the current tty and use that as a key to utmpx: this | |
* brings a record with the username and hostname: this is what's | |
* reported to the user. | |
* | |
* We're at the mercy of the login program to fill in the ut_host | |
* field: sometimes it contains the IP address (as a string), and | |
* other times it's a hostname (perhaps truncated). We have no | |
* control over this process and simply take what we're given. | |
* | |
* SSH SHORCUTS | |
* ------------ | |
* | |
* As a short-circuit for users who come in via Secure Shell, we | |
* take a quick check for the $SSH_CLIENT environment variable, | |
* which would contain the IP address. If this is found, we return | |
* it directly without doing any I/O or mucking around with the TTY. | |
* | |
* Use the -S cmdline parameter to disable the $SSH_CLIENT check, | |
* and in any case we do not use the value unless there is a space | |
* after the remote IP address. | |
* | |
* BUILDING + RUNNING | |
* ------------------ | |
* | |
* This requires just a C compiler: | |
* | |
* $ cc whoamip.c -o whoamip | |
* | |
* It should compile without errors or warnings. | |
* | |
* Running the program produces the hostname on the standard | |
* output, which can be captured in the shell (often in /etc/profile). | |
* | |
* $ host=`whoamip` | |
* | |
* We exit with zero (success) if we believe we've located the hostname, | |
* and nonzero (failure) if we can't for whatever reason. | |
* | |
* COMMAND LINE | |
* ------------ | |
* | |
* -V | |
* Show the program's version information, then exit with success | |
* | |
* -S | |
* Disable the $SSH_CLIENT check. | |
* | |
* VERSION HISTORY | |
* --------------- | |
* | |
* 1.0.1 - 2006-07-31 | |
* Initial release | |
*/ | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <errno.h> | |
#include <utmpx.h> | |
#include <unistd.h> | |
#ifndef TRUE | |
# define TRUE 1 | |
# define FALSE 0 | |
#endif | |
static const char Version[] = | |
"whoamip 1.0.1 - 2006-07-31 - http://www.unixwiz.net/tools/"; | |
static int no_ssh_client = FALSE; | |
int main(int argc, char **argv) | |
{ | |
int c; | |
char *tty, *p, *env; | |
struct utmpx protox, *utp; | |
/*--------------------------------------------------------------- | |
* COMMAND-LINE | |
*/ | |
while ( (c = getopt(argc, argv, "VS")) != EOF ) | |
{ | |
switch (c) | |
{ | |
case 'V': | |
puts(Version); | |
exit(EXIT_SUCCESS); | |
case 'S': | |
no_ssh_client = TRUE; | |
break; | |
default: | |
exit(EXIT_FAILURE); | |
} | |
} | |
/*--------------------------------------------------------------- | |
* SHORTCUT: SSH variable? | |
* | |
* Most users don't use SSH, but for those that do, the $SSH_CLIENT | |
* reports the remote connection: | |
* | |
* SSH_CLIENT="64.170.162.98 51851 22" | |
* | |
* We only care about the IP address and not the ports involved, | |
* but this is a pretty reliable mechanism. | |
*/ | |
if ( ! no_ssh_client | |
&& (env = getenv("SSH_CLIENT")) != 0 | |
&& (p = strchr(env, ' ')) != 0 ) | |
{ | |
*p = '\0'; | |
*p = '\0'; | |
puts(env); | |
exit(EXIT_SUCCESS); | |
} | |
/*--------------------------------------------------------------- | |
* FIND TTY NAME | |
* | |
* The utmp/wtmp files ONLY work when indexed by tty name, so we | |
* have to find the current tty. For network connections, this is | |
* virtually always /dev/ptsX (a pseudo-tty), and we remove the | |
* leading /dev/ part. | |
* | |
* Some systems work with /dev/pts123, while others use /dev/pts/123. | |
* We remove /dev/ in either case. | |
* | |
* NOTE: a tty is associated with a *file descriptor*, not a | |
* program, so we have to pick one. We use the standard input, | |
* because the standard output & error may well be attached to | |
* either an output file or a pipe: | |
* | |
* host=`whoamip` | |
* | |
* If we cannot find the tty name, we're done - sorry. | |
* | |
* Otherwise, rip off everything up to the final / | |
*/ | |
if ( (tty = ttyname(fileno(stdin))) == 0 ) | |
{ | |
fprintf(stderr, "cannot get tty [%s]\n", strerror(errno) ); | |
exit(EXIT_FAILURE); | |
} | |
if ( strncmp(tty, "/dev/", 5) == 0 ) | |
tty += 5; | |
/*--------------------------------------------------------------- | |
* LOCATE UTMPX | |
* | |
* Look in the utmpx file for a record matching this line, but | |
* the lookup is done with a prototype UTMPX record that has the | |
* ut_line member filled in. | |
*/ | |
memset(&protox, 0, sizeof protox); | |
strcpy(protox.ut_line, tty); | |
if ( (utp = getutxline(&protox) ) == 0 ) | |
{ | |
fprintf(stderr, "cannot locate UTMPX for {%s}\n", tty); | |
exit(EXIT_FAILURE); | |
} | |
/*--------------------------------------------------------------- | |
* FOUND IT! | |
* | |
* We should have a NUL-byte terminated string, but we believe | |
* that we've seen systems which use up to the full size of the | |
* buffer without the trailing NUL. That would mean we might end | |
* up with a runaway string. That would be bad. | |
* | |
* So we create a buffer one byte larger, copy the ut_host field | |
* into it, and assuredly add our own NUL byte. | |
* | |
* This may be overkill, but we don't get so snookered by funky | |
* data. | |
*/ | |
{ | |
#define SZ sizeof(utp->ut_host) | |
char linebuf[1 + SZ]; | |
memcpy(linebuf, utp->ut_host, SZ); | |
linebuf[SZ] = '\0'; | |
puts(linebuf); | |
} | |
return EXIT_SUCCESS; | |
} | |
Choose download locationDownload |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment