X-Git-Url: http://git.samba.org/samba.git/?a=blobdiff_plain;f=util.c;h=a86b48afd34a7c09c9e971927294b062c37ab812;hb=daded207524d8d911fcbe8337c4b1b4b7a08ef1a;hp=7b61d1b3f1e35967f664f10a32b309e8195b6e94;hpb=789582037abdd88cf034eeee7a5e8c3f98780256;p=obnox%2Fwireshark%2Fwip.git diff --git a/util.c b/util.c index 7b61d1b3f1..a86b48afd3 100644 --- a/util.c +++ b/util.c @@ -3,8 +3,8 @@ * * $Id$ * - * Ethereal - Network traffic analyzer - * By Gerald Combs + * Wireshark - Network traffic analyzer + * By Gerald Combs * Copyright 1998 Gerald Combs * * This program is free software; you can redistribute it and/or @@ -37,37 +37,9 @@ #include #endif -#ifdef HAVE_SYS_STAT_H -#include -#endif - -#ifdef NEED_SNPRINTF_H -# include "snprintf.h" -#endif - -#ifdef NEED_MKSTEMP -#include "mkstemp.h" -#endif - -#ifdef HAVE_IO_H -#include -#ifndef __MINGW32__ -typedef int mode_t; /* for win32 */ -#endif /* __MINGW32__ */ -#endif /* HAVE_IO_H */ - #include #include - -/* - * This has to come after the include of , as the include of - * might cause to be included, and if we've - * already included as a result of including , - * we get a bunch of redefinitions. - */ -#ifdef HAVE_WINDOWS_H -#include -#endif +#include #include "util.h" @@ -76,7 +48,7 @@ typedef int mode_t; /* for win32 */ * separated by spaces. */ char * -get_args_as_string(int argc, char **argv, int optind) +get_args_as_string(int argc, char **argv, int optindex) { int len; int i; @@ -86,8 +58,8 @@ get_args_as_string(int argc, char **argv, int optind) * Find out how long the string will be. */ len = 0; - for (i = optind; i < argc; i++) { - len += strlen(argv[i]); + for (i = optindex; i < argc; i++) { + len += (int) strlen(argv[i]); len++; /* space, or '\0' if this is the last argument */ } @@ -99,118 +71,18 @@ get_args_as_string(int argc, char **argv, int optind) /* * Now construct the string. */ - strcpy(argstring, ""); - i = optind; + argstring[0] = '\0'; + i = optindex; for (;;) { - strcat(argstring, argv[i]); + g_strlcat(argstring, argv[i], len); i++; if (i == argc) break; - strcat(argstring, " "); + g_strlcat(argstring, " ", len); } return argstring; } -static char * -setup_tmpdir(char *dir) -{ - int len = strlen(dir); - char *newdir; - - /* Append path separator if necessary */ - if (dir[len - 1] == G_DIR_SEPARATOR) { - newdir = dir; - } - else { - newdir = g_malloc(len + 2); - strcpy(newdir, dir); - strcat(newdir, G_DIR_SEPARATOR_S); - } - return newdir; -} - -static int -try_tempfile(char *namebuf, int namebuflen, const char *dir, const char *pfx) -{ - static const char suffix[] = "XXXXXXXXXX"; - int namelen = strlen(dir) + strlen(pfx) + sizeof suffix; - mode_t old_umask; - int tmp_fd; - - if (namebuflen < namelen) { - /* Stick in a truncated name, so that if this error is - reported with the file name, you at least get - something. */ - snprintf(namebuf, namebuflen, "%s%s%s", dir, pfx, suffix); - errno = ENAMETOOLONG; - return -1; - } - strcpy(namebuf, dir); - strcat(namebuf, pfx); - strcat(namebuf, suffix); - - /* The Single UNIX Specification doesn't say that "mkstemp()" - creates the temporary file with mode rw-------, so we - won't assume that all UNIXes will do so; instead, we set - the umask to 0077 to take away all group and other - permissions, attempt to create the file, and then put - the umask back. */ - old_umask = umask(0077); - tmp_fd = mkstemp(namebuf); - umask(old_umask); - return tmp_fd; -} - -static char *tmpdir = NULL; -#ifdef _WIN32 -static char *temp = NULL; -#endif -static char *E_tmpdir; - -#ifndef P_tmpdir -#define P_tmpdir "/var/tmp" -#endif - -int -create_tempfile(char *namebuf, int namebuflen, const char *pfx) -{ - char *dir; - int fd; - static gboolean initialized; - - if (!initialized) { - if ((dir = getenv("TMPDIR")) != NULL) - tmpdir = setup_tmpdir(dir); -#ifdef _WIN32 - if ((dir = getenv("TEMP")) != NULL) - temp = setup_tmpdir(dir); -#endif - - E_tmpdir = setup_tmpdir(P_tmpdir); - initialized = TRUE; - } - - if (tmpdir != NULL) { - fd = try_tempfile(namebuf, namebuflen, tmpdir, pfx); - if (fd != -1) - return fd; - } - -#ifdef _WIN32 - if (temp != NULL) { - fd = try_tempfile(namebuf, namebuflen, temp, pfx); - if (fd != -1) - return fd; - } -#endif - - fd = try_tempfile(namebuf, namebuflen, E_tmpdir, pfx); - if (fd != -1) - return fd; - - return try_tempfile(namebuf, namebuflen, G_DIR_SEPARATOR_S "tmp", pfx); -} - /* Compute the difference between two seconds/microseconds time stamps. */ void compute_timestamp_diff(gint *diffsec, gint *diffusec, @@ -263,12 +135,16 @@ compute_timestamp_diff(gint *diffsec, gint *diffusec, SSH_CLIENT (ssh): REMOTEHOST (tcsh, others?): DISPLAY (x11): [remote name]: - CLIENTNAME (terminal server): + SESSIONNAME (terminal server): */ -gchar *get_conn_cfilter(void) { +const gchar *get_conn_cfilter(void) { static GString *filter_str = NULL; gchar *env, **tokens; + char *lastp, *lastc, *p; + char *pprotocol = NULL; + char *phostname = NULL; + size_t hostlen; if (filter_str == NULL) { filter_str = g_string_new(""); @@ -276,36 +152,169 @@ gchar *get_conn_cfilter(void) { if ((env = getenv("SSH_CONNECTION")) != NULL) { tokens = g_strsplit(env, " ", 4); if (tokens[3]) { - g_string_sprintf(filter_str, "not (tcp port %s and %s host %s " + g_string_printf(filter_str, "not (tcp port %s and %s host %s " "and tcp port %s and %s host %s)", tokens[1], host_ip_af(tokens[0]), tokens[0], tokens[3], host_ip_af(tokens[2]), tokens[2]); return filter_str->str; } } else if ((env = getenv("SSH_CLIENT")) != NULL) { tokens = g_strsplit(env, " ", 3); - g_string_sprintf(filter_str, "not (tcp port %s and %s host %s " + g_string_printf(filter_str, "not (tcp port %s and %s host %s " "and tcp port %s)", tokens[1], host_ip_af(tokens[0]), tokens[0], tokens[2]); return filter_str->str; } else if ((env = getenv("REMOTEHOST")) != NULL) { - if (strcasecmp(env, "localhost") == 0 || strcmp(env, "127.0.0.1") == 0) { + /* FreeBSD 7.0 sets REMOTEHOST to an empty string */ + if (g_ascii_strcasecmp(env, "localhost") == 0 || + strcmp(env, "127.0.0.1") == 0 || + strcmp(env, "") == 0) { return ""; } - g_string_sprintf(filter_str, "not %s host %s", host_ip_af(env), env); + g_string_printf(filter_str, "not %s host %s", host_ip_af(env), env); return filter_str->str; } else if ((env = getenv("DISPLAY")) != NULL) { - tokens = g_strsplit(env, ":", 2); - if (tokens[0] && tokens[0][0] != 0) { - if (strcasecmp(tokens[0], "localhost") == 0 || - strcmp(tokens[0], "127.0.0.1") == 0) { + /* + * This mirrors what _X11TransConnectDisplay() does. + * Note that, on some systems, the hostname can + * begin with "/", which means that it's a pathname + * of a UNIX domain socket to connect to. + * + * The comments mirror those in _X11TransConnectDisplay(), + * too. :-) + * + * Display names may be of the following format: + * + * [protoco./] [hostname] : [:] displaynumber [.screennumber] + * + * A string with exactly two colons separating hostname + * from the display indicates a DECnet style name. Colons + * in the hostname may occur if an IPv6 numeric address + * is used as the hostname. An IPv6 numeric address may + * also end in a double colon, so three colons in a row + * indicates an IPv6 address ending in :: followed by + * :display. To make it easier for people to read, an + * IPv6 numeric address hostname may be surrounded by [] + * in a similar fashion to the IPv6 numeric address URL + * syntax defined by IETF RFC 2732. + * + * If no hostname and no protocol is specified, the string + * is interpreted as the most efficient local connection + * to a server on the same machine. This is usually: + * + * o shared memory + * o local stream + * o UNIX domain socket + * o TCP to local host. + */ + + p = env; + + /* + * Step 0, find the protocol. This is delimited by + * the optional slash ('/'). + */ + for (lastp = p; *p != '\0' && *p != ':' && *p != '/'; p++) + ; + if (*p == '\0') + return ""; /* must have a colon */ + + if (p != lastp && *p != ':') { /* protocol given? */ + /* Yes */ + pprotocol = p; + + /* Is it TCP? */ + if (p - lastp != 3 || g_ascii_strncasecmp(lastp, "tcp", 3) != 0) + return ""; /* not TCP */ + p++; /* skip the '/' */ + } else + p = env; /* reset the pointer in + case no protocol was given */ + + /* + * Step 1, find the hostname. This is delimited either by + * one colon, or two colons in the case of DECnet (DECnet + * Phase V allows a single colon in the hostname). (See + * note above regarding IPv6 numeric addresses with + * triple colons or [] brackets.) + */ + lastp = p; + lastc = NULL; + for (; *p != '\0'; p++) + if (*p == ':') + lastc = p; + + if (lastc == NULL) + return ""; /* must have a colon */ + + if ((lastp != lastc) && (*(lastc - 1) == ':') + && (((lastc - 1) == lastp) || (*(lastc - 2) != ':'))) { + /* DECnet display specified */ + return ""; + } else + hostlen = lastc - lastp; + + if (hostlen == 0) + return ""; /* no hostname supplied */ + + phostname = g_malloc(hostlen + 1); + memcpy(phostname, lastp, hostlen); + phostname[hostlen] = '\0'; + + if (pprotocol == NULL) { + /* + * No protocol was explicitly specified, so it + * could be a local connection over a transport + * that we won't see. + * + * Does the host name refer to the local host? + * If so, the connection would probably be a + * local connection. + * + * XXX - compare against our host name? + * _X11TransConnectDisplay() does. + */ + if (g_ascii_strcasecmp(phostname, "localhost") == 0 || + strcmp(phostname, "127.0.0.1") == 0) { + g_free(phostname); + return ""; + } + + /* + * A host name of "unix" (case-sensitive) also + * causes a local connection. + */ + if (strcmp(phostname, "unix") == 0) { + g_free(phostname); + return ""; + } + + /* + * Does the host name begin with "/"? If so, + * it's presumed to be the pathname of a + * UNIX domain socket. + */ + if (phostname[0] == '/') { + g_free(phostname); return ""; } - g_string_sprintf(filter_str, "not %s host %s", - host_ip_af(tokens[0]), tokens[0]); - return filter_str->str; } - } else if ((env = getenv("CLIENTNAME")) != NULL) { - if (g_strcasecmp("console", env) != 0) { - g_string_sprintf(filter_str, "not %s host %s", host_ip_af(env), env); + + g_string_printf(filter_str, "not %s host %s", + host_ip_af(phostname), phostname); + g_free(phostname); + return filter_str->str; + } else if ((env = getenv("SESSIONNAME")) != NULL) { + /* Apparently the KB article at + * http://technet2.microsoft.com/WindowsServer/en/library/6caf87bf-3d70-4801-9485-87e9ec3df0171033.mspx?mfr=true + * is incorrect. There are _plenty_ of cases where CLIENTNAME + * and SESSIONNAME are set outside of a Terminal Terver session. + * It looks like Terminal Server sets SESSIONNAME to RDP-TCP# + * for "real" sessions. + * + * XXX - There's a better way to do this described at + * http://www.microsoft.com/technet/archive/termsrv/maintain/featusability/tsrvapi.mspx?mfr=true + */ + if (g_ascii_strncasecmp(env, "rdp", 3) == 0) { + g_string_printf(filter_str, "not tcp port 3389"); return filter_str->str; } }