GSaha567/seq_level_training_data
052
1text,length,is_long_context,metric_val,label_metric2"/*************************************************************************3* Copyright (c) 2015, Synopsys, Inc. *4* All rights reserved. *5* *6* Redistribution and use in source and binary forms, with or without *7* modification, are permitted provided that the following conditions are *8* met: *9* *10* 1. Redistributions of source code must retain the above copyright *11* notice, this list of conditions and the following disclaimer. *12* *13* 2. Redistributions in binary form must reproduce the above copyright *14* notice, this list of conditions and the following disclaimer in the *15* documentation and/or other materials provided with the distribution. *16* *17* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *18* ""AS IS"" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT *19* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR *20* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT *21* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, *22* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT *23* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, *24* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY *25* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *26* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE *27* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *28*************************************************************************/29#include <stdio.h>30#include <stdlib.h>31#include <string.h>32 33#ifdef _WIN3234#include <windows.h>35#include <winbase.h>36#include <winsock.h>37#include <ws2tcpip.h> // for socklen_t38#include <io.h>39#else40#include <errno.h>41#include <netdb.h>42#include <signal.h>43#include <unistd.h>44#include <arpa/inet.h>45#include <netinet/tcp.h>46#include <netinet/in.h>47#include <sys/socket.h>48#include <sys/stat.h>49#include <sys/types.h>50#include <sys/wait.h>51#ifdef sun552#include <poll.h>53#include <time.h>54#include <sys/time.h>55#include <sys/systeminfo.h>56#endif57#ifdef irix658#include <sys/poll.h>59#include <sys/systeminfo.h>60#endif61#ifdef hp70062#include <sys/poll.h>63#include <time.h>64extern ""C"" int select(int, int*, int*, int*, const struct timeval*);65#endif66#endif67 68#include ""nameServCalls.h""69 70#include ""debug.h""71#include ""startproc.h""72 73#ifdef XXX_enable_xerces_parsing74#include ""CmXml.h""75#include ""CmXmlException.h""76#else77class CmXml {78public:79 CmXml(char const*) {}80 char *getCmSystems() { return dup(""no_cm""); }81 bool isCmSystem(char const *) { return true; }82 83 char *getAttributes(char const*) { return dup(""""); }84 char *getCommands(char const*) { return dup(""""); }85 bool isAttribute(char const*, char const*) { return true; }86 char *translateCommand(char const*, char *[], int * = 0) { return NULL; }87 char *translateResult(char const*, char const*, char const *reply) { return dup(reply);}88 bool isCommand(char const *, char const *) { return true; }89 bool isReturnable(char const *, char const *) {return false; }90 void checkConsistency() {}91private:92 char *dup(char const *s) {93 char *res = new char[strlen(s) + 1];94 return strcpy(res, s);95 }96};97 98class CmXmlException {99public:100 char const* getMessage() const {return ""unlikely"";}101};102#endif103 104#include ""CmXmlStringTokenizer.h""105 106 107int do_debug = 0;108FILE* log_fd;109char dbgFileName[1024];110 111static int nClients = 0;112 113#ifndef _WIN32114#define closesocket(sock) close(sock)115#endif116 117// This is pointer to the object,118// which holds all information concerning work with 'cm.xml'.119static CmXml *cmXml = NULL;120 121static const int m_DriversNum = 3;122 123// this is types of CM realized in this driver124static const int CLEARCASE = 0;125static const int SI = 1;126static const int GENERIC = 2;127 128static const char* m_DriversSuffixes[m_DriversNum] = {129 ""CM:ClearCase"",130 ""CM:Source Integrity"",131 ""CM:Generic""132};133 134char m_DriversNames[m_DriversNum][1024];135 136typedef struct {137 // int m_DriversAddress[m_DriversNum];138 // int m_DriversPort[m_DriversNum];139 int m_DriversListeningSocket[m_DriversNum];140} CConnectionDescriptor;141static CConnectionDescriptor Connection;142static int do_shutdown = 0;143static int work_forever = 0;144 145static const char *REGISTER_CMD = ""register"";146static const char *UNREGISTER_CMD = ""unregister"";147static const char *UNCHECKOUT_CMD = ""uncheckout"";148static const char *CHECKOUT_CMD = ""checkout"";149static const char *CHECKIN_CMD = ""checkin"";150static const char *RESERVE_CMD = ""reserve"";151static const char *RESYNC_CMD = ""resync"";152static const char *UNRESERVE_CMD = ""unreserve"";153static const char *LOCALLIST_CMD = ""lsco"";154 155 156//--------------------------------------------------------------------------------------------157// This procedure will create a listen socket for client requests channel158//--------------------------------------------------------------------------------------------159int CreateListener() {160 int sock;161 struct sockaddr_in name;162 163 // Create the socket. 164 sock = socket (PF_INET, SOCK_STREAM, 0);165 if (sock < 0)166 return -1;167 168 unsigned int set_option = 1;169 setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const char *)&set_option, sizeof(set_option));170 171 // Give the socket a name. 172 name.sin_family = AF_INET;173 name.sin_port = 0;174 name.sin_addr.s_addr = htonl(INADDR_ANY);175 if (bind (sock, (struct sockaddr *) &name, sizeof (name)) < 0)176 return -1;177 if(listen(sock, 5) < 0)178 return -1;179 return sock;180}181//--------------------------------------------------------------------------------------------182 183//############################################################################################184// This class represents the client record in the clients linked list.185// Any client record contain client name, client TCP address and port and server TCP 186// address and port.187//############################################################################################188class ClientDescriptor {189public:190 ClientDescriptor(int id, 191 int client_socket,192 int client_port,193 int client_tcp_addr,194 int client_type);195 196 ~ClientDescriptor();197 static void AddNewClient(ClientDescriptor *sd);198 static void RemoveClient(int id);199 static void RemoveClient(ClientDescriptor *p);200 static void RemoveAllClients(void);201 static ClientDescriptor *LookupID(int id);202 int m_ID;203 int m_ClientSocket;204 int m_ClientPort;205 int m_ClientTCP;206 int m_ClientType;207 ClientDescriptor *m_Next;208 static ClientDescriptor *sd_list;209 static ClientDescriptor *sd_list_last;210 211 // Support for CM system's name, how 'CM:Generic' interface understands it.212public:213 char* getCmName();214 void setCmName(char *cm_name);215 216private:217 char *m_cmName;218 219 // Textual description of this client220public:221 char* getDescription();222 223private:224 char *m_Description;225 226};227 228ClientDescriptor *ClientDescriptor::sd_list = NULL;229ClientDescriptor *ClientDescriptor::sd_list_last = NULL;230//------------------------------------------------------------------------------------------------------231// Constructor will create new client with the client name232//------------------------------------------------------------------------------------------------------233ClientDescriptor::ClientDescriptor(int id, 234 int client_socket,235 int client_port, 236 int client_addr,237 int client_type) 238{239 this->m_ID = id;240 this->m_ClientSocket = client_socket;241 this->m_ClientPort = client_port;242 this->m_ClientTCP = client_addr;243 this->m_ClientType = client_type;244 this->m_Next = NULL;245 this->m_cmName = NULL;246 this->m_Description = NULL;247 248}249//------------------------------------------------------------------------------------------------------250 251//------------------------------------------------------------------------------------------------------252// Destructor will free the space allocated for the new client name253//------------------------------------------------------------------------------------------------------254ClientDescriptor::~ClientDescriptor() {255 free(this->m_cmName);256 free(this->m_Description);257}258//------------------------------------------------------------------------------------------------------259 260//------------------------------------------------------------------------------------------------------261// This method will add new client to the clients linked list262//------------------------------------------------------------------------------------------------------263void ClientDescriptor::AddNewClient(ClientDescriptor *sd) {264 if(sd_list == NULL){265 sd_list = sd;266 sd_list_last = sd;267 } else {268 sd_list_last->m_Next = sd;269 sd_list_last = sd;270 }271}272//------------------------------------------------------------------------------------------------------273 274//------------------------------------------------------------------------------------------------------275// This function will return a pointer to the client record in the clients linked list276// or NULL of no client with the given name found.277//------------------------------------------------------------------------------------------------------278ClientDescriptor *ClientDescriptor::LookupID(int id)279{280 ClientDescriptor *cur = sd_list;281 while(cur != NULL){282 if(cur->m_ID==id) return cur;283 cur = cur->m_Next;284 }285 return NULL;286}287//------------------------------------------------------------------------------------------------------288 289//------------------------------------------------------------------------------------------------------290// This function will remove the client with the given name.291//------------------------------------------------------------------------------------------------------292void ClientDescriptor::RemoveClient(int id) {293 ClientDescriptor *prev = NULL;294 ClientDescriptor *cur = sd_list;295 while(cur != NULL) {296 if(cur->m_ID == id) {297 closesocket(cur->m_ClientSocket);298 if(prev == NULL)299 sd_list = cur->m_Next;300 else301 prev->m_Next = cur->m_Next;302 if(sd_list_last == cur)303 sd_list_last = prev;304 delete cur;305 return;306 }307 prev = cur;308 cur = cur->m_Next;309 }310}311//------------------------------------------------------------------------------------------------------312 313//------------------------------------------------------------------------------------------------------314// This function will remove client with the given address315//------------------------------------------------------------------------------------------------------316void ClientDescriptor::RemoveClient(ClientDescriptor *p) {317 ClientDescriptor *prev = NULL;318 ClientDescriptor *cur = sd_list;319 while(cur != NULL) {320 if(p==cur) {321 closesocket(cur->m_ClientSocket);322 if(prev == NULL)323 sd_list = cur->m_Next;324 else325 prev->m_Next = cur->m_Next;326 if(sd_list_last == cur)327 sd_list_last = prev;328 delete cur;329 return;330 }331 prev = cur;332 cur = cur->m_Next;333 }334}335//------------------------------------------------------------------------------------------------------336 337//------------------------------------------------------------------------------------------------------338// This function will remove client with the given address339//------------------------------------------------------------------------------------------------------340void ClientDescriptor::RemoveAllClients(void) {341 ClientDescriptor *p;342 ClientDescriptor *cur = sd_list;343 while(cur != NULL) {344 p=cur;345 cur = cur->m_Next;346 closesocket(p->m_ClientSocket);347 delete p;348 }349 sd_list=sd_list_last=NULL;350 351}352//------------------------------------------------------------------------------------------------------353 354//------------------------------------------------------------------------------------------------------355// Gets the name of the current CM system, that this client connects to.356// This name is from the list of all CM system supported by 'CM:Generic' interface.357//------------------------------------------------------------------------------------------------------358char* ClientDescriptor::getCmName() {359 return this->m_cmName;360}361//------------------------------------------------------------------------------------------------------362 363//------------------------------------------------------------------------------------------------------364// Sets the name of the current CM system, that this client connects to.365// This name is from the list of all CM system supported by 'CM:Generic' interface.366//------------------------------------------------------------------------------------------------------367void ClientDescriptor::setCmName(char *cm_name) {368 this->m_cmName = strdup(cm_name);369}370//------------------------------------------------------------------------------------------------------371 372//------------------------------------------------------------------------------------------------------373// Returns textual description of this client:374// ""socket=<xxx>, type=<y>, ip=<ii>.<ii>.<ii>.<ii>, port=<zzzzz>""375//------------------------------------------------------------------------------------------------------376char* ClientDescriptor::getDescription() {377 378 if(this->m_Description == NULL) {379 380 // Getting parts of IP address381 int ip0 = this->m_ClientTCP & 255;382 int ip1 = (this->m_ClientTCP >> 8) & 255;383 int ip2 = (this->m_ClientTCP >> 16) & 255;384 int ip3 = (this->m_ClientTCP >> 24) & 255;385 386 // Formatting string387 char str[1024];388 sprintf(str, ""socket=%i, type=%i, ip=[%i.%i.%i.%i], port=%i"",389 this->m_ClientSocket, this->m_ClientType,390 ip3, ip2, ip1, ip0,391 this->m_ClientPort);392 393 this->m_Description = strdup(str);394 }395 396 return this->m_Description;397 398} //getDescription399//------------------------------------------------------------------------------------------------------400//############################################################################################401 402//--------------------------------------------------------------------------------------------403// This function will inspect clients list in order to determine which clients404// need to query server. The data will be forwarded from the client socket405// into model server socket and reply will be forwarded from model server socket406// to the client socket.407//--------------------------------------------------------------------------------------------408int MakeSocketsArray(int server[m_DriversNum], int *sockets) {409 static ClientDescriptor* hang;410 411 for(int i=0;i<m_DriversNum;i++)412 sockets[i]=server[i];413 int amount=m_DriversNum;414 ClientDescriptor *cur = ClientDescriptor::sd_list;415 while(ClientDescriptor::sd_list!=NULL && cur != NULL) {416 sockets[amount++]=cur->m_ClientSocket;417 cur = cur->m_Next;418 }419 return amount;420}421//--------------------------------------------------------------------------------------------422 423//------------------------------------------------------------------------------------------------------424// This function will check if data available in the selected socket425//------------------------------------------------------------------------------------------------------426int CheckSocketForRead(int socket) {427 timeval timeout;428 timeout.tv_sec = 0;429 timeout.tv_usec = 0;430 fd_set sock_set;431 int nfsd = 0;432#ifndef _WIN32433 nfsd = FD_SETSIZE;434#endif435 436 FD_ZERO(&sock_set);437 FD_SET(socket, &sock_set);438#ifdef hp700439 int res = select(nfsd,(int *)&sock_set,NULL,NULL,&timeout);440#else441 int res = select(nfsd,&sock_set,NULL,NULL,&timeout);442#endif443 if(res > 0) {444 return 1;445 }446 return 0;447}448//------------------------------------------------------------------------------------------------------449 450//------------------------------------------------------------------------------------------------------451 452//------------------------------------------------------------------------------------------------------453// This function will check if data available in any socket454//------------------------------------------------------------------------------------------------------455int WaitSocket(int *sockets, int amount) {456 timeval timeout;457 timeout.tv_sec = 8;458 timeout.tv_usec = 0;459 fd_set sock_set;460 int nfsd = 0;461#ifndef _WIN32462 nfsd = FD_SETSIZE;463#endif464 465 FD_ZERO(&sock_set);466 for(int i=0;i<amount;i++) {467 FD_SET(*(sockets+i), &sock_set);468 }469#ifdef hp700470 int res = select(nfsd,(int *)&sock_set,NULL,NULL,&timeout);471#else472 int res = select(nfsd,&sock_set,NULL,NULL,&timeout);473#endif474 if(res > 0) {475 return 1;476 }477 return 0;478}479//------------------------------------------------------------------------------------------------------480 481//--------------------------------------------------------------------------------------------482// This function will create new client record in the clients linked list.483//--------------------------------------------------------------------------------------------484ClientDescriptor* CreateNewClient(int id, int client_socket, int client_port,485 int client_tcp, int client_type) {486 ClientDescriptor* descr = NULL;487 descr = new ClientDescriptor(id,client_socket,client_port,client_tcp,client_type);488 descr->AddNewClient(descr);489 return descr;490}491//--------------------------------------------------------------------------------------------492 493//--------------------------------------------------------------------------------------------494// This function will run every time the new client try to connect to the editor495// It will create socket connection between the client and the currently 496// running pmod server and will start client log.497//--------------------------------------------------------------------------------------------498void ConnectClient(int client_socket, sockaddr *addr, int client_type) {499 static int ID_Counter = 0;500 int client_port = ((sockaddr_in *)addr)->sin_port;501 int client_tcp = ntohl(((sockaddr_in *)addr)->sin_addr.s_addr);502 503 // We will not use password right now, but we may in future504 ClientDescriptor* client = CreateNewClient(ID_Counter,505 client_socket,506 client_port,507 client_tcp,508 client_type);509 char *str = client->getDescription();510 if(str != NULL) {511 _DBG(fprintf(log_fd, "" New client connected: %s.\\n"", str));512 } else {513 _DBG(fprintf(log_fd, "" New client connected.\\n""));514 }515 ID_Counter++;516}517//--------------------------------------------------------------------------------------------518 519//---------------------------------------------------------------------------------------------520// This function sends the reply. It sends the length of message before sending message 521// itself.522//---------------------------------------------------------------------------------------------523static int sendReply(int socket, char const* str, char prefix = 0) {524 525 int len = (str != NULL) ? strlen(str) : 0;526 527 // M.b. we have to add prefix528 char *tmpBuf = NULL;529 if(prefix != 0) {530 if(len == 0) {531 tmpBuf = new char [2];532 tmpBuf[0] = prefix;533 tmpBuf[1] = 0;534 len = 1;535 } else {536 tmpBuf = new char [len + 3];537 tmpBuf[0] = prefix;538 tmpBuf[1] = '\\n';539 tmpBuf[2] = 0;540 strcat(tmpBuf, str);541 len += 2;542 }543 str = tmpBuf;544 }545 546 // If nothing to send -> exit547 if(len != 0) {548#ifdef XXX_enable_xerces_parsing549 // Replace slashes550 for(int i=0;i<len;i++) {551 if(str[i]=='\\\\') {552 str[i]='/';553 }554 }555#endif556 SendString(socket, str);557 }558 559 // Delete memory, which was temporarly allocated. 560 delete [] tmpBuf;561 tmpBuf = NULL;562 563 return len != 0;564 565} //sendReply566 567//---------------------------------------------------------------------------------------------568// Parse command line. It divides this string into set of string569// which correspond to different argument.570//---------------------------------------------------------------------------------------------571static char** parseCommandLine(char* lpCmdLine) {572 573 int i, j, k;574 int len = strlen(lpCmdLine);575 bool inQ = false; // Flag: we are inside the string,576 // which bounded by double quotes, or not.577 int idx = 0; // Index of the current character of the command line578 int token_len = 0; // Here will be the current token's length.579 int argc = 0; // Here will be a number of tokens in command line580 char *token = NULL; // Current token581 582 // Find possible number of tokens. It is upper estimation.583 for(char *str = lpCmdLine; str != NULL; str = strchr(str, ' ')) {584 argc++;585 str++;586 }587 588 // Allocate memory for resulting array of tokens589 char **argv = new char* [argc + 1];590 for(i = 0; i <= argc; i++) {591 argv[i] = NULL;592 }593 594 // Start first token595 token = new char [len + 1];596 token[0] = 0;597 token_len = 0;598 argv[0] = token;599 argc = 1;600 601 // Goes thru all characters in the command line602 for(idx = 0; idx < len; idx++) {603 604 // If this character is double quote -> switch flag605 if(lpCmdLine[idx] == '""') {606 inQ = !inQ;607 continue;608 }609 610 // If current character is space and611 // not in the string which bounded by double quotes612 // -> start new token.613 if(!inQ && lpCmdLine[idx] == ' ') {614 615 // Close previous token616 if(argc > 0) {617 token[token_len] = 0;618 }619 620 // Start new token621 token = new char [len - idx + 1];622 token[0] = 0;623 token_len = 0;624 argv[argc++] = token;625 continue;626 }627 628 token[token_len++] = lpCmdLine[idx];629 } //for idx630 631 // Close last token632 if(argc > 0) {633 token[token_len] = 0;634 }635 636 // Remove bad tokens (empty or blanks)637 for(k = argc - 1; k >= 0; k--) {638 639 // We will work with this token640 token = argv[k];641 token_len = strlen(token);642 643 // Check if it contains only spaces644 for(j = 0; j < token_len; j++) {645 if(token[j] != ' ') {646 break;647 }648 }649 650 // We have to remove this token651 if(j == token_len) {652 653 delete token;654 token = NULL;655 656 // Shift array657 for(i = k + 1; i <= argc; i++) {658 argv[i - 1] = argv[i];659 }660 }661 } //for k662 663 return argv;664 665} //parseCommandLine666//---------------------------------------------------------------------------------------------667 668//---------------------------------------------------------------------------------------------669// Expands all environment variables in the given command line specification.670// Function will modify source buffer. We suppose that this buffer has enough space.671//672// Returns: 0 - all right, source buffer contains processed command line;673// !0 - error, source buffer contains error description.674//---------------------------------------------------------------------------------------------675int expandEnvVariables(char *commandLine) {676 677 // Calculate number of references to env. variables, i.e. number of dollar signs.678 int len = strlen(commandLine);679 int count = 0;680 for(int i = 0; i < len; i++) {681 if(commandLine[i] == '$') {682 count++;683 }684 }685 686 if(count == 0) {687 // Nothing to do. Source buffer doesn't contain any env. variables.688 return 0;689 }690 691 // Allocate temporary memory for transformation.692 int tmp_sz = len + count * 1024;693 char *expanded = new char [tmp_sz];694 memset(expanded, 0, tmp_sz);695 696 // Go through source command line specification, find env. variables, and replace them.697 char var_name[1024];698 char *var_value = NULL;699 char *prev = commandLine;700 char *ptr = NULL;701 int retCode = 0;702 while(prev != NULL) {703 704 // Find next reference to env. variable.705 ptr = strchr(prev, '$');706 if(ptr == NULL) {707 708 // Copy the rest part of source command line.709 strcat(expanded, prev);710 break;711 712 } else {713 714 // Extract name of env. variable.715 if(ptr[1] == '{') {716 717 // We have ""${VARNAME}"" notation here.718 719 // Find closing brace.720 char *close_brace = strchr(ptr + 2, '}');721 if(close_brace == NULL) {722 strcpy(expanded,723 ""Command line specification contains reference "" \\724 ""to environment variable, which starts from '${', "" \\725 ""but doesn't contain closing curly brace '}'."");726 retCode = -1;727 break;728 }729 730 // Get env. variable name.731 tmp_sz = close_brace - ptr - 2;732 strncpy(var_name, ptr + 2, tmp_sz);733 var_name[tmp_sz] = 0;734 735 // Get env. variable value.736 var_value = getenv(var_name);737 738 // Check if variable was found.739 if(var_value == NULL) {740 sprintf(expanded,741 ""Command line specification contains reference "" \\742 ""to undefined environment variable '%s'."",743 var_name);744 retCode = -1;745 break;746 }747 748 // M.b. we have some part before reference to env. variable.749 if(ptr != prev) {750 tmp_sz = ptr - prev;751 strncat(expanded, prev, tmp_sz);752 }753 754 // Put env. variable value to destination buffer.755 strcat(expanded, var_value);756 757 // Go ahead.758 prev = close_brace + 1;759 760 } else {761 762 // We have ""$VARNAME"" notation here.763 764 // Find end of env. variable. We suppose that it is either '/' or '\\'.765 char *close_slash = strpbrk(ptr + 1, ""\\\\/"");766 767 // Get env. variable name.768 if(close_slash == NULL) {769 strcpy(var_name, ptr + 1);770 } else {771 tmp_sz = close_slash - ptr - 1;772 strncpy(var_name, ptr + 1, tmp_sz);773 var_name[tmp_sz] = 0;774 }775 776 // Get env. variable value.777 var_value = getenv(var_name);778 779 // Check if variable was found.780 if(var_value == NULL) {781 sprintf(expanded,782 ""Command line specification contains reference "" \\783 ""to undefined environment variable '%s'. "" \\784 ""M.b. program coudln't extract correctly variable name. "" \\785 ""It is better to use '${VARNAME}' notation."",786 var_name);787 retCode = -1;788 break;789 }790 791 // M.b. we have some part before reference to env. variable.792 if(ptr != prev) {793 tmp_sz = ptr - prev;794 strncat(expanded, prev, tmp_sz);795 }796 797 // Put env. variable value to destination buffer.798 strcat(expanded, var_value);799 800 // Go ahead.801 prev = close_slash;802 803 } //if ptr[1]804 } //if ptr == NULL805 } //while806 807 strcpy(commandLine, expanded);808 delete [] expanded;809 expanded = NULL;810 811 return retCode;812 813} //expandEnvVariables814//---------------------------------------------------------------------------------------------815 816//---------------------------------------------------------------------------------------------817// Runs external program818//---------------------------------------------------------------------------------------------819 820#ifdef _WIN32821 822DWORD OutputError(char** pszOutputBuffer, char *pszAPI);823DWORD ReadAndHandleOutput(char** pBuffer,HANDLE hPipeRead);824DWORD PrepAndLaunchRedirectedChild(char** pBuffer,825 char* command,826 HANDLE hChildStdOut,827 HANDLE hChildStdIn,828 HANDLE hChildStdErr);829DWORD WINAPI GetAndSendInputThread(LPVOID lpvThreadParam);830 831DWORD Win32RunRedirectedApp(char* command, char** pBuffer, char* workingDir) {832 HANDLE hOutputReadTmp,hOutputRead,hOutputWrite;833 HANDLE hInputWriteTmp,hInputRead,hInputWrite;834 HANDLE hErrorWrite;835 SECURITY_ATTRIBUTES sa;836 837 // Set up the security attributes struct.838 sa.nLength= sizeof(SECURITY_ATTRIBUTES);839 sa.lpSecurityDescriptor = NULL;840 sa.bInheritHandle = TRUE;841 842 843 // Create the child output pipe.844 if(!CreatePipe(&hOutputReadTmp,&hOutputWrite,&sa,0)) {845 return OutputError(pBuffer,""CreatePipe"");846 }847 848 849 // Create a duplicate of the output write handle for the std error850 // write handle. This is necessary in case the child application851 // closes one of its std output handles.852 if (!DuplicateHandle(GetCurrentProcess(),hOutputWrite,853 GetCurrentProcess(),&hErrorWrite,0,854 TRUE,DUPLICATE_SAME_ACCESS)) {855 return OutputError(pBuffer,""DuplicateHandle"");856 }857 858 859 // Create the child input pipe.860 if (!CreatePipe(&hInputRead,&hInputWriteTmp,&sa,0)) {861 return OutputError(pBuffer,""CreatePipe"");862 }863 864 865 // Create new output read handle and the input write handles. Set866 // the Properties to FALSE. Otherwise, the child inherits the867 // properties and, as a result, non-closeable handles to the pipes868 // are created.869 if (!DuplicateHandle(GetCurrentProcess(),hOutputReadTmp,870 GetCurrentProcess(),871 &hOutputRead, // Address of new handle.872 0,FALSE, // Make it uninheritable.873 DUPLICATE_SAME_ACCESS)) {874 return OutputError(pBuffer,""DupliateHandle"");875 }876 877 if (!DuplicateHandle(GetCurrentProcess(),hInputWriteTmp,878 GetCurrentProcess(),879 &hInputWrite, // Address of new handle.880 0,FALSE, // Make it uninheritable.881 DUPLICATE_SAME_ACCESS)) {882 return OutputError(pBuffer,""DupliateHandle"");883 }884 885 886 // Close inheritable copies of the handles you do not want to be887 // inherited.888 if (!CloseHandle(hOutputReadTmp)) return OutputError(pBuffer,""CloseHandle"");889 if (!CloseHandle(hInputWriteTmp)) return OutputError(pBuffer,""CloseHandle"");890 891 892 DWORD dwErr = PrepAndLaunchRedirectedChild(pBuffer,command,hOutputWrite,hInputRead,hErrorWrite);893 if(dwErr!=ERROR_SUCCESS) return dwErr;894 895 896 // Close pipe handles (do not continue to modify the parent).897 // You need to make sure that no handles to the write end of the898 // output pipe are maintained in this process or else the pipe will899 // not close when the child process exits and the ReadFile will hang.900 if (!CloseHandle(hOutputWrite)) return OutputError(pBuffer,""CloseHandle"");901 if (!CloseHandle(hInputRead )) return OutputError(pBuffer,""CloseHandle"");902 if (!CloseHandle(hErrorWrite)) return OutputError(pBuffer,""CloseHandle"");903 904 905 // Read the child's output.906 dwErr = ReadAndHandleOutput(pBuffer,hOutputRead);907 if(dwErr!=ERROR_SUCCESS) return dwErr;908 // Redirection is complete909 910 if (!CloseHandle(hOutputRead)) return OutputError(pBuffer,""CloseHandle"");911 if (!CloseHandle(hInputWrite)) return OutputError(pBuffer,""CloseHandle"");912 913 return ERROR_SUCCESS;914}915 916 917///////////////////////////////////////////////////////////////////////918// PrepAndLaunchRedirectedChild919// Sets up STARTUPINFO structure, and launches redirected child.920///////////////////////////////////////////////////////////////////////921DWORD PrepAndLaunchRedirectedChild(char** pBuffer,922 char* command,923 HANDLE hChildStdOut,924 HANDLE hChildStdIn,925 HANDLE hChildStdErr) {926 PROCESS_INFORMATION pi;927 STARTUPINFO si;928 929 // Set up the start up info struct.930 ZeroMemory(&si,sizeof(STARTUPINFO));931 si.wShowWindow=SW_HIDE;932 si.cb = sizeof(STARTUPINFO);933 si.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW;934 si.hStdOutput = hChildStdOut;935 si.hStdInput = hChildStdIn;936 si.hStdError = hChildStdErr;937 938 // Launch the process that you want to redirect939 if (!CreateProcess(NULL,command,NULL,NULL,TRUE,940 CREATE_NO_WINDOW,NULL,NULL,&si,&pi)) {941 return OutputError(pBuffer,""CreateProcess"");942 }943 944 945 // Close any unnecessary handles.946 if (!CloseHandle(pi.hThread)) return OutputError(pBuffer,""CloseHandle"");947 return ERROR_SUCCESS;948}949 950///////////////////////////////////////////////////////////////////////951// ReadAndHandleOutput952// Monitors handle for input. Exits when child exits or pipe breaks.953///////////////////////////////////////////////////////////////////////954#include ""string""955using namespace std;956DWORD ReadAndHandleOutput(char** pBuffer,HANDLE hPipeRead)957{958 CHAR lpBuffer[256];959 string szOutput;960 DWORD nBytesRead;961 962 while(TRUE) {963 if (!ReadFile(hPipeRead,lpBuffer,sizeof(lpBuffer)-1,964 &nBytesRead,NULL) || !nBytesRead) {965 if (GetLastError() == ERROR_BROKEN_PIPE)966 break; // pipe done - normal exit path.967 else968 return OutputError(pBuffer,""ReadFile""); // Something bad happened.969 }970 lpBuffer[nBytesRead]=0;971 szOutput += lpBuffer;972 }973 974 int nLen = szOutput.length()+1;975 *pBuffer = new char[nLen];976 memcpy(*pBuffer,szOutput.c_str(),nLen);977 return ERROR_SUCCESS;978}979 980///////////////////////////////////////////////////////////////////////981// OutputError982// OutputError the error number and corresponding message.983///////////////////////////////////////////////////////////////////////984DWORD OutputError(char** pszOutputBuffer, char *pszAPI)985{986 char* lpMsgBuf;987 static char* pcOutputFormat=""ERROR: API = %s.\\n message = %s.\\n""; 988 989 DWORD dwError = GetLastError();990 FormatMessage(991 FORMAT_MESSAGE_ALLOCATE_BUFFER |992 FORMAT_MESSAGE_FROM_SYSTEM |993 FORMAT_MESSAGE_IGNORE_INSERTS,994 NULL,995 dwError,996 0, // Default language997 (LPTSTR) &lpMsgBuf,998 0,999 NULL1000 );1001 1002 int nLen = strlen(lpMsgBuf)+strlen(pcOutputFormat)+strlen(pszAPI)+1;1003 *pszOutputBuffer = new char[nLen];1004 sprintf(*pszOutputBuffer, pcOutputFormat, pszAPI, lpMsgBuf);1005 // Free the buffer.1006 LocalFree( lpMsgBuf );1007 1008 return dwError;1009}1010#endif1011 1012int runCommand(char* command, char** pBuffer, char* workingDir) {1013 1014 // Check parameters1015 if(command == NULL || pBuffer == NULL) {1016 return -1;1017 }1018 1019 // M.b. we have to expand env. variables.1020 int expand_retcode = expandEnvVariables(command);1021 if(expand_retcode != 0) {1022 1023 // We couldn't expand command line specification.1024 int len = strlen(command);1025 *pBuffer = new char[len + 1];1026 strcpy(*pBuffer, command);1027 return expand_retcode;1028 }1029 1030 _DBG(fprintf(log_fd, ""\\n<RUN>\\n""));1031 _DBG(fprintf(log_fd, ""%s"", command));1032 _DBG(fprintf(log_fd, ""\\n</RUN>\\n\\n""));1033 1034 static const char* CANT_CREATE_PIPE = ""Error: Can't create pipe."";1035 static const char* CANT_CREATE_PROCESS = ""Error: Can't create process."";1036 static const char* CANT_REDIRECT_IO = ""Error: Can't redirect output from external process."";1037 static const char* CANT_READ_OUTPUT = ""Error: Can't read output of external program."";1038 static const char* DONE = ""done."";1039 1040 // Here will be output from external program1041 *pBuffer = NULL;1042 1043#ifdef _WIN321044 // Running external program on Windows platform1045 return Win32RunRedirectedApp(command, pBuffer, workingDir);1046#else1047 // Running external program on UNIX platform1048 1049 // Create pipe for communicating with external program1050 int p[2];1051 if(pipe(p) != 0) {1052 int len = strlen(CANT_CREATE_PIPE);1053 *pBuffer = new char[len + 1];1054 strcpy(*pBuffer, CANT_CREATE_PIPE);1055 return -1;1056 }1057 1058 // We return this code1059 int retCode = 0;1060 1061 // Parse source command line to set of arguments1062 char **arglist = parseCommandLine(command);1063 1064 // To run external program we have to fork current process1065 const pid_t pid = fork();1066 1067 if(pid == -1) {1068 1069 // We failed to create another process1070 int len = strlen(CANT_CREATE_PROCESS);1071 *pBuffer = new char[len + 1];1072 strcpy(*pBuffer, CANT_CREATE_PROCESS);1073 retCode = -1;1074 1075 } else if(pid == 0) {1076 1077 // It is child process1078 setpgid(0, 0);1079 1080 // Redirecting input/output1081 if(dup2(p[0], 0) == -1 || dup2(p[1], 1) == -1 || dup2(p[1], 2) == -1) {1082 1083 // We failed to redirect input/output1084 int len = strlen(CANT_REDIRECT_IO);1085 *pBuffer = new char[len + 1];1086 strcpy(*pBuffer, CANT_REDIRECT_IO);1087 retCode = -1;1088 1089 } else {1090 1091 // Run external program1092 if(execvp(arglist[0], arglist) != 0) {1093 1094 // We failed to start external program1095 char *errmsg = strerror(errno);1096 printf(""Can't execute '%s': %s"", arglist[0], errmsg);1097 exit(errno);1098 }1099 1100 // Actually we will never be here1101 exit(0);1102 1103 } //if dup21104 1105 } else {1106 1107 // It is parent process1108 int childPID = 0;1109 int status = 0;1110 1111 // Wait until child finishes1112 do {1113 childPID = wait(&status);1114 } while((childPID != pid) && (childPID > 0));1115 1116 // Exit code of external program1117 retCode = status;1118 1119 // Read output from external program1120 struct stat st;1121 int res = fstat(p[0], &st);1122 if(res == 0) {1123 1124 int len = st.st_size;1125 if(len > 0) {1126 1127 // Allocate memory and try to read1128 char *buffer = new char[len + 1];1129 int actual = read(p[0], buffer, len);1130 1131 if(actual < 0) {1132 1133 // We failed to read output1134 int len = strlen(CANT_READ_OUTPUT);1135 *pBuffer = new char[len + 1];1136 strcpy(*pBuffer, CANT_READ_OUTPUT);1137 retCode = status != 0 ? status : -1;1138 delete [] buffer;1139 1140 } else {1141 1142 // Mark end of string. Just to make sure.1143 if(actual <= len) {1144 buffer[actual] = 0;1145 } else {1146 buffer[len] = 0;1147 }1148 *pBuffer = buffer;1149 }1150 } //if len1151 } //if res1152 1153 // Close pipe1154 close(p[0]);1155 close(p[1]);1156 1157 } //if pid1158 1159 // Print to log-file what we've got from external program1160 _DBG(fprintf(log_fd, ""\\n<OUTPUT>\\n""));1161 if(*pBuffer != NULL) {1162 char *str = *pBuffer;1163 int len = strlen(str);1164 if(str[len - 1] == '\\n') {1165 _DBG(fprintf(log_fd, ""%s"", str));1166 } else {1167 _DBG(fprintf(log_fd, ""%s\\n"", str));1168 }1169 }1170 _DBG(fprintf(log_fd, ""\\n</OUTPUT>\\n\\n""));1171 1172 // Delete memory which was temporarly allocated1173 delete [] arglist;1174 1175 return retCode;1176#endif1177 1178} //runCommand1179 1180int runCommand(char* command, char** pBuffer) {1181 return runCommand(command,pBuffer,(char*)NULL);1182}1183 1184//---------------------------------------------------------------------------------------------1185// This function will process given ClearCase command with it's arguments and will 1186// send the reply1187//---------------------------------------------------------------------------------------------1188int ProcessClearCaseCommand(ClientDescriptor* client, char **args) {1189 char command[1024];1190#ifdef XXX_enable_xerces_parsing1191 char* reply = NULL;1192#else1193 static char const empty[] = """";1194 char* reply = new char[sizeof(empty)];1195 strcpy(reply, empty);1196#endif1197 1198 if(strcmp(args[0],REGISTER_CMD)==0) {1199 nClients++;1200 sendReply(client->m_ClientSocket,""done"");