00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062 #ifdef _MSC_VER
00063 #pragma warning(disable:4786)
00064 #define _X86_
00065 #include <cstdarg>
00066 #include <windef.h>
00067 #include <winbase.h>
00068
00069 #include <direct.h>
00070
00071 #include <cstdio>
00072 #include <cstdlib>
00073 #include <string>
00074 #else
00075 #include <stdio.h>
00076 #include <stdlib.h>
00077 #include <string.h>
00078 #endif
00079
00080 #include "infolines.h"
00081 #include "abktypes.h"
00082 #include "abkassert.h"
00083
00084 #if defined(sun) || defined(__SUNPRO_CC)
00085 #include <sys/systeminfo.h>
00086 #endif
00087
00088 #ifdef linux
00089 #include <sys/utsname.h>
00090 #endif
00091
00092 #if defined(linux) || defined(sun) || defined(__SUNPRO_CC)
00093 #include <unistd.h>
00094 #include <pwd.h>
00095 #include <sys/stat.h>
00096 #endif
00097
00098
00099
00100 void abk_dump_stack()
00101 {
00102 return;
00103 #if defined(linux) || defined(sun) || defined(__SUNPRO_CC)
00104 printf("\n --- ABK GROUP DELIBERATE STACK DUMP ----------- \n\n");
00105 fflush(stdout);
00106 char s[160];
00107 unsigned ProcId=getpid();
00108 #if defined(linux)
00109 sprintf(s, "/bin/echo \"bt \nquit \\n\" | "
00110 "gdb -q /proc/%d/exe %d", ProcId,ProcId);
00111 #else
00112 sprintf(s, "/bin/echo \"where\\ndetach \\n\" | dbx - %d", ProcId);
00113 #endif
00114 system(s);
00115 printf(" ------------------ END STACK DUMP -------------- \n");
00116 fflush(stdout);
00117 #else
00118
00119
00120 #endif
00121 return;
00122 }
00123
00124 void abk_call_debugger()
00125 {
00126 #if defined(linux) || defined(sun) || defined(__SUNPRO_CC)
00127 unsigned ProcId=getpid();
00128 printf("\n --- ATTACHING DEBUGGER to process %d ", ProcId);
00129 printf(" (an ABKGROUP utility) --- \n\n");
00130 fflush(stdout);
00131 char s[160];
00132 #if defined(linux)
00133 sprintf(s, "gdb -q /proc/%d/exe %d", ProcId,ProcId);
00134 #else // must be Solaris
00135 sprintf(s, "dbx - %d", ProcId);
00136 #endif
00137 system(s);
00138 printf(" ------------------ CONTINUING -------------- \n");
00139 fflush(stdout);
00140 #else
00141 fprintf(stderr," abk_call_debugger(): Can't call debugger on this platform\n");
00142 fflush(stderr);
00143 #endif
00144 return;
00145 }
00146
00147 double getPeakMemoryUsage()
00148 {
00149
00150 #if ! (defined(sun) || defined(linux) || defined(__SUNPRO_CC))
00151 return -1;
00152 #endif
00153
00154 #if defined(sun) || defined(__SUNPRO_CC)
00155 char procFileName[20];
00156 unsigned pid=getpid();
00157 sprintf(procFileName,"/proc/%d/as",pid);
00158 struct stat buf;
00159 if (stat(procFileName,&buf))
00160 {
00161 char procFileNameOld[20];
00162 sprintf(procFileNameOld,"/proc/%d",pid);
00163 if (stat(procFileNameOld,&buf))
00164 return -1.0;
00165 }
00166 return (1.0/(1024*1024)) * buf.st_size;
00167 #elif defined(linux)
00168 char buf[1000];
00169 sprintf(buf,"/proc/%d/stat", static_cast<unsigned>(getpid()));
00170 ifstream ifs(buf);
00171 for(unsigned k=0; k!=23; k++) ifs >> buf;
00172
00173 return (1.0/(1024*1024)) * atoi(buf);
00174 #else
00175 return -1;
00176 #endif
00177 }
00178
00179 static double getMemoryUsageEstimate();
00180
00181 MemUsage::MemUsage()
00182 {
00183 _peak=getPeakMemoryUsage();
00184 #if (defined(sun) || defined(__SUNPRO_CC) || defined(linux))
00185 _estimate=_peak;
00186 return ;
00187 #endif
00188 _estimate=getMemoryUsageEstimate();
00189 }
00190
00191 void MemChange::resetMark()
00192 {
00193 _memUsageMark=getMemoryUsageEstimate();
00194 }
00195
00196 MemChange::MemChange()
00197 {
00198 resetMark();
00199 }
00200
00201 MemChange::operator double() const
00202 {
00203 #if defined(sun) || defined(linux) || defined(__SUNPRO_CC)
00204 return getPeakMemoryUsage()-_memUsageMark;
00205 #else
00206 return -1.0;
00207 #endif
00208 }
00209
00210 Platform::Platform()
00211 {
00212 #if defined(sun) || defined(__SUNPRO_CC)
00213 Str31 sys, rel, arch, platf;
00214 sysinfo(SI_SYSNAME, sys, 31);
00215 sysinfo(SI_RELEASE, rel, 31);
00216 sysinfo(SI_ARCHITECTURE,arch, 31);
00217 sysinfo(SI_PLATFORM,platf, 31);
00218 _infoLine= new char[strlen(sys)+strlen(rel)+strlen(arch)+strlen(platf)+30];
00219 sprintf(_infoLine,"# Platform : %s %s %s %s \n",sys,rel,arch,platf);
00220 #elif defined(linux)
00221 struct utsname buf;
00222 uname(&buf);
00223 _infoLine= new char[strlen(buf.sysname)+strlen(buf.release)
00224 +strlen(buf.version)+strlen(buf.machine)+30];
00225 sprintf(_infoLine,"# Platform : %s %s %s %s \n",buf.sysname,buf.release,
00226 buf.version,buf.machine);
00227 #elif defined(_MSC_VER)
00228 _infoLine= new char[40];
00229 strcpy(_infoLine, "# Platform : MS Windows \n");
00230 #else
00231 _infoLine= new char[40];
00232 strcpy(_infoLine, "# Platform : unknown \n");
00233 #endif
00234 }
00235
00236 #if !defined(sun) && !defined(linux)
00237 extern int gethostname(char*, int);
00238 #endif
00239
00240 User::User()
00241 {
00242
00243
00244 #if defined(linux)
00245 char host[100];
00246 gethostname(host,31);
00247 struct passwd *pwr=getpwuid(getuid());
00248 if (pwr==NULL)
00249 {
00250 _infoLine= new char[40];
00251 strcpy(_infoLine, "# User : unknown \n");
00252 return;
00253 }
00254
00255 _infoLine= new char[strlen(pwr->pw_name)+strlen(pwr->pw_gecos)+130];
00256 sprintf(_infoLine,"# User : %s@%s (%s) \n",
00257 pwr->pw_name,host,pwr->pw_gecos);
00258 #elif defined(_MSC_VER)
00259 _infoLine= new char[40];
00260 strcpy(_infoLine, "# User : unknown \n");
00261 #else
00262 _infoLine= new char[40];
00263 strcpy(_infoLine, "# User : unknown \n");
00264 #endif
00265 }
00266
00267
00268
00269 const int kMegaByte=1024*1024;
00270 const int kSmallChunks=1000;
00271 const int kMaxAllocs=20000;
00272 const double MemUsageEps=3;
00273
00274
00275
00276 inline int memused()
00277 {
00278
00279 return static_cast<int>(getPeakMemoryUsage()*kMegaByte);
00280 }
00281
00282 double getMemoryUsageEstimate()
00283 {
00284 #if ! (defined(linux) || defined(sun) || defined(__SUNPRO_CC))
00285 return -1;
00286 #endif
00287 static int prevMem=0;
00288 static int extra;
00289 static int fail=0;
00290
00291 if (fail) return -1;
00292
00293
00294
00295
00296 void* ptr[kMaxAllocs];
00297 int numAllocs=0;
00298
00299 int last=memused();
00300
00301 if (last<=0) return -1;
00302
00303 int chunk=8192;
00304 int allocated=0;
00305 int countSmallChunks=kSmallChunks;
00306
00307 while (1)
00308 {
00309
00310 if (numAllocs>=kMaxAllocs)
00311 {
00312 abkwarn(0,"too many allocs (may be okay for 64-bit builds)");
00313
00314 for (int i=0; i!=numAllocs; ++i) free(ptr[i]);
00315 return -1.0;
00316 }
00317
00318 if (!(ptr[numAllocs++]=malloc(chunk)))
00319 {
00320 fail=1;
00321 return -1;
00322 }
00323
00324 allocated+=chunk;
00325 if (memused()>last+MemUsageEps)
00326 break;
00327 if (chunk<=kMegaByte && !countSmallChunks--)
00328 {
00329 chunk*=2;
00330 countSmallChunks=kSmallChunks;
00331 }
00332 }
00333
00334
00335
00336
00337
00338
00339
00340 for (int i=0; i!=numAllocs; ++i) free(ptr[i]);
00341
00342 extra=memused()-last;
00343
00344
00345
00346
00347 prevMem=memused()-allocated;
00348
00349 return prevMem/double(kMegaByte);
00350 }
00351
00352 UserHomeDir::UserHomeDir()
00353 {
00354 #if defined(sun) || defined(linux)
00355 struct passwd *pwrec;
00356 pwrec=getpwuid(getuid());
00357 _infoLine=strdup(pwrec->pw_dir);
00358 #elif defined(_MSC_VER)
00359 char *homedr=getenv("HOMEDRIVE");
00360 char *homepath=getenv("HOMEPATH");
00361 char *pathbuf=new char[_MAX_PATH];
00362 if (homedr==NULL || homepath==NULL)
00363 strcpy(pathbuf, "c:\\users\\default");
00364 else
00365 _makepath(pathbuf,homedr,homepath,NULL,NULL);
00366 int len=strlen(pathbuf);
00367 if (pathbuf[len-1]=='\\') pathbuf[len-1]='\0';
00368 _infoLine=strdup(pathbuf);
00369 delete [] pathbuf;
00370 #endif
00371 }
00372
00373 ExecLocation::ExecLocation()
00374 {
00375 char buf[1000]="";
00376 #ifdef linux
00377 readlink("/proc/self/exe", buf, 1000);
00378 int pos=strlen(buf)-1;
00379 for (;pos>=0;pos--)
00380 {
00381 if (buf[pos]=='/')
00382 {
00383 buf[pos]='\0';
00384 break;
00385 }
00386 }
00387 #endif
00388
00389 #if defined(sun) || defined(__SUNPRO_CC)
00390 pid_t pid=getpid();
00391 char tempfname[100]="";
00392 sprintf(tempfname,"/tmp/atempf%d",static_cast<int>(pid));
00393 sprintf(buf,"/usr/proc/bin/ptree %d | tail -4 > %s",
00394 static_cast<int>(pid),tempfname);
00395 system(buf);
00396 { ifstream ifs(tempfname); ifs >> buf; ifs >> buf;}
00397 unlink(tempfname);
00398 if (buf[0]!='/')
00399 {
00400 if (strrchr(buf,'/')==NULL)
00401 { getcwd(buf,1000); _infoLine=strdup(buf); return; }
00402 else
00403 {
00404 char buf1[500]="",buf2[1000]="";
00405 getcwd(buf1,500);
00406 strncpy(buf2,buf,500);
00407 sprintf(buf,"%s/%s",buf1,buf2);
00408 }
00409 }
00410 char *lastDelim=strrchr(buf,'/');
00411 if (lastDelim==NULL) sprintf(buf,"Cannot find");
00412 else *lastDelim='\0';
00413 #elif defined(_MSC_VER)
00414 ::GetModuleFileName(NULL,buf,995);
00415 char drv[_MAX_DRIVE],dir[_MAX_DIR],fname[_MAX_FNAME],ext[_MAX_EXT];
00416 _splitpath(buf,drv,dir,fname,ext);
00417 _makepath(buf,drv,dir,"","");
00418 int len=strlen(buf);
00419 if (buf[len-1]=='\\') buf[len-1]='\0';
00420 #endif
00421
00422 _infoLine=strdup(buf);
00423 }