unix_hurl.cpp
上传用户:zhongxx05
上传日期:2007-06-06
资源大小:33641k
文件大小:11k
源码类别:

Symbian

开发平台:

C/C++

  1. /* ***** BEGIN LICENSE BLOCK ***** 
  2.  * Version: RCSL 1.0/RPSL 1.0 
  3.  *  
  4.  * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved. 
  5.  *      
  6.  * The contents of this file, and the files included with this file, are 
  7.  * subject to the current version of the RealNetworks Public Source License 
  8.  * Version 1.0 (the "RPSL") available at 
  9.  * http://www.helixcommunity.org/content/rpsl unless you have licensed 
  10.  * the file under the RealNetworks Community Source License Version 1.0 
  11.  * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl, 
  12.  * in which case the RCSL will apply. You may also obtain the license terms 
  13.  * directly from RealNetworks.  You may not use this file except in 
  14.  * compliance with the RPSL or, if you have a valid RCSL with RealNetworks 
  15.  * applicable to this file, the RCSL.  Please see the applicable RPSL or 
  16.  * RCSL for the rights, obligations and limitations governing use of the 
  17.  * contents of the file.  
  18.  *  
  19.  * This file is part of the Helix DNA Technology. RealNetworks is the 
  20.  * developer of the Original Code and owns the copyrights in the portions 
  21.  * it created. 
  22.  *  
  23.  * This file, and the files included with this file, is distributed and made 
  24.  * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
  25.  * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
  26.  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS 
  27.  * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
  28.  * 
  29.  * Technology Compatibility Kit Test Suite(s) Location: 
  30.  *    http://www.helixcommunity.org/content/tck 
  31.  * 
  32.  * Contributor(s): 
  33.  *  
  34.  * ***** END LICENSE BLOCK ***** */ 
  35. #ifndef _UNIX
  36. #error This is the UNIX hypernav stuff!!
  37. #endif
  38. #include <signal.h>
  39. #include <sys/wait.h>
  40. #include <unistd.h>
  41. #include <errno.h>
  42. #include <sys/types.h>
  43. #include <stdlib.h> // for exit() prototype
  44. #include <string.h>
  45. #include <stdio.h>
  46. #include "hxassert.h"
  47. #include "hxstrutl.h"
  48. #include "unix_hurl.h"
  49. #include "cunixprefutils.h"
  50. //Globals for the url passing to child proc in UNIX.
  51. #define MAX_URL_LEN 1024
  52. #define MAX_EXEC_LEN 1024
  53. int zn_anHURLPipe[2] = { -1, -1 };
  54. int zm_nHurlProcID = -1;
  55. int zn_anExecPipe[2] = { -1, -1 };
  56. int zm_nExecProcID = -1;
  57. char g_pURL[MAX_URL_LEN]; /* Flawfinder: ignore */
  58. pid_t g_childPID;
  59. void InitHurlListener()
  60. {
  61.     zn_anHURLPipe[0] = -1;
  62.     zn_anHURLPipe[1] = -1;
  63.     zn_anExecPipe[0] = -1;
  64.     zn_anExecPipe[1] = -1;
  65. }
  66. void browse_child(int status)
  67. {
  68.     int chstatus;
  69.     pid_t childPID;
  70.     while((childPID = waitpid(0, &chstatus, WNOHANG)) > 0)
  71.     {
  72. if(g_childPID == childPID)
  73. {
  74.     g_childPID = 0;
  75.     if(WEXITSTATUS(chstatus) != 0)
  76.     {
  77. if(fork() == 0)
  78. {
  79.     CUnixPrefUtils::CleanEnv();
  80.     execlp("netscape", "netscape", g_pURL, NULL);
  81.     _exit(0);
  82. }
  83.     }
  84. }
  85.     }
  86. }
  87. void _ListenForHurlRequests()
  88. {
  89.     int  status = 0;
  90.     char szURL[MAX_URL_LEN+1]; /* Flawfinder: ignore */
  91.     char szBuff[MAX_URL_LEN+1]; /* Flawfinder: ignore */
  92.     //If its there grab it.
  93.     szBuff[0]= '';
  94.     szURL[0]= '';
  95.     status = 1;
  96.     while( status != 0 )
  97.     {
  98.         status = ::read(zn_anHURLPipe[0], szBuff, MAX_URL_LEN);
  99.         
  100.         if( status > 0 )
  101.         {
  102.             if( (strlen(szURL)+status)<MAX_URL_LEN )
  103.             {
  104.                 strncat( szURL, szBuff, status ); szURL[status] = ''; /* Flawfinder: ignore */
  105.             }
  106.             else
  107.             {
  108.                 //URL is too long. We don't want to over run.
  109.                 HX_ASSERT( "URL exceeds MAX_URL_LEN" == NULL );
  110.                 //Reset everything and keep looping.
  111.                 status    = -1;
  112.                 errno     = EAGAIN;
  113.                 szURL[0]  ='';
  114.                 szBuff[0] ='';
  115.             }
  116.         }
  117.         
  118.         //Did we find an error?
  119.         if( status < 0)
  120.         {
  121.             if( errno != EINTR && errno != EAGAIN )
  122.             {
  123.                 //A really bad error....
  124.                 HX_ASSERT( "a really bad error" == NULL );
  125.             }
  126.             //otherwise just ignore it. We were just nonblocking or interupted
  127.             //by a signal.
  128.         }
  129.         
  130.         if( status > 0 && szBuff[status-1]=='' )
  131.         {
  132.             //We just received a newline for our URL. That means we are
  133.             //ready to hurl it.
  134.             char browsercmd[MAX_URL_LEN+100]; /* Flawfinder: ignore */
  135.             if((g_childPID = fork()) == 0)
  136.             {
  137.                 SafeSprintf(browsercmd, MAX_URL_LEN+100, "netscape -remote 'openURL(%s)' >/dev/null  2>&1", szURL);
  138. CUnixPrefUtils::CleanEnv();
  139.                 execlp("sh",  "sh", "-c", browsercmd, NULL);
  140.                 _exit(0);
  141.             }
  142.             else
  143.             {
  144.                 SafeStrCpy(g_pURL, szURL, MAX_URL_LEN);
  145.                 signal(SIGCHLD, browse_child);
  146.             }
  147.             //Reset everything and keep looping.
  148.             status = -1;
  149.             szURL[0]='';
  150.             szBuff[0]='';
  151.         }
  152.         
  153.     } //while(status)
  154.     ::close( zn_anHURLPipe[0] );
  155.     zn_anHURLPipe[0]=-1;
  156.     _exit(0);
  157. }
  158. void _ListenForExecRequests()
  159. {
  160.     int  status = 0;
  161.     char szExec[MAX_EXEC_LEN+1]; /* Flawfinder: ignore */
  162.     char szBuff[MAX_EXEC_LEN+1]; /* Flawfinder: ignore */
  163.     //If its there grab it.
  164.     szBuff[0]= '';
  165.     szExec[0]= '';
  166.     status = 1;
  167.     while( status != 0 )
  168.     {
  169.         status = ::read(zn_anExecPipe[0], szBuff, MAX_EXEC_LEN);
  170.         
  171.         if( status > 0 )
  172.         {
  173.             if( (strlen(szExec)+status)<MAX_EXEC_LEN )
  174.             {
  175.                 strncat( szExec, szBuff, status ); szExec[status] = ''; /* Flawfinder: ignore */
  176.             }
  177.             else
  178.             {
  179.                 //URL is too long. We don't want to over run.
  180.                 HX_ASSERT( "EXEC string exceeds MAX_EXEC_LEN" == NULL );
  181.                 //Reset everything and keep looping.
  182.                 status     = -1;
  183.                 errno      = EAGAIN;
  184.                 szExec[0]  ='';
  185.                 szBuff[0]  ='';
  186.             }
  187.         }
  188.         
  189.         //Did we find an error?
  190.         if( status < 0)
  191.         {
  192.             if( errno != EINTR && errno != EAGAIN )
  193.             {
  194.                 //A really bad error....
  195.                 HX_ASSERT( "a really bad error" == NULL );
  196.                 _exit(0);
  197.             }
  198.             //otherwise just ignore it. We were just nonblocking or interupted
  199.             //by a signal.
  200.         }
  201.         
  202.         if( status > 0 && szBuff[status-1]=='' )
  203.         {
  204.             //We just received a newline for our exec string. We can exec now....
  205.             char browsercmd[MAX_EXEC_LEN+100]; /* Flawfinder: ignore */
  206.     signal(SIGCHLD, browse_child);
  207.             if(fork() == 0)
  208.             {
  209. CUnixPrefUtils::CleanEnv();
  210.                 execlp("sh",  "sh", "-c", szExec, NULL);
  211.                 _exit(0);
  212.             }
  213.             //Reset everything and keep looping.
  214.             status = -1;
  215.             szExec[0]='';
  216.             szBuff[0]='';
  217.         }
  218.         
  219.     } //while(status)
  220.     ::close( zn_anExecPipe[0] );
  221.     zn_anExecPipe[0]=-1;
  222.     _exit(0);
  223. }
  224. void ShutdownHurlListener()
  225. {
  226.     if( zn_anHURLPipe[0] != -1 )
  227.         close( zn_anHURLPipe[0] );
  228.     if( zn_anHURLPipe[1] != -1 )
  229.         close( zn_anHURLPipe[1] );
  230.     if( zn_anExecPipe[0] != -1 )
  231.         close( zn_anExecPipe[0] );
  232.     if( zn_anExecPipe[1] != -1 )
  233.         close( zn_anExecPipe[1] );
  234.     
  235.     zn_anHURLPipe[0] = -1;
  236.     zn_anHURLPipe[1] = -1; 
  237.     zn_anExecPipe[0] = -1;
  238.     zn_anExecPipe[1] = -1;
  239. }
  240. void StartHurlListener()
  241. {
  242.     if ( 0 != pipe(zn_anHURLPipe) )
  243.     {
  244. //Can't create pipe.
  245. zn_anHURLPipe[0] = -1;
  246. zn_anHURLPipe[1] = -1;
  247.         HX_ASSERT( "Can't create pipe for hurling...." == NULL );
  248.     }
  249.     //First create the hurling process.
  250.     if( 0 > (zm_nHurlProcID = fork()))
  251.     {
  252. //Error trying to fork.
  253. //What should we do?
  254.         HX_ASSERT( "Can't fork for hurling....." == NULL );
  255.     }
  256.     if( 0 == zm_nHurlProcID )
  257.     {
  258. //This is the child proc. Its life is the life of the parent so
  259.         //we don't need to do a waitpid unless we want to.
  260. //Close the write end of the pipe.
  261. if ( 0 != ::close( zn_anHURLPipe[1]) )
  262. {
  263.     //close, error. Kill this child proc.
  264.             //XXXGfw non fatal for now.
  265.             HX_ASSERT( "Can't close pipe in child." == NULL );
  266.     //_exit(1);
  267. }
  268.         zn_anHURLPipe[1]=-1;
  269.         //
  270.         // Enter a loop here that just looks for hurling requests
  271.         // on the pipe and does a fork/exec for each one.
  272.         //
  273.         // zn_anHURLPipe[0] == Read end of pipe.
  274.         // zn_anHURLPipe[1] == Write end of pipe.
  275.         //
  276.         // All urls are null terminated.
  277.         // All reads are blocking. No reason no to be.
  278.         //We never return from the following.
  279.         _ListenForHurlRequests();
  280.     }
  281.     //Leave the exec pipe open for..........
  282.     //The parent just returns after closing the read end of the pipe....
  283.     //Close the read end of the pipe.
  284.     if ( 0 != ::close( zn_anHURLPipe[0]) )
  285.     {
  286.         HX_ASSERT( "Can't close pipe in parent." == NULL );
  287.     }
  288.     zn_anHURLPipe[0]=-1;
  289.     if ( 0 != pipe(zn_anExecPipe) )
  290.     {
  291. //Can't create pipe.
  292. zn_anExecPipe[0] = -1;
  293. zn_anExecPipe[1] = -1;
  294.         HX_ASSERT( "Can't create pipe for execing...." == NULL );
  295.     }
  296.     
  297.     //Now create the process for execing.....
  298.     if( 0 > (zm_nExecProcID = fork()))
  299.     {
  300. //Error trying to fork.
  301. //What should we do?
  302.         HX_ASSERT( "Can't fork for execing....." == NULL );
  303.     }
  304.     if( 0 == zm_nExecProcID )
  305.     {
  306. //This is the child proc. Its life is the life of the parent so
  307.         //we don't need to do a waitpid unless we want to.
  308. //Close the write end of the pipe.
  309. if ( 0 != ::close( zn_anExecPipe[1]) )
  310. {
  311.     //close, error. Kill this child proc.
  312.             //XXXGfw non fatal for now.
  313.             HX_ASSERT( "Can't close pipe in exec child." == NULL );
  314.     //_exit(1);
  315. }
  316.         zn_anExecPipe[1]=-1;
  317.         //
  318.         // zn_anExecPipe[0] == Read end of pipe.
  319.         // zn_anExecPipe[1] == Write end of pipe.
  320.         //
  321.         // All execs are null terminated.
  322.         // All reads are blocking. No reason no to be.
  323.         //We never return from the following.
  324.         _ListenForExecRequests();
  325.     }
  326.     if ( 0 != ::close( zn_anExecPipe[0]) )
  327.     {
  328.         HX_ASSERT( "Can't close pipe in parent." == NULL );
  329.     }
  330.     zn_anExecPipe[0]=-1;
  331. }
  332. void SendHurlRequest(const char *pszURL)
  333. {
  334.     //We have started a child proc to do the hurling for us. If this is
  335.     //the core thread we just send the request to the child proct via the
  336.     //open pipe. If this is the child proc then we actually do it.
  337.     if( pszURL && strlen(pszURL) && zn_anHURLPipe[1]>=0 )
  338.         ::write( zn_anHURLPipe[1], pszURL, strlen(pszURL)+1 );
  339. }
  340. void SendExecRequest(const char *pszExec)
  341. {
  342.     //We have started a child proc to do the Exec for us. If this is
  343.     //the core thread we just send the request to the child proct via the
  344.     //open pipe. If this is the child proc then we actually do it.
  345.     if( pszExec && strlen(pszExec) && zn_anExecPipe[1]>=0 )
  346.     {
  347.         ::write( zn_anExecPipe[1], pszExec, strlen(pszExec)+1 );
  348.     }
  349. }