1*9203SMark.Logan@Sun.COM /******************************************************************************* 2*9203SMark.Logan@Sun.COM * Copyright (C) 2004-2008 Intel Corp. All rights reserved. 3*9203SMark.Logan@Sun.COM * 4*9203SMark.Logan@Sun.COM * Redistribution and use in source and binary forms, with or without 5*9203SMark.Logan@Sun.COM * modification, are permitted provided that the following conditions are met: 6*9203SMark.Logan@Sun.COM * 7*9203SMark.Logan@Sun.COM * - Redistributions of source code must retain the above copyright notice, 8*9203SMark.Logan@Sun.COM * this list of conditions and the following disclaimer. 9*9203SMark.Logan@Sun.COM * 10*9203SMark.Logan@Sun.COM * - Redistributions in binary form must reproduce the above copyright notice, 11*9203SMark.Logan@Sun.COM * this list of conditions and the following disclaimer in the documentation 12*9203SMark.Logan@Sun.COM * and/or other materials provided with the distribution. 13*9203SMark.Logan@Sun.COM * 14*9203SMark.Logan@Sun.COM * - Neither the name of Intel Corp. nor the names of its 15*9203SMark.Logan@Sun.COM * contributors may be used to endorse or promote products derived from this 16*9203SMark.Logan@Sun.COM * software without specific prior written permission. 17*9203SMark.Logan@Sun.COM * 18*9203SMark.Logan@Sun.COM * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' 19*9203SMark.Logan@Sun.COM * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20*9203SMark.Logan@Sun.COM * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21*9203SMark.Logan@Sun.COM * ARE DISCLAIMED. IN NO EVENT SHALL Intel Corp. OR THE CONTRIBUTORS 22*9203SMark.Logan@Sun.COM * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23*9203SMark.Logan@Sun.COM * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24*9203SMark.Logan@Sun.COM * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25*9203SMark.Logan@Sun.COM * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26*9203SMark.Logan@Sun.COM * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27*9203SMark.Logan@Sun.COM * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28*9203SMark.Logan@Sun.COM * POSSIBILITY OF SUCH DAMAGE. 29*9203SMark.Logan@Sun.COM *******************************************************************************/ 30*9203SMark.Logan@Sun.COM 31*9203SMark.Logan@Sun.COM #ifdef HAVE_CONFIG_H 32*9203SMark.Logan@Sun.COM #include "config.h" 33*9203SMark.Logan@Sun.COM #endif 34*9203SMark.Logan@Sun.COM #include "iatshareddata.h" 35*9203SMark.Logan@Sun.COM #include "ATVersion.h" 36*9203SMark.Logan@Sun.COM #include <cstring> 37*9203SMark.Logan@Sun.COM #include <cstdlib> 38*9203SMark.Logan@Sun.COM #include <cstdio> 39*9203SMark.Logan@Sun.COM #include <climits> 40*9203SMark.Logan@Sun.COM #include <cerrno> 41*9203SMark.Logan@Sun.COM #include <fstream> 42*9203SMark.Logan@Sun.COM #include <dirent.h> 43*9203SMark.Logan@Sun.COM 44*9203SMark.Logan@Sun.COM #define AT_VERSION_ARGUMENT "--version" 45*9203SMark.Logan@Sun.COM #define AT_VERSION_MAXSIZE 40 46*9203SMark.Logan@Sun.COM #define AT_APPNAME_MAXSIZE 15 47*9203SMark.Logan@Sun.COM #define ATstr(s) ATname(s) 48*9203SMark.Logan@Sun.COM #define ATname(s) #s 49*9203SMark.Logan@Sun.COM #define AT_VERSION_OUT_FORMAT "Version: %." ATstr(AT_VERSION_MAXSIZE) "s\n" 50*9203SMark.Logan@Sun.COM #define AT_VERSION_SCAN_FORMAT "Version: %" ATstr(AT_VERSION_MAXSIZE) "s" 51*9203SMark.Logan@Sun.COM #define AT_PIDFILE_NAME_FORMAT IATSTATERUNDIR "/%." ATstr(AT_APPNAME_MAXSIZE) "s.pid" 52*9203SMark.Logan@Sun.COM #define AT_DEF_PIDFILE_NAME_FORMAT "/var/run/%." ATstr(AT_APPNAME_MAXSIZE) "s.pid" 53*9203SMark.Logan@Sun.COM #define AT_PROCSTAT_NAME_FORMAT "Name:\t%" ATstr(AT_APPNAME_MAXSIZE) "s\n" 54*9203SMark.Logan@Sun.COM 55*9203SMark.Logan@Sun.COM const std::string ATVersion::appSearchPath = 56*9203SMark.Logan@Sun.COM "PATH='/usr/local/sbin:/usr/sbin:/sbin:/usr/local/bin:/usr/bin:/bin' && "; 57*9203SMark.Logan@Sun.COM 58*9203SMark.Logan@Sun.COM bool ATVersion::ShowVersionIfArg(int argc, const char **argv, const char *versionStr) 59*9203SMark.Logan@Sun.COM { 60*9203SMark.Logan@Sun.COM if (1 < argc) { 61*9203SMark.Logan@Sun.COM for (int i = 1; i < argc; i++) { 62*9203SMark.Logan@Sun.COM if (0 == strncmp(argv[i], AT_VERSION_ARGUMENT, strlen(AT_VERSION_ARGUMENT))) { 63*9203SMark.Logan@Sun.COM fprintf(stdout, AT_VERSION_OUT_FORMAT, versionStr); 64*9203SMark.Logan@Sun.COM return true; 65*9203SMark.Logan@Sun.COM } 66*9203SMark.Logan@Sun.COM } 67*9203SMark.Logan@Sun.COM } 68*9203SMark.Logan@Sun.COM return false; 69*9203SMark.Logan@Sun.COM } 70*9203SMark.Logan@Sun.COM 71*9203SMark.Logan@Sun.COM bool ATVersion::GetAppVersion(const char *appName, std::string &version) 72*9203SMark.Logan@Sun.COM { 73*9203SMark.Logan@Sun.COM std::list<unsigned long> pids; 74*9203SMark.Logan@Sun.COM 75*9203SMark.Logan@Sun.COM version = ""; 76*9203SMark.Logan@Sun.COM if (IsAppRunning(appName, pids)) { 77*9203SMark.Logan@Sun.COM for (std::list<unsigned long>::iterator iter = pids.begin(); iter != pids.end(); iter++) { 78*9203SMark.Logan@Sun.COM std::string path = GetAppPathByPid(*iter); 79*9203SMark.Logan@Sun.COM if (!path.empty()) { 80*9203SMark.Logan@Sun.COM version = GetProcessVersion(path); 81*9203SMark.Logan@Sun.COM return true; 82*9203SMark.Logan@Sun.COM } 83*9203SMark.Logan@Sun.COM } 84*9203SMark.Logan@Sun.COM } 85*9203SMark.Logan@Sun.COM version = GetProcessVersion(ATVersion::appSearchPath + appName); 86*9203SMark.Logan@Sun.COM if (version.empty()) { 87*9203SMark.Logan@Sun.COM version = GetProcessVersion(appName); 88*9203SMark.Logan@Sun.COM } 89*9203SMark.Logan@Sun.COM return false; 90*9203SMark.Logan@Sun.COM } 91*9203SMark.Logan@Sun.COM 92*9203SMark.Logan@Sun.COM std::string ATVersion::GetProcessVersion(std::string cmd) 93*9203SMark.Logan@Sun.COM { 94*9203SMark.Logan@Sun.COM if (cmd.empty()) { 95*9203SMark.Logan@Sun.COM return ""; 96*9203SMark.Logan@Sun.COM } 97*9203SMark.Logan@Sun.COM 98*9203SMark.Logan@Sun.COM FILE *fp = popen((cmd + " " AT_VERSION_ARGUMENT " 2>/dev/null").c_str(), "r"); 99*9203SMark.Logan@Sun.COM if (fp) { 100*9203SMark.Logan@Sun.COM char buf[AT_VERSION_MAXSIZE + 1]; 101*9203SMark.Logan@Sun.COM int res = fscanf(fp, AT_VERSION_SCAN_FORMAT, buf); 102*9203SMark.Logan@Sun.COM buf[AT_VERSION_MAXSIZE] = '\0'; 103*9203SMark.Logan@Sun.COM pclose(fp); 104*9203SMark.Logan@Sun.COM if (1 == res) { 105*9203SMark.Logan@Sun.COM return buf; 106*9203SMark.Logan@Sun.COM } 107*9203SMark.Logan@Sun.COM } 108*9203SMark.Logan@Sun.COM return ""; 109*9203SMark.Logan@Sun.COM } 110*9203SMark.Logan@Sun.COM 111*9203SMark.Logan@Sun.COM bool ATVersion::IsAppRunning(const char *appName, std::list<unsigned long> &pids) 112*9203SMark.Logan@Sun.COM { 113*9203SMark.Logan@Sun.COM struct dirent **namelist; 114*9203SMark.Logan@Sun.COM FILE *stat; 115*9203SMark.Logan@Sun.COM char name_str[AT_APPNAME_MAXSIZE + 1]; 116*9203SMark.Logan@Sun.COM int num_entries; 117*9203SMark.Logan@Sun.COM char status_path[256]; 118*9203SMark.Logan@Sun.COM unsigned long pid; 119*9203SMark.Logan@Sun.COM unsigned long selfpid = 0; 120*9203SMark.Logan@Sun.COM bool res = false; 121*9203SMark.Logan@Sun.COM int ret; 122*9203SMark.Logan@Sun.COM 123*9203SMark.Logan@Sun.COM pids.clear(); 124*9203SMark.Logan@Sun.COM 125*9203SMark.Logan@Sun.COM memset(status_path, '\0', sizeof(status_path)); 126*9203SMark.Logan@Sun.COM snprintf(status_path, sizeof(status_path), AT_PIDFILE_NAME_FORMAT, appName); 127*9203SMark.Logan@Sun.COM std::ifstream pidf(status_path); 128*9203SMark.Logan@Sun.COM if (pidf.is_open()) { 129*9203SMark.Logan@Sun.COM pidf >> pid; 130*9203SMark.Logan@Sun.COM pidf.close(); 131*9203SMark.Logan@Sun.COM if (!(GetAppPathByPid(pid).empty())) { 132*9203SMark.Logan@Sun.COM pids.push_back(pid); 133*9203SMark.Logan@Sun.COM return true; 134*9203SMark.Logan@Sun.COM } 135*9203SMark.Logan@Sun.COM } 136*9203SMark.Logan@Sun.COM 137*9203SMark.Logan@Sun.COM memset(status_path, '\0', sizeof(status_path)); 138*9203SMark.Logan@Sun.COM snprintf(status_path, sizeof(status_path), AT_DEF_PIDFILE_NAME_FORMAT, appName); 139*9203SMark.Logan@Sun.COM pidf.open(status_path); 140*9203SMark.Logan@Sun.COM if (pidf.is_open()) { 141*9203SMark.Logan@Sun.COM pidf >> pid; 142*9203SMark.Logan@Sun.COM pidf.close(); 143*9203SMark.Logan@Sun.COM if (!(GetAppPathByPid(pid).empty())) { 144*9203SMark.Logan@Sun.COM pids.push_back(pid); 145*9203SMark.Logan@Sun.COM return true; 146*9203SMark.Logan@Sun.COM } 147*9203SMark.Logan@Sun.COM } 148*9203SMark.Logan@Sun.COM 149*9203SMark.Logan@Sun.COM num_entries = scandir("/proc", &namelist, 0, alphasort); 150*9203SMark.Logan@Sun.COM if (num_entries < 0) { 151*9203SMark.Logan@Sun.COM return false; 152*9203SMark.Logan@Sun.COM } 153*9203SMark.Logan@Sun.COM 154*9203SMark.Logan@Sun.COM memset(status_path, '\0', sizeof(status_path)); 155*9203SMark.Logan@Sun.COM if (-1 != readlink("/proc/self", status_path, sizeof(status_path))) { 156*9203SMark.Logan@Sun.COM selfpid = std::atol(status_path); 157*9203SMark.Logan@Sun.COM } 158*9203SMark.Logan@Sun.COM 159*9203SMark.Logan@Sun.COM while (num_entries--) { 160*9203SMark.Logan@Sun.COM char *pidstr = namelist[num_entries]->d_name; 161*9203SMark.Logan@Sun.COM if ((pidstr) && (pidstr[0] > '0') && (pidstr[0] <= '9')) { 162*9203SMark.Logan@Sun.COM pid = std::atol(pidstr); 163*9203SMark.Logan@Sun.COM if (pid != selfpid) { 164*9203SMark.Logan@Sun.COM /* for process name we check the 'status' entry */ 165*9203SMark.Logan@Sun.COM memset(status_path, '\0', sizeof(status_path)); 166*9203SMark.Logan@Sun.COM snprintf(status_path, sizeof(status_path), "/proc/%lu/status", pid); 167*9203SMark.Logan@Sun.COM if (NULL != (stat = fopen(status_path, "r"))) { 168*9203SMark.Logan@Sun.COM memset(name_str, '\0', sizeof(name_str)); 169*9203SMark.Logan@Sun.COM ret = fscanf(stat, AT_PROCSTAT_NAME_FORMAT, name_str); 170*9203SMark.Logan@Sun.COM fclose(stat); 171*9203SMark.Logan@Sun.COM if ((1 == ret) && (strncmp(name_str, appName, 15) == 0)) { 172*9203SMark.Logan@Sun.COM pids.push_back(pid); 173*9203SMark.Logan@Sun.COM res = true; 174*9203SMark.Logan@Sun.COM } 175*9203SMark.Logan@Sun.COM } 176*9203SMark.Logan@Sun.COM } 177*9203SMark.Logan@Sun.COM } 178*9203SMark.Logan@Sun.COM free(namelist[num_entries]); 179*9203SMark.Logan@Sun.COM } 180*9203SMark.Logan@Sun.COM free(namelist); 181*9203SMark.Logan@Sun.COM 182*9203SMark.Logan@Sun.COM return res; 183*9203SMark.Logan@Sun.COM } 184*9203SMark.Logan@Sun.COM 185*9203SMark.Logan@Sun.COM 186*9203SMark.Logan@Sun.COM std::string ATVersion::GetAppPathByPid(unsigned long pid) 187*9203SMark.Logan@Sun.COM { 188*9203SMark.Logan@Sun.COM char path[256]; 189*9203SMark.Logan@Sun.COM char exe_buf[PATH_MAX]; 190*9203SMark.Logan@Sun.COM 191*9203SMark.Logan@Sun.COM memset(path, '\0', sizeof(path)); 192*9203SMark.Logan@Sun.COM snprintf(path, sizeof(path), "/proc/%lu/exe", pid); 193*9203SMark.Logan@Sun.COM memset(exe_buf, '\0', PATH_MAX); 194*9203SMark.Logan@Sun.COM if (-1 == readlink(path, exe_buf, PATH_MAX)) { 195*9203SMark.Logan@Sun.COM return ""; 196*9203SMark.Logan@Sun.COM } 197*9203SMark.Logan@Sun.COM 198*9203SMark.Logan@Sun.COM if (NULL != strstr(exe_buf, " (deleted)")) { 199*9203SMark.Logan@Sun.COM return ""; 200*9203SMark.Logan@Sun.COM } 201*9203SMark.Logan@Sun.COM 202*9203SMark.Logan@Sun.COM return exe_buf; 203*9203SMark.Logan@Sun.COM } 204*9203SMark.Logan@Sun.COM 205