unix_hurl.cpp
上传用户:zhongxx05
上传日期:2007-06-06
资源大小:33641k
文件大小:11k
- /* ***** BEGIN LICENSE BLOCK *****
- * Version: RCSL 1.0/RPSL 1.0
- *
- * Portions Copyright (c) 1995-2002 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
- * Version 1.0 (the "RPSL") available at
- * http://www.helixcommunity.org/content/rpsl unless you have licensed
- * the file under the RealNetworks Community Source License Version 1.0
- * (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.
- *
- * 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 1024
- int 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]= ' ';
- szURL[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] = ' '; /* 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] =' ';
- szBuff[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]==' ' )
- {
- //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]=' ';
- szBuff[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]= ' ';
- szExec[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] = ' '; /* 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] =' ';
- szBuff[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]==' ' )
- {
- //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]=' ';
- szBuff[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 );
- }
- }