📄 unix_hurl.cpp
字号:
/* ***** BEGIN LICENSE BLOCK ***** * Source last modified: $Id: unix_hurl.cpp,v 1.3.42.3 2004/07/09 01:47:39 hubbe Exp $ * * Portions Copyright (c) 1995-2004 RealNetworks, Inc. All Rights Reserved. * * The contents of this file, and the files included with this file, * are subject to the current version of the RealNetworks Public * Source License (the "RPSL") available at * http://www.helixcommunity.org/content/rpsl unless you have licensed * the file under the current version of the RealNetworks Community * Source License (the "RCSL") available at * http://www.helixcommunity.org/content/rcsl, in which case the RCSL * will apply. You may also obtain the license terms directly from * RealNetworks. You may not use this file except in compliance with * the RPSL or, if you have a valid RCSL with RealNetworks applicable * to this file, the RCSL. Please see the applicable RPSL or RCSL for * the rights, obligations and limitations governing use of the * contents of the file. * * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the * "GPL") in which case the provisions of the GPL are applicable * instead of those above. If you wish to allow use of your version of * this file only under the terms of the GPL, and not to allow others * to use your version of this file under the terms of either the RPSL * or RCSL, indicate your decision by deleting the provisions above * and replace them with the notice and other provisions required by * the GPL. If you do not delete the provisions above, a recipient may * use your version of this file under the terms of any one of the * RPSL, the RCSL or the GPL. * * This file is part of the Helix DNA Technology. RealNetworks is the * developer of the Original Code and owns the copyrights in the * portions it created. * * This file, and the files included with this file, is distributed * and made available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY * KIND, EITHER EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET * ENJOYMENT OR NON-INFRINGEMENT. * * Technology Compatibility Kit Test Suite(s) Location: * http://www.helixcommunity.org/content/tck * * Contributor(s): * * ***** END LICENSE BLOCK ***** */#ifndef _UNIX#error This is the UNIX hypernav stuff!!#endif#include <signal.h>#include <sys/wait.h>#include <unistd.h>#include <errno.h>#include <sys/types.h>#include <stdlib.h> // for exit() prototype#include <string.h>#include <stdio.h>#include "hxassert.h"#include "hxstrutl.h"#include "unix_hurl.h"#include "cunixprefutils.h"//Globals for the url passing to child proc in UNIX.#define MAX_URL_LEN 1024#define MAX_EXEC_LEN 1024int zn_anHURLPipe[2] = { -1, -1 };int zm_nHurlProcID = -1;int zn_anExecPipe[2] = { -1, -1 };int zm_nExecProcID = -1;char g_pURL[MAX_URL_LEN]; /* Flawfinder: ignore */pid_t g_childPID;void InitHurlListener(){ zn_anHURLPipe[0] = -1; zn_anHURLPipe[1] = -1; zn_anExecPipe[0] = -1; zn_anExecPipe[1] = -1;}void browse_child(int status){ int chstatus; pid_t childPID; while((childPID = waitpid(0, &chstatus, WNOHANG)) > 0) { if(g_childPID == childPID) { g_childPID = 0; if(WEXITSTATUS(chstatus) != 0) { if(fork() == 0) { CUnixPrefUtils::CleanEnv(); execlp("netscape", "netscape", g_pURL, NULL); _exit(0); } } } }}void _ListenForHurlRequests(){ int status = 0; char szURL[MAX_URL_LEN+1]; /* Flawfinder: ignore */ char szBuff[MAX_URL_LEN+1]; /* Flawfinder: ignore */ //If its there grab it. szBuff[0]= '\0'; szURL[0]= '\0'; status = 1; while( status != 0 ) { status = ::read(zn_anHURLPipe[0], szBuff, MAX_URL_LEN); if( status > 0 ) { if( (strlen(szURL)+status)<MAX_URL_LEN ) { strncat( szURL, szBuff, status ); szURL[status] = '\0'; /* Flawfinder: ignore */ } else { //URL is too long. We don't want to over run. HX_ASSERT( "URL exceeds MAX_URL_LEN" == NULL ); //Reset everything and keep looping. status = -1; errno = EAGAIN; szURL[0] ='\0'; szBuff[0] ='\0'; } } //Did we find an error? if( status < 0) { if( errno != EINTR && errno != EAGAIN ) { //A really bad error.... HX_ASSERT( "a really bad error" == NULL ); } //otherwise just ignore it. We were just nonblocking or interupted //by a signal. } if( status > 0 && szBuff[status-1]=='\0' ) { //We just received a newline for our URL. That means we are //ready to hurl it. char browsercmd[MAX_URL_LEN+100]; /* Flawfinder: ignore */ if((g_childPID = fork()) == 0) { SafeSprintf(browsercmd, MAX_URL_LEN+100, "netscape -remote 'openURL(%s)' >/dev/null 2>&1", szURL); CUnixPrefUtils::CleanEnv(); execlp("sh", "sh", "-c", browsercmd, NULL); _exit(0); } else { SafeStrCpy(g_pURL, szURL, MAX_URL_LEN); signal(SIGCHLD, browse_child); } //Reset everything and keep looping. status = -1; szURL[0]='\0'; szBuff[0]='\0'; } } //while(status) ::close( zn_anHURLPipe[0] ); zn_anHURLPipe[0]=-1; _exit(0);}void _ListenForExecRequests(){ int status = 0; char szExec[MAX_EXEC_LEN+1]; /* Flawfinder: ignore */ char szBuff[MAX_EXEC_LEN+1]; /* Flawfinder: ignore */ //If its there grab it. szBuff[0]= '\0'; szExec[0]= '\0'; status = 1; while( status != 0 ) { status = ::read(zn_anExecPipe[0], szBuff, MAX_EXEC_LEN); if( status > 0 ) { if( (strlen(szExec)+status)<MAX_EXEC_LEN ) { strncat( szExec, szBuff, status ); szExec[status] = '\0'; /* Flawfinder: ignore */ } else { //URL is too long. We don't want to over run. HX_ASSERT( "EXEC string exceeds MAX_EXEC_LEN" == NULL ); //Reset everything and keep looping. status = -1; errno = EAGAIN; szExec[0] ='\0'; szBuff[0] ='\0'; } } //Did we find an error? if( status < 0) { if( errno != EINTR && errno != EAGAIN ) { //A really bad error.... HX_ASSERT( "a really bad error" == NULL ); _exit(0); } //otherwise just ignore it. We were just nonblocking or interupted //by a signal. } if( status > 0 && szBuff[status-1]=='\0' ) { //We just received a newline for our exec string. We can exec now.... char browsercmd[MAX_EXEC_LEN+100]; /* Flawfinder: ignore */ signal(SIGCHLD, browse_child); if(fork() == 0) { CUnixPrefUtils::CleanEnv(); execlp("sh", "sh", "-c", szExec, NULL); _exit(0); } //Reset everything and keep looping. status = -1; szExec[0]='\0'; szBuff[0]='\0'; } } //while(status) ::close( zn_anExecPipe[0] ); zn_anExecPipe[0]=-1; _exit(0);}void ShutdownHurlListener(){ if( zn_anHURLPipe[0] != -1 ) close( zn_anHURLPipe[0] ); if( zn_anHURLPipe[1] != -1 ) close( zn_anHURLPipe[1] ); if( zn_anExecPipe[0] != -1 ) close( zn_anExecPipe[0] ); if( zn_anExecPipe[1] != -1 ) close( zn_anExecPipe[1] ); zn_anHURLPipe[0] = -1; zn_anHURLPipe[1] = -1; zn_anExecPipe[0] = -1; zn_anExecPipe[1] = -1;}void StartHurlListener(){ if ( 0 != pipe(zn_anHURLPipe) ) { //Can't create pipe. zn_anHURLPipe[0] = -1; zn_anHURLPipe[1] = -1; HX_ASSERT( "Can't create pipe for hurling...." == NULL ); } //First create the hurling process. if( 0 > (zm_nHurlProcID = fork())) { //Error trying to fork. //What should we do? HX_ASSERT( "Can't fork for hurling....." == NULL ); } if( 0 == zm_nHurlProcID ) { //This is the child proc. Its life is the life of the parent so //we don't need to do a waitpid unless we want to. //Close the write end of the pipe. if ( 0 != ::close( zn_anHURLPipe[1]) ) { //close, error. Kill this child proc. //XXXGfw non fatal for now. HX_ASSERT( "Can't close pipe in child." == NULL ); //_exit(1); } zn_anHURLPipe[1]=-1; // // Enter a loop here that just looks for hurling requests // on the pipe and does a fork/exec for each one. // // zn_anHURLPipe[0] == Read end of pipe. // zn_anHURLPipe[1] == Write end of pipe. // // All urls are null terminated. // All reads are blocking. No reason no to be. //We never return from the following. _ListenForHurlRequests(); } //Leave the exec pipe open for.......... //The parent just returns after closing the read end of the pipe.... //Close the read end of the pipe. if ( 0 != ::close( zn_anHURLPipe[0]) ) { HX_ASSERT( "Can't close pipe in parent." == NULL ); } zn_anHURLPipe[0]=-1; if ( 0 != pipe(zn_anExecPipe) ) { //Can't create pipe. zn_anExecPipe[0] = -1; zn_anExecPipe[1] = -1; HX_ASSERT( "Can't create pipe for execing...." == NULL ); } //Now create the process for execing..... if( 0 > (zm_nExecProcID = fork())) { //Error trying to fork. //What should we do? HX_ASSERT( "Can't fork for execing....." == NULL ); } if( 0 == zm_nExecProcID ) { //This is the child proc. Its life is the life of the parent so //we don't need to do a waitpid unless we want to. //Close the write end of the pipe. if ( 0 != ::close( zn_anExecPipe[1]) ) { //close, error. Kill this child proc. //XXXGfw non fatal for now. HX_ASSERT( "Can't close pipe in exec child." == NULL ); //_exit(1); } zn_anExecPipe[1]=-1; // // zn_anExecPipe[0] == Read end of pipe. // zn_anExecPipe[1] == Write end of pipe. // // All execs are null terminated. // All reads are blocking. No reason no to be. //We never return from the following. _ListenForExecRequests(); } if ( 0 != ::close( zn_anExecPipe[0]) ) { HX_ASSERT( "Can't close pipe in parent." == NULL ); } zn_anExecPipe[0]=-1;}void SendHurlRequest(const char *pszURL){ //We have started a child proc to do the hurling for us. If this is //the core thread we just send the request to the child proct via the //open pipe. If this is the child proc then we actually do it. if( pszURL && strlen(pszURL) && zn_anHURLPipe[1]>=0 ) ::write( zn_anHURLPipe[1], pszURL, strlen(pszURL)+1 );}void SendExecRequest(const char *pszExec){ //We have started a child proc to do the Exec for us. If this is //the core thread we just send the request to the child proct via the //open pipe. If this is the child proc then we actually do it. if( pszExec && strlen(pszExec) && zn_anExecPipe[1]>=0 ) { ::write( zn_anExecPipe[1], pszExec, strlen(pszExec)+1 ); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -