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
ShowVersionIfArg(int argc,const char ** argv,const char * versionStr)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
GetAppVersion(const char * appName,std::string & version)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
GetProcessVersion(std::string cmd)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
IsAppRunning(const char * appName,std::list<unsigned long> & pids)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
GetAppPathByPid(unsigned long pid)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