Mercurial > ecos-v2_0-branch
comparison host/tools/ecostest/common/TestResource.cpp @ 76:435cced73e2f ecos-v1_3_1-release
eCos v1.3.1 merged from eCos master repository on 2000-03-27-23:22:51-BST
| author | jlarmour |
|---|---|
| date | Tue, 28 Mar 2000 14:10:45 +0000 |
| parents | |
| children | 6736c52df507 |
comparison
equal
deleted
inserted
replaced
| 75:41bf073c0c32 | 76:435cced73e2f |
|---|---|
| 1 //####COPYRIGHTBEGIN#### | |
| 2 // | |
| 3 // ---------------------------------------------------------------------------- | |
| 4 // Copyright (C) 1998, 1999, 2000 Red Hat, Inc. | |
| 5 // | |
| 6 // This program is part of the eCos host tools. | |
| 7 // | |
| 8 // This program is free software; you can redistribute it and/or modify it | |
| 9 // under the terms of the GNU General Public License as published by the Free | |
| 10 // Software Foundation; either version 2 of the License, or (at your option) | |
| 11 // any later version. | |
| 12 // | |
| 13 // This program is distributed in the hope that it will be useful, but WITHOUT | |
| 14 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 15 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | |
| 16 // more details. | |
| 17 // | |
| 18 // You should have received a copy of the GNU General Public License along with | |
| 19 // this program; if not, write to the Free Software Foundation, Inc., | |
| 20 // 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |
| 21 // | |
| 22 // ---------------------------------------------------------------------------- | |
| 23 // | |
| 24 //####COPYRIGHTEND#### | |
| 25 //================================================================= | |
| 26 // | |
| 27 // TestResource.cpp | |
| 28 // | |
| 29 // Resource test class | |
| 30 // | |
| 31 //================================================================= | |
| 32 //================================================================= | |
| 33 //#####DESCRIPTIONBEGIN#### | |
| 34 // | |
| 35 // Author(s): sdf | |
| 36 // Contributors: sdf | |
| 37 // Date: 1999-04-01 | |
| 38 // Description: This class abstracts a test resource for use in the testing infrastructure | |
| 39 // Usage: | |
| 40 // | |
| 41 //####DESCRIPTIONEND#### | |
| 42 #include "eCosStd.h" | |
| 43 #include "eCosTestUtils.h" | |
| 44 #include "eCosTrace.h" | |
| 45 #ifdef _WIN32 | |
| 46 #include "Subprocess.h" | |
| 47 #endif | |
| 48 #include "TestResource.h" | |
| 49 | |
| 50 CTestResource *CTestResource::pFirstInstance=0; | |
| 51 unsigned int CTestResource::nCount=0; | |
| 52 | |
| 53 String CTestResource::strResourceHost; | |
| 54 int CTestResource::nResourcePort; | |
| 55 | |
| 56 CTestResource::CTestResource(LPCTSTR target, LPCTSTR pszDownloadPort, int nBaud, LPCTSTR pszResetString): | |
| 57 m_strReset(pszResetString), | |
| 58 m_bInUse(false), | |
| 59 m_nBaud(nBaud), | |
| 60 m_strPort(pszDownloadPort), | |
| 61 m_bLocked(false), | |
| 62 m_Target(target), | |
| 63 m_strHost(CeCosTestUtils::HostName()), | |
| 64 m_nPort(0) | |
| 65 { | |
| 66 VTRACE(_T("@@@ Created resource %08x %s\n"),(unsigned int)this,(LPCTSTR)Output()); | |
| 67 Chain(); | |
| 68 } | |
| 69 | |
| 70 CTestResource::~CTestResource() | |
| 71 { | |
| 72 ENTERCRITICAL; | |
| 73 VTRACE(_T("@@@ Destroy resource %08x %s\n"),this,(LPCTSTR)Output()); | |
| 74 if(m_pPrevInstance || m_pNextInstance){ | |
| 75 nCount--; | |
| 76 } | |
| 77 if(pFirstInstance==this){ | |
| 78 pFirstInstance=m_pNextInstance; | |
| 79 } | |
| 80 if(m_pPrevInstance){ | |
| 81 m_pPrevInstance->m_pNextInstance=m_pNextInstance; | |
| 82 } | |
| 83 if(m_pNextInstance){ | |
| 84 m_pNextInstance->m_pPrevInstance=m_pPrevInstance; | |
| 85 } | |
| 86 LEAVECRITICAL; | |
| 87 } | |
| 88 | |
| 89 // Find the resource matching the given host:port specification | |
| 90 // Returns 0 if no such host:port found | |
| 91 CTestResource * CTestResource::Lookup(LPCTSTR pszHost, int nPort) | |
| 92 { | |
| 93 CTestResource *pResource; | |
| 94 ENTERCRITICAL; | |
| 95 for(pResource=pFirstInstance;pResource;pResource=pResource->m_pNextInstance){ | |
| 96 if(nPort==pResource->TcpipPort() && 0==_tcsicmp(pszHost,pResource->Host())){ | |
| 97 break; | |
| 98 } | |
| 99 } | |
| 100 LEAVECRITICAL; | |
| 101 return pResource; | |
| 102 } | |
| 103 | |
| 104 unsigned int CTestResource::GetMatchCount (const CeCosTest::ExecutionParameters &e,bool bIgnoreLocking) | |
| 105 { | |
| 106 unsigned int i=0; | |
| 107 ENTERCRITICAL; | |
| 108 for(const CTestResource *pResource=pFirstInstance;pResource;pResource=pResource->m_pNextInstance){ | |
| 109 if(pResource->Matches(e,bIgnoreLocking)){ | |
| 110 i++; | |
| 111 } | |
| 112 } | |
| 113 LEAVECRITICAL; | |
| 114 return i; | |
| 115 } | |
| 116 | |
| 117 bool CTestResource::GetMatches (const CeCosTest::ExecutionParameters &e, StringArray &arstr, bool bIgnoreLocking) | |
| 118 { | |
| 119 bool rc=false; | |
| 120 arstr.clear(); | |
| 121 if(LoadSocket()){ | |
| 122 ENTERCRITICAL; | |
| 123 for(CTestResource *pResource=pFirstInstance;pResource;pResource=pResource->m_pNextInstance){ | |
| 124 if(pResource->Matches(e,bIgnoreLocking)){ | |
| 125 arstr.push_back(CeCosTestSocket::HostPort(pResource->Host(),pResource->TcpipPort())); | |
| 126 } | |
| 127 } | |
| 128 LEAVECRITICAL; | |
| 129 rc=true; | |
| 130 } | |
| 131 return rc; | |
| 132 } | |
| 133 | |
| 134 void CTestResource::DeleteAllInstances() | |
| 135 { | |
| 136 ENTERCRITICAL; | |
| 137 while(pFirstInstance){ | |
| 138 delete pFirstInstance; | |
| 139 } | |
| 140 LEAVECRITICAL; | |
| 141 } | |
| 142 | |
| 143 bool CTestResource::LoadFile (LPCTSTR psz,void *key) | |
| 144 { | |
| 145 bool rc=true; | |
| 146 ENTERCRITICAL; | |
| 147 DeleteAllInstances(); | |
| 148 #ifdef _WIN32 | |
| 149 if(key){ | |
| 150 // Find all the keys under "psz" and load from each of them | |
| 151 HKEY hKey; | |
| 152 if(ERROR_SUCCESS==RegOpenKeyEx ((HKEY)key, psz, 0L, KEY_ENUMERATE_SUB_KEYS, &hKey)){ | |
| 153 TCHAR szName[256]; | |
| 154 DWORD dwSizeName=sizeof szName; | |
| 155 FILETIME ftLastWriteTime; | |
| 156 for(DWORD dwIndex=0;ERROR_SUCCESS==RegEnumKeyEx(hKey, dwIndex, szName, &dwSizeName, NULL, NULL, NULL, &ftLastWriteTime); dwIndex++){ | |
| 157 CTestResource *pResource=new CTestResource(_T("")); | |
| 158 String strKey; | |
| 159 strKey.Format(_T("%s\\%s"),psz,szName); | |
| 160 CTestResourceProperties prop1(pResource,strKey,key); | |
| 161 prop1.SetDefaults(); | |
| 162 prop1.Load(); | |
| 163 dwSizeName=sizeof szName; | |
| 164 } | |
| 165 RegCloseKey(hKey); | |
| 166 } | |
| 167 } else | |
| 168 #endif | |
| 169 { | |
| 170 // Find all the files in directory "psz" and load from each of them | |
| 171 void *pHandle; | |
| 172 TCHAR szOrigDir[256]; | |
| 173 _tgetcwd(szOrigDir,sizeof szOrigDir-1); | |
| 174 if(0==_tchdir(psz)){ | |
| 175 String strFile; | |
| 176 for(bool b=CeCosTestUtils::StartSearch(pHandle,strFile);b;b=CeCosTestUtils::NextFile(pHandle,strFile)){ | |
| 177 struct _stat buf; | |
| 178 if(0==_tstat(strFile,&buf) && 0==(S_IFDIR&buf.st_mode)){ | |
| 179 CTestResource *pResource=new CTestResource(_T("")); | |
| 180 CTestResourceProperties prop1(pResource,strFile); | |
| 181 prop1.SetDefaults(); | |
| 182 prop1.Load(); | |
| 183 } | |
| 184 } | |
| 185 CeCosTestUtils::EndSearch(pHandle); | |
| 186 } else { | |
| 187 TRACE(_T("Failed to change to %s from %s\n"),psz,szOrigDir); | |
| 188 } | |
| 189 _tchdir(szOrigDir); | |
| 190 } | |
| 191 LEAVECRITICAL; | |
| 192 | |
| 193 return rc; | |
| 194 } | |
| 195 | |
| 196 bool CTestResource::SaveFile (LPCTSTR psz,void *key) | |
| 197 { | |
| 198 bool rc=false; | |
| 199 ENTERCRITICAL; | |
| 200 #ifdef _WIN32 | |
| 201 if(key){ | |
| 202 // Delete all the keys under "psz" | |
| 203 HKEY hKey; | |
| 204 if(ERROR_SUCCESS==RegOpenKeyEx ((HKEY)key, psz, 0L, KEY_ENUMERATE_SUB_KEYS, &hKey)){ | |
| 205 TCHAR szName[256]; | |
| 206 DWORD dwSizeName=sizeof szName; | |
| 207 FILETIME ftLastWriteTime; | |
| 208 DWORD dwIndex; | |
| 209 if(ERROR_SUCCESS==RegQueryInfoKey(hKey,0,0,0,&dwIndex,0,0,0,0,0,0,0)){ | |
| 210 while((signed)--dwIndex>=0){ | |
| 211 if(ERROR_SUCCESS!=RegEnumKeyEx(hKey, dwIndex, szName, &dwSizeName, NULL, NULL, NULL, &ftLastWriteTime) || | |
| 212 ERROR_SUCCESS!=RegDeleteKey(hKey,szName)){ | |
| 213 rc=false; | |
| 214 } | |
| 215 dwSizeName=sizeof szName; | |
| 216 } | |
| 217 } | |
| 218 RegCloseKey(hKey); | |
| 219 } | |
| 220 } else | |
| 221 #endif | |
| 222 { | |
| 223 // Delete all the files under directory "psz" | |
| 224 void *pHandle; | |
| 225 TCHAR szOrigDir[256]; | |
| 226 _tgetcwd(szOrigDir,sizeof szOrigDir-1); | |
| 227 if(0==_tchdir(psz)){ | |
| 228 String strFile; | |
| 229 for(bool b=CeCosTestUtils::StartSearch(pHandle,strFile);b;b=CeCosTestUtils::NextFile(pHandle,strFile)){ | |
| 230 struct _stat buf; | |
| 231 if(0==_tstat(strFile,&buf) && 0==(S_IFDIR&buf.st_mode)){ | |
| 232 _tunlink(strFile); | |
| 233 } | |
| 234 } | |
| 235 CeCosTestUtils::EndSearch(pHandle); | |
| 236 } else { | |
| 237 fprintf(stderr,"Failed to change to %s from %s\n",psz,szOrigDir); | |
| 238 } | |
| 239 _tchdir(szOrigDir); | |
| 240 } | |
| 241 | |
| 242 rc=true; | |
| 243 for(CTestResource *pResource=pFirstInstance;pResource;pResource=pResource->m_pNextInstance){ | |
| 244 String strName; | |
| 245 if(key){ | |
| 246 strName.Format(_T("%s\\%s-%d"),psz,(LPCTSTR)pResource->m_strHost,pResource->m_nPort); | |
| 247 CTestResourceProperties prop1(pResource,strName,key); | |
| 248 rc&=prop1.Save(); | |
| 249 } else { | |
| 250 strName.Format(_T("%s%c%s-%d"),psz,cPathsep,(LPCTSTR)pResource->m_strHost,pResource->m_nPort); | |
| 251 CTestResourceProperties prop1(pResource,strName,key); | |
| 252 rc&=prop1.Save(); | |
| 253 } | |
| 254 | |
| 255 } | |
| 256 LEAVECRITICAL; | |
| 257 | |
| 258 return rc; | |
| 259 } | |
| 260 | |
| 261 CTestResource::CTestResourceProperties::CTestResourceProperties(CTestResource *pResource,LPCTSTR psz,void *key): | |
| 262 CProperties(psz,key) | |
| 263 { | |
| 264 CProperties::Add(_T("Baud"), pResource->m_nBaud,0); | |
| 265 Add(_T("BoardId"), pResource->m_strBoardID); | |
| 266 Add(_T("Date"), pResource->m_strDate); | |
| 267 Add(_T("Email"), pResource->m_strEmail); | |
| 268 Add(_T("Host"), pResource->m_strHost); | |
| 269 CProperties::Add(_T("Locked"), pResource->m_bLocked,0); | |
| 270 Add(_T("Originator"), pResource->m_strUser); | |
| 271 CProperties::Add(_T("Port"), pResource->m_nPort); | |
| 272 Add(_T("Reason"), pResource->m_strReason); | |
| 273 Add(_T("Reset"), pResource->m_strReset); | |
| 274 Add(_T("Serial"), pResource->m_strPort); | |
| 275 Add(_T("Target"), pResource->m_Target); | |
| 276 Add(_T("User"), pResource->m_strUser); | |
| 277 } | |
| 278 | |
| 279 bool CTestResource::Lock() | |
| 280 { | |
| 281 if(!m_bLocked){ | |
| 282 m_bLocked=true; | |
| 283 return true; | |
| 284 } else { | |
| 285 return false; | |
| 286 } | |
| 287 } | |
| 288 | |
| 289 bool CTestResource::Unlock() | |
| 290 { | |
| 291 if(m_bLocked){ | |
| 292 m_bLocked=false; | |
| 293 return true; | |
| 294 } else { | |
| 295 return false; | |
| 296 } | |
| 297 } | |
| 298 | |
| 299 bool CTestResource::LoadSocket(LPCTSTR pszResourceHost,int nResourcePort,Duration dTimeout/*=10*1000*/) | |
| 300 { | |
| 301 bool rc=false; | |
| 302 ENTERCRITICAL; | |
| 303 CTestResource *pResource; | |
| 304 // If the resource is in use, we don't dare delete it! | |
| 305 for(pResource=CTestResource::First();pResource;pResource=pResource->Next()){ | |
| 306 pResource->m_bFlag=false; | |
| 307 } | |
| 308 CeCosTestSocket sock; | |
| 309 if(sock.Connect(pszResourceHost,nResourcePort,dTimeout)){ | |
| 310 // Write the message to the socket | |
| 311 int nRequest=0; // read | |
| 312 if(!sock.sendInteger(nRequest)){ | |
| 313 ERROR(_T("Failed to write to socket\n")); | |
| 314 } else { | |
| 315 int nResources; | |
| 316 if(sock.recvInteger(nResources,_T(""),dTimeout)){ | |
| 317 rc=true; | |
| 318 while(nResources--){ | |
| 319 String strImage; | |
| 320 if(sock.recvString(strImage,_T(""),dTimeout)){ | |
| 321 VTRACE(_T("Recv \"%s\"\n"),(LPCTSTR)strImage); | |
| 322 CTestResource tmp; | |
| 323 tmp.FromStr(strImage); | |
| 324 CTestResource *pResource=Lookup(tmp.Host(),tmp.TcpipPort()); | |
| 325 if(0==pResource){ | |
| 326 pResource=new CTestResource(_T("")); | |
| 327 } | |
| 328 pResource->FromStr(strImage); | |
| 329 pResource->m_bFlag=true; | |
| 330 } else { | |
| 331 rc=false; | |
| 332 break; | |
| 333 } | |
| 334 } | |
| 335 } | |
| 336 } | |
| 337 } | |
| 338 // If the resource is in use, we don't dare delete it! | |
| 339 CTestResource *pNext; | |
| 340 for(pResource=CTestResource::First();pResource;pResource=pNext){ | |
| 341 pNext=pResource->Next(); | |
| 342 if(!pResource->m_bFlag && !pResource->m_bInUse){ | |
| 343 delete pResource; | |
| 344 } | |
| 345 } | |
| 346 | |
| 347 LEAVECRITICAL; | |
| 348 return rc; | |
| 349 } | |
| 350 | |
| 351 void CTestResource::Image(String &str) | |
| 352 { | |
| 353 CTestResourceProperties prop(this); | |
| 354 str=prop.MakeCommandString(); | |
| 355 VTRACE(_T("Make command string %s\n"),(LPCTSTR)str); | |
| 356 } | |
| 357 | |
| 358 bool CTestResource::FromStr(LPCTSTR pszImage) | |
| 359 { | |
| 360 CTestResourceProperties prop(this); | |
| 361 prop.LoadFromCommandString(pszImage); | |
| 362 VTRACE(_T("From command string %s\n"),pszImage); | |
| 363 return true; | |
| 364 } | |
| 365 | |
| 366 void CTestResource::Chain() | |
| 367 { | |
| 368 ENTERCRITICAL; | |
| 369 nCount++; | |
| 370 m_pNextInstance=pFirstInstance; | |
| 371 if(m_pNextInstance){ | |
| 372 m_pNextInstance->m_pPrevInstance=this; | |
| 373 } | |
| 374 m_pPrevInstance=0; | |
| 375 pFirstInstance=this; | |
| 376 LEAVECRITICAL; | |
| 377 } | |
| 378 | |
| 379 bool CTestResource::Matches (const CeCosTest::ExecutionParameters &e,bool bIgnoreLocking) const | |
| 380 { | |
| 381 return (bIgnoreLocking||(!m_bLocked)) && (0==_tcsicmp(e.Target(),m_Target)); | |
| 382 }; | |
| 383 | |
| 384 bool CTestResource::SaveSocket(LPCTSTR pszResourceServer,int nResourcePort,Duration dTimeout) | |
| 385 { | |
| 386 bool rc=true; | |
| 387 ENTERCRITICAL; | |
| 388 CeCosTestSocket sock(pszResourceServer,nResourcePort, dTimeout); | |
| 389 if(sock.Ok()){ | |
| 390 // Write the message to the socket | |
| 391 int nRequest=1; //write | |
| 392 if(!sock.sendInteger(nRequest, _T(""),dTimeout)){ | |
| 393 ERROR(_T("Failed to write to socket\n")); | |
| 394 rc=false; | |
| 395 } else { | |
| 396 int nResources=0; | |
| 397 CTestResource *pResource; | |
| 398 for(pResource=CTestResource::First();pResource;pResource=pResource->Next()){ | |
| 399 nResources++; | |
| 400 } | |
| 401 if(sock.sendInteger(nResources,_T("resource count"),dTimeout)){ | |
| 402 for(pResource=CTestResource::First();pResource;pResource=pResource->Next()){ | |
| 403 String strImage; | |
| 404 pResource->Image(strImage); | |
| 405 TRACE(_T("Send \"%s\"\n"),(LPCTSTR)strImage); | |
| 406 if(!sock.sendString (strImage, _T("reply"),dTimeout)){ | |
| 407 rc=false; | |
| 408 break; | |
| 409 } | |
| 410 } | |
| 411 } else { | |
| 412 rc=false; | |
| 413 } | |
| 414 } | |
| 415 } else { | |
| 416 rc=false; | |
| 417 } | |
| 418 LEAVECRITICAL; | |
| 419 return rc; | |
| 420 } | |
| 421 | |
| 422 CeCosTest::ServerStatus CTestResource::Query() | |
| 423 { | |
| 424 CeCosTest::ExecutionParameters e(CeCosTest::ExecutionParameters::QUERY,m_Target); | |
| 425 CeCosTestSocket *pSock=0; | |
| 426 CeCosTest::ServerStatus s=CeCosTest::Connect(m_strHost,m_nPort,pSock,e,m_strInfo); | |
| 427 delete pSock; | |
| 428 return s; | |
| 429 } | |
| 430 | |
| 431 int CTestResource::Count(const CeCosTest::ExecutionParameters &e) | |
| 432 { | |
| 433 int nCount=0; | |
| 434 for(const CTestResource *p=pFirstInstance;p;p=p->m_pNextInstance){ | |
| 435 if(p->Matches(e)){ | |
| 436 nCount++; | |
| 437 } | |
| 438 } | |
| 439 return nCount; | |
| 440 } | |
| 441 | |
| 442 bool CTestResource::Use() | |
| 443 { | |
| 444 bool rc; | |
| 445 ENTERCRITICAL; | |
| 446 if(m_bInUse){ | |
| 447 rc=false; | |
| 448 } else { | |
| 449 m_bInUse=true; | |
| 450 rc=true; | |
| 451 } | |
| 452 LEAVECRITICAL; | |
| 453 return rc; | |
| 454 } | |
| 455 | |
| 456 CTestResource *CTestResource::GetResource (const CeCosTest::ExecutionParameters &e) | |
| 457 { | |
| 458 CTestResource *p=0; | |
| 459 if(0==Count(e)){ | |
| 460 ERROR(_T("GetResource: no candidates available\n")); | |
| 461 } else { | |
| 462 ENTERCRITICAL; | |
| 463 for(p=pFirstInstance;p;p=p->m_pNextInstance){ | |
| 464 if(p->Matches(e) && !p->m_bInUse){ | |
| 465 TRACE(_T("Acquired %s\n"),p->Serial()); | |
| 466 p->Use(); | |
| 467 break; | |
| 468 } | |
| 469 } | |
| 470 LEAVECRITICAL; | |
| 471 } | |
| 472 return p; | |
| 473 } | |
| 474 | |
| 475 String CTestResource::Output() const | |
| 476 { | |
| 477 String str; | |
| 478 str.Format( | |
| 479 _T("%10s:%d %20s %8s"), | |
| 480 Host(), | |
| 481 TcpipPort(), | |
| 482 Target(), | |
| 483 Serial()); | |
| 484 if(HasReset()){ | |
| 485 str+=_T(" Reset:"); | |
| 486 str+=m_strReset; | |
| 487 } | |
| 488 if(IsLocked()){ | |
| 489 str+=_T(" [RL]"); | |
| 490 } | |
| 491 return str; | |
| 492 } | |
| 493 | |
| 494 bool CTestResource::Matches(LPCTSTR pszHost, int nPort, const CeCosTest::ExecutionParameters &e) | |
| 495 { | |
| 496 bool rc=false; | |
| 497 ENTERCRITICAL; | |
| 498 if(LoadSocket()){ | |
| 499 CTestResource *pResource=Lookup(pszHost,nPort); | |
| 500 if(pResource){ | |
| 501 rc=pResource->Matches(e); | |
| 502 } | |
| 503 } | |
| 504 LEAVECRITICAL; | |
| 505 return rc; | |
| 506 } | |
| 507 | |
| 508 CResetAttributes::ResetResult CTestResource::Reset(LogFunc *pfnLog, void *pfnLogparam) | |
| 509 { | |
| 510 String strReset; | |
| 511 strReset.Format(_T("port(%s,%d) %s"),Serial(),Baud(),ResetString()); | |
| 512 return CResetAttributes(strReset).Reset(pfnLog,pfnLogparam); | |
| 513 } | |
| 514 | |
| 515 CResetAttributes::ResetResult CTestResource::Reset(String &str) | |
| 516 { | |
| 517 return Reset(StringLogFunc,&str); | |
| 518 } | |
| 519 | |
| 520 void CALLBACK CTestResource::StringLogFunc (void *pParam,LPCTSTR psz) | |
| 521 { | |
| 522 *((String *)pParam)+=psz; | |
| 523 } | |
| 524 | |
| 525 | |
| 526 CResetAttributes::ResetResult CTestResource::RemoteReset(LogFunc *pfnLog, void *pfnLogparam) | |
| 527 { | |
| 528 String strCmd; | |
| 529 strCmd.Format(_T("rsh %s x10reset %s\n"),Host(),ResetString()); | |
| 530 pfnLog(pfnLogparam,strCmd); | |
| 531 | |
| 532 #ifdef _WIN32 | |
| 533 // because this can be used from GUI tools | |
| 534 CSubprocess sp; | |
| 535 sp.Run(pfnLog,pfnLogparam,strCmd); | |
| 536 #else // UNIX | |
| 537 FILE *f=POPEN(strCmd,"rt"); | |
| 538 if(f){ | |
| 539 char buf[80]; | |
| 540 while(fgets(buf,sizeof buf,f)){ | |
| 541 pfnLog(pfnLogparam,buf); | |
| 542 } | |
| 543 PCLOSE(f); | |
| 544 } else { | |
| 545 String strMsg; | |
| 546 strMsg.Format(_T("Failed to execute '%s'\n"),(LPCTSTR)strCmd); | |
| 547 pfnLog(pfnLogparam,strMsg); | |
| 548 } | |
| 549 #endif | |
| 550 return CResetAttributes::RESET_OK; // FIXME | |
| 551 } | |
| 552 |
