#include // for cerr #include // for errno issues #include // for access, write, read #include // for ... in Process #include // for O_RDONLY #include // for sigaction #include // for waitpid / pid_t #include // for atoi #include // for strcat #include // for threading #if defined (__MINGW32__) || defined (__MSVCRT__) #include #define sleep(x) Sleep(x*1000) #elif defined (__DARWIN__) #include #include // for socket #include // for sock_addr #include // for inet_addr #include #else #include // for socket #include // for sock_addr #include // for inet_addr #include #endif #include "ant.h" // for GetTempDirectory static pthread_mutex_t _mutex = PTHREAD_MUTEX_INITIALIZER; int _StartPromoStatus () { char exe [256]; char NamedPipe [1024]; char buf [10]; sockaddr_in addr; u_short port = 11012; int i; int fd; char *tmp = GetTempDirectory (); int PipeFD = -1; memset (&addr, 0, sizeof (addr)); addr.sin_family = AF_INET; addr.sin_addr.s_addr = inet_addr ("127.0.0.1"); addr.sin_port = htons (port); pthread_mutex_lock (&_mutex); /* locks the access */ sprintf (NamedPipe, "%s/%s.NamedPipe", tmp, GetUserName ()); if (access (NamedPipe, F_OK) == 0) { fd = open (NamedPipe, O_RDONLY | O_BINARY); read (fd, buf, sizeof (buf)); close (fd); port = atoi (buf); } else { // We need to ignore SIGPIPE in case someone dismisses the PromoStatus window before we are done #if defined (__MINGW32__) || defined (__MSVCRT__) //---------------------- // Initialize Winsock WSADATA wsaData; int iResult = WSAStartup (MAKEWORD (2,2), &wsaData); if (iResult != NO_ERROR) std::cerr << "Error at WSAStartup()\n"; #else signal (SIGPIPE, SIG_IGN); #endif fd = creat (NamedPipe, 0600); #if defined (__MINGW32__) || defined (__MSVCRT__) if ((PipeFD = socket (AF_INET, SOCK_STREAM, 0)) == SOCKET_ERROR) { std::cerr << "Error creating the sockets!" << std::endl; WSACleanup(); pthread_mutex_unlock (&_mutex); /* unlocks the access */ return (PipeFD); } #else if ((PipeFD = socket (AF_INET, SOCK_STREAM, 0)) == -1) { std::cerr << "Error creating the sockets!" << std::endl; pthread_mutex_unlock (&_mutex); /* unlocks the access */ return (PipeFD); } #endif int ret_val; ret_val = connect (PipeFD, (struct sockaddr *)&addr, sizeof (addr)); if (ret_val == -1) { perror ("PROMOSTATUS - connect1"); } else if (ret_val == 0) { read (PipeFD, buf, sizeof (buf)); port = atoi (buf); } close (PipeFD); sprintf (buf, "%d\n", port); write (fd, buf, strlen (buf)); close (fd); // Run PromoStatus #if defined (__MINGW32__) || defined (__MSVCRT__) sprintf (exe, "%s/bin/PromoStatus", GetEnv ("SDDAS_HOME")); if ((int) ShellExecute (NULL, "open", exe, NULL, NULL, SW_SHOWNORMAL) <= 32) #elif defined (__DARWIN__) // We do all this extra work on the Mac so it will come to the front when launched. // With "system", the app would launch in the background. ProcessSerialNumber psn; OSErr err = GetCurrentProcess(&psn); ProcessInfoRec info; memset (&info, 0, sizeof (info)); info.processInfoLength = sizeof(info); info.processName = 0; err = GetProcessInformation(&psn, &info); /* Now you have got a file specifier of your running app Now make a specifier of the other one. */ sprintf (exe, "%s/bin/PromoStatus", GetEnv ("SDDAS_HOME")); CFURLRef cfurl = CFURLCreateFromFileSystemRepresentation (NULL, (const UInt8 *) exe, strlen (exe), false); FSRef otherAppRef; if (CFURLGetFSRef (cfurl, &otherAppRef) == false) { std::cerr << "ERROR - Couldn't convert PromoStatus" << std::endl; } if ( LSOpenApplication != NULL ) { LSApplicationParameters appParams; // Do it the easy way on 10.4 and later. memset(&appParams, 0, sizeof(appParams)); appParams.version = 0; appParams.flags = kLSLaunchDefaults; appParams.application = &otherAppRef; err = LSOpenApplication(&appParams, &psn); } else { FSSpec appSpec; LaunchParamBlockRec lpb; // Do it the compatible way on earlier systems. // I launch System Events using LaunchApplication, rather than // Launch Services, because LaunchApplication gives me back // the ProcessSerialNumber. Unfortunately this requires me to // get an FSSpec for the application because there's no // FSRef version of Launch Application. if (err == noErr) { err = FSGetCatalogInfo(&otherAppRef, kFSCatInfoNone, NULL, NULL, &appSpec, NULL); } if (err == noErr) { memset(&lpb, 0, sizeof(lpb)); lpb.launchBlockID = extendedBlock; lpb.launchEPBLength = extendedBlockLen; lpb.launchControlFlags = launchContinue | launchNoFileFlags; // lpb.launchAppSpec = &appSpec; err = LaunchApplication(&lpb); } if (err == noErr) { psn = lpb.launchProcessSN; } } if (err != noErr) #else sprintf (exe, "%s/bin/PromoStatus &", GetEnv ("SDDAS_HOME")); if (system (exe) == -1) #endif { std::cerr << "ERROR - Couldn't execute PromoStatus" << std::endl; perror ("PROMOSTATUS"); unlink (NamedPipe); PipeFD = 0; pthread_mutex_unlock (&_mutex); /* unlocks the access */ return (PipeFD); } } addr.sin_port = htons (port); sleep (2); for (i = 0; i < 5; i++) { if ((PipeFD = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) { perror ("PROMOSTATUS - socket"); } #if defined (__MINGW32__) || defined (__MSVCRT__) if (connect (PipeFD, (SOCKADDR *) &addr, sizeof(addr)) == SOCKET_ERROR) { std::cerr << "Error connecting: " << WSAGetLastError () << std::endl; #else if (connect (PipeFD, (struct sockaddr *) &addr, sizeof(struct sockaddr_in)) == -1) { perror ("PROMOSTATUS - connect"); if (errno == EADDRNOTAVAIL) break; // assume it is okay? #endif std::cerr << "Attempt " << i + 1 << " failed..." << std::endl; close (PipeFD); PipeFD = 0; sleep (2); } else { break; } } #if defined (__MINGW32__) || defined (__MSVCRT__) WSACleanup(); #endif pthread_mutex_unlock (&_mutex); /* unlocks the access */ return (PipeFD); } int _Process (char *arg0, ...) { int argno; va_list ap; char command_line [1024]; char *args [20]; memset (command_line, 0, sizeof (command_line)); va_start (ap, arg0); argno = 0; while ((args [argno++] = va_arg (ap, char *)) != 0); va_end (ap); argno--; strcpy (command_line, arg0); strcat (command_line, " "); for (int i = 1; i < argno; i++) { strcat (command_line, args [i]); strcat (command_line, " "); } #if defined (__MINGW32__) || defined (__MSVCRT__) SHELLEXECUTEINFO ExecuteInfo; DWORD lpExitCode; memset (&ExecuteInfo, 0, sizeof (ExecuteInfo)); ExecuteInfo.cbSize = sizeof(ExecuteInfo); ExecuteInfo.fMask = SEE_MASK_FLAG_NO_UI | SEE_MASK_NOCLOSEPROCESS; ExecuteInfo.hwnd = 0; ExecuteInfo.lpVerb = "open"; // Operation to perform ExecuteInfo.lpFile = arg0; // Application name ExecuteInfo.lpParameters = strchr (command_line, ' ') + 1; // Additional parameters ExecuteInfo.lpDirectory = 0; // Default directory ExecuteInfo.nShow = SW_SHOWNORMAL; ExecuteInfo.hInstApp = 0; if (ShellExecuteEx (&ExecuteInfo) == FALSE) { std::cerr << "ERROR - Couldn't execute " << command_line << std::endl; perror ("Process"); } else { WaitForSingleObject (ExecuteInfo.hProcess, INFINITE); GetExitCodeProcess (ExecuteInfo.hProcess, &lpExitCode); CloseHandle (ExecuteInfo.hProcess); return (lpExitCode != 0); } #else // All this stuff does is exec a program and its more cross platform to // just use system. Let's leave it commented out for a while until we // sure it works. #if 0 int status; pid_t pid, wpid; struct sigaction act, oact; sigemptyset (&act.sa_mask); act.sa_handler = SIG_DFL; act.sa_flags = 0; sigaction (SIGCHLD, &act, &oact); pid = fork (); switch (pid) { case -1 : perror ("ERROR! Fork in Process"); break; case 0 : // CHILD PROCESS execvp (arg0, args); std::cerr << "Error: running " << arg0 << std::endl; perror ("execv Process"); _exit (1); break; // never reached default : // PARENT PROCESS char msg [64]; if ((wpid = waitpid (pid, &status, 0)) != pid) { sprintf (msg, "Process () : wait %ld", (long) pid); perror (msg); sigaction (SIGCHLD, &oact, NULL); return -1; } // Overuse of parenthesis since W* functions are macros... sigaction (SIGCHLD, &oact, NULL); if (WIFSIGNALED ((status))) return -1; else return WEXITSTATUS ((status)); } // switch // if execution gets here, waitpid == -1 sigaction (SIGCHLD, &oact, NULL); return -1; #endif #endif return (system (command_line)); }