Esempio n. 1
0
/*
** Name: PCexec_suid - Execute a command as the ingres user.
**
** Description:
**	This procedure works with the Ingres service to run the given
**	command as the ingres user. It mimicks the "setuid" bit in UNIX.
**
** Inputs:
**	cmdbuf - command to execute as the ingres user
**
** Outputs:
**	none
**
** Returns:
**	OK
**	FAIL
**
** Side Effects:
**	none
**
** History:
**	08-jan-1998 (somsa01)
**	    Created.
**	19-feb-1998 (somsa01)
**	    We need to pass to the service the current working directory
**	    as well.  (Bug #89006)
**	25-feb-1998 (somsa01)
**	    We now have an input file for the process' stdin which
**	    runs through the OpenIngres service.
**	19-jun-1998 (somsa01)
**	    Use SYSTEM_PRODUCT_NAME for the name of the service.
**	10-jul-1998 (kitch01)
**		Bug 91362. If user is 'system' run through OpenIngres service
**		despite having access to server shared memory 'system' does not
**		have required privilege to access semaphores/mutexes.
**	11-jun-1999 (somsa01)
**	    If the command is a startup command, then it is always run through
**	    the Ingres service.
**	03-nov-1999 (somsa01)
**	    A failure from ControlService() should be treated as a severe
**	    error which should not let us continue.
** 	22-jan-2000 (somsa01)
**	    Return the exit code of the spawned process. Also, if the
**	    files exist, truncate them. The service name is now keyed off
**	    of II_INSTALLATION.
**	05-jun-2000 (somsa01)
**	    The Ingres installation may be started as the SYSTEM account,
**	    in which the 'ingres' user will not automatically have access
**	    to the shared memory segments. Therefore, even if the real
**	    user is 'ingres', check to see if he has access.
**	24-oct-2000 (somsa01)
**	    Removed the check on shared memory access. Access to the shared
**	    memory segment does not necessarily mean that the user running
**	    the process does not need to run the specified process as the
**	    Ingres owner. Also, generalized the check of the user with
**	    IDname_service().
**	18-dec-2000 (somsa01)
**	    Modified the cases to run the command "as is" without the Ingres
**	    service.
**	20-mar-2002 (somsa01)
**	    If all is well, return the exit code of the child process that
**	    was executed.
**	29-mar-2002 (somsa01)
**	    Properly return the child process exit code.
**	11-apr-2003 (somsa01)
**	    While waiting for "pending" to not be set, give some CPU back
**	    to the OS.
**      29-Jul-2005 (drivi01)
**	    Allow user to run the command if he/she owns a shared
**	    segment and ingres is not running as a service.
**	06-Dec-2006 (drivi01)
**	    Adding support for Vista, Vista requires "Global\" prefix for
**	    shared objects as well.  Replacing calls to GVosvers with 
**	    GVshobj which returns the prefix to shared objects.
**	    Added PCadjust_SeDebugPrivilege to allow quering of 
**	    System processes.
**	25-Jul-2007 (drivi01)
**		On Vista, PCexec_suid is unable to use SE_DEBUG Privilege
**	    to query process status and retireve its exit code.
**		The routine for monitoring a process and retrieving 
**	    its exit code has been moved to Ingres Service.
**	05-Nov-2009 (wanfr01) b122847
**	    Don't do a PCsleep unless you are waiting for more input
*/
STATUS
PCexec_suid(char *cmdbuf)
{
    EX_CONTEXT		context;
    SERVICE_STATUS	ssServiceStatus;
    LPSERVICE_STATUS	lpssServiceStatus = &ssServiceStatus;
    struct SETUID	setuid;
    DWORD		ProcID;
    HANDLE		SaveStdout;
    SECURITY_ATTRIBUTES	sa;
    CHAR		szRealUserID[25] = "";
    CHAR		*pszRealUserID = szRealUserID;
    CHAR		szServiceUserID[25] = "";
    CHAR		*pszServiceUserID = szServiceUserID;
    DWORD		BytesWritten, BytesRead = 0;
    CHAR		*inst_id;
    CHAR		SetuidShmName[64];
    CHAR		*temp_loc;
    CHAR		InBuf[256], OutBuf[256];
    static CHAR		SetuidPipeName[32];
    CL_ERR_DESC		err_code;
    CHAR		ServiceName[255];
    DWORD		ExitCode = 0;
    CHAR		tchII_INSTALLATION[3];
    BOOL		SetuidDbCmd = FALSE, ServiceCommand = FALSE;
    int			i, cmdlen;
    char		*ObjectPrefix;
	u_i4		drType;
    SC_HANDLE		schSCManager, OpIngSvcHandle;
    BOOL		bServiceStarted = FALSE;

    if (EXdeclare(ex_handler, &context) != OK)
    {
	EXdelete();
	PCexit(FAIL);
    }
    NMgtAt("II_INSTALLATION", &inst_id);
    STcopy(inst_id, tchII_INSTALLATION);

    /*
    ** See if this is a command that MUST be run through the Ingres
    ** service.
    */
    cmdlen = (i4)STlength(cmdbuf);
    for (i = 0; ServiceCommands[i] ; i++)
    {
	if (STbcompare( cmdbuf, cmdlen, ServiceCommands[i],
			(i4)STlength(ServiceCommands[i]), FALSE ) == 0)
	{
	    ServiceCommand = TRUE;
	    break;
	}
    }

    /*
    ** If the user is the same as the user who started the Ingres
    ** service, just spawn the command.
    */
    if (!ServiceCommand)
    {
	IDname(&pszRealUserID);
	if (!IDname_service(&pszServiceUserID) &&
	    STcompare(pszServiceUserID, pszRealUserID) == 0 && 
		PCisAdmin())
	{
	    /*
	    ** Attempt to just execute the command.
	    */
	    return( PCcmdline( (LOCATION *) NULL, cmdbuf, PC_WAIT,
		    (LOCATION *) NULL, &err_code) );
	}
	else
	{
	    /*
	    ** If current user is not the same as service user and ingres is not
	    ** running as a service, check if shared memory segment is owned
	    ** by current user, if user has access to shared segment allow him
	    ** to run the command.
	    */
	    PTR	shmem;
	    SIZE_TYPE	allocated_pages=0;
	    STATUS status;

	    if((status = MEget_pages(ME_MSHARED_MASK, 1, "lglkdata.mem",
	                 &shmem, &allocated_pages, &err_code)) == OK)
	    {
	        STprintf(ServiceName, "%s_Database_%s", SYSTEM_SERVICE_NAME, 
		tchII_INSTALLATION);
	        if ((schSCManager = OpenSCManager(NULL, NULL, 
					SC_MANAGER_CONNECT)) != NULL)
	        {
		    if ((OpIngSvcHandle = OpenService(schSCManager, ServiceName,
					SERVICE_QUERY_STATUS)) != NULL)
		    {
		       if (QueryServiceStatus(OpIngSvcHandle,lpssServiceStatus))
		       {
		    	if (ssServiceStatus.dwCurrentState != SERVICE_STOPPED)
			     bServiceStarted = TRUE;
		        }
		    }
	        }	
	        if (!bServiceStarted)
		    return(PCcmdline( (LOCATION *) NULL, cmdbuf, PC_WAIT,
			(LOCATION *) NULL, &err_code) );
	    }

	}

	/*
	** See if this command is an Ingres command which needs to interact
	** with at least one database.
	*/
	for (i = 0; validSetuidDbCmds[i] ; i++)
	{
	    if (STbcompare( cmdbuf, cmdlen, validSetuidDbCmds[i],
			    (i4)STlength(validSetuidDbCmds[i]), FALSE ) == 0)
	    {
		SetuidDbCmd = TRUE;
		break;
	    }
	}

	/*
	** If the user has access to the Ingres shared memory segment,
	** just spawn the command provided that it is not in the
	** validSetuidDbCmds list.
	*/
	if (!SetuidDbCmd)
	{
	    PTR	shmem;
	    SIZE_TYPE	allocated_pages=0;
	    STATUS	status;

	    if (((status = MEget_pages(ME_MSHARED_MASK, 1, "lglkdata.mem",
		&shmem,
		&allocated_pages, &err_code)) == OK) ||
		(status == ME_NO_SUCH_SEGMENT))
	    {
		if (status != ME_NO_SUCH_SEGMENT)
		    MEfree_pages(shmem, allocated_pages, &err_code);
		
		return( PCcmdline( (LOCATION *) NULL, cmdbuf, PC_WAIT,
			(LOCATION *) NULL, &err_code) );
	    }
	}
    }

    /*
    ** We must run the command through the Ingres service.
    */

    if ( STstrindex(cmdbuf, "-silent", 0, FALSE ) )
	SilentMode = TRUE;

    iimksec(&sa);


	GVshobj(&ObjectPrefix);
	STprintf(SetuidShmName, "%s%sSetuidShm", ObjectPrefix, tchII_INSTALLATION);

    if ( (SetuidShmHandle = OpenFileMapping(FILE_MAP_READ | FILE_MAP_WRITE,
					    FALSE,
					    SetuidShmName)) == NULL )
    {
	error_exit(GetLastError());
	return(FAIL);
    }
    if ( (SetuidShmPtr = MapViewOfFile(SetuidShmHandle,
				       FILE_MAP_WRITE | FILE_MAP_READ,
				       0,
				       0,
				       sizeof(struct SETUID_SHM))) == NULL )
    {
	error_exit(GetLastError());
	return(FAIL);
    }

    /* Set up the information to send to the service. */
    STcopy(cmdbuf, setuid.cmdline);
    GetCurrentDirectory(sizeof(setuid.WorkingDirectory),
			setuid.WorkingDirectory);
	NMgtAt("II_TEMPORARY", &temp_loc);
	drType = GetDriveType(NULL);
	if (drType == DRIVE_REMOTE)
	{
		STcopy(temp_loc, setuid.WorkingDirectory);
	}
    SaveStdout = GetStdHandle(STD_OUTPUT_HANDLE);
    CVla(GetCurrentProcessId(), setuid.ClientProcID);
    STprintf(SetuidPipeName, "\\\\.\\PIPE\\INGRES\\%s\\SETUID", inst_id);

    /* Set up the stdout file for the command. */
    STprintf(OutfileName, "%s\\%sstdout.tmp", temp_loc, setuid.ClientProcID);
    if ( (OutFile = CreateFile(OutfileName,
			       GENERIC_READ | GENERIC_WRITE,
			       FILE_SHARE_READ | FILE_SHARE_WRITE,
			       &sa,
			       CREATE_ALWAYS,
			       FILE_ATTRIBUTE_NORMAL,
			       NULL)) == INVALID_HANDLE_VALUE )
    {
	error_exit(GetLastError());
	return(FAIL);
    }

    /* Set up the stdin file for the command. */
    STprintf(InfileName, "%s\\%sstdin.tmp", temp_loc, setuid.ClientProcID);
    if ( (InFile = CreateFile(InfileName,
			      GENERIC_READ | GENERIC_WRITE,
			      FILE_SHARE_READ | FILE_SHARE_WRITE,
			      &sa,
			      CREATE_ALWAYS,
			      FILE_FLAG_WRITE_THROUGH,
			      NULL)) == INVALID_HANDLE_VALUE )
    {
	error_exit(GetLastError());
	return(FAIL);
    }

    /* Wait until the service is ready to process our request. */
    while (SetuidShmPtr->pending == TRUE)
	PCsleep(100);
    SetuidShmPtr->pending = TRUE;

    /* Trigger the "setuid" event of the service. */
    if ( (schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT)) == NULL)
    {
	error_exit(GetLastError());
	return(FAIL);
    }

    STprintf(ServiceName, "%s_Database_%s", SYSTEM_SERVICE_NAME,
	     tchII_INSTALLATION );
	OpIngSvcHandle = OpenService(schSCManager, ServiceName,
						SERVICE_USER_DEFINED_CONTROL);
	if (OpIngSvcHandle == NULL)
	{
		STprintf(ServiceName, "%s_DBATools_%s", SYSTEM_SERVICE_NAME,
	     tchII_INSTALLATION );
		OpIngSvcHandle = OpenService(schSCManager, ServiceName,
						SERVICE_USER_DEFINED_CONTROL);
	}
    if ( OpIngSvcHandle == NULL)
    {
	error_exit(GetLastError());
	return(FAIL);
    }
    if (!ControlService(OpIngSvcHandle, RUN_COMMAND_AS_INGRES,
			lpssServiceStatus))
    {
	error_exit(GetLastError());
	CloseServiceHandle(schSCManager);
	return(FAIL);
    }

    WaitNamedPipe(SetuidPipeName, NMPWAIT_WAIT_FOREVER);

    /* Send the information to the service. */
    if ( (Setuid_Handle = CreateFile(SetuidPipeName,
				     GENERIC_READ|GENERIC_WRITE,
				     FILE_SHARE_READ|FILE_SHARE_WRITE,
				     &sa,
				     OPEN_EXISTING,
				     FILE_ATTRIBUTE_NORMAL,
				     NULL)) == INVALID_HANDLE_VALUE )
    {
	error_exit(GetLastError());
	return(FAIL);
    }
    if (!WriteFile(Setuid_Handle, &setuid, sizeof(struct SETUID),
		   &BytesWritten, NULL))
    {
	error_exit(GetLastError());
	return(FAIL);
    }

    /*
    ** Retrieve information back from the service, and then
    ** disconnect from the pipe.
    */
    if (!ReadFile(Setuid_Handle, &setuid, sizeof(struct SETUID),
		  &BytesRead, NULL))
    {
	error_exit(GetLastError());
	return(FAIL);
    }

    ProcID = setuid.CreatedProcID;
    SetuidShmPtr->pending = FALSE;

    UnmapViewOfFile(SetuidShmPtr);
    SetuidShmPtr = NULL;
    CloseHandle(SetuidShmHandle);

    if ( (ProcID != -1) && (ProcID != -2) )
    {
	/*
	** Wait for the "spawned" process to exit, reading its output
	** from the stdout file.
	*/
	for (;;)
	{
	    if ( ((!ReadFile(OutFile, OutBuf, sizeof(OutBuf), &BytesRead, NULL)
		  || (BytesRead == 0)) && setuid.ExitCode != STILL_ACTIVE ))
		break;

	    if ( BytesRead &&
		 (!WriteFile(SaveStdout, OutBuf, BytesRead, &BytesWritten,
		  NULL)) && setuid.ExitCode != STILL_ACTIVE)
		break;
	    else if (BytesRead < sizeof(OutBuf))
		PCsleep(200);

	    /*
	    ** Currently, the only DBA program which can require
	    ** user input is verifydb. Therefore, when it spits out
	    ** the appropriate messages asking for user input, get
	    ** it from the end user and pass it along to the spawned
	    ** process.
	    */
	    if ( (STrstrindex(OutBuf, "S_DU04FF_CONTINUE_PROMPT", 0, FALSE)
			!= NULL) ||
		 (STrstrindex(OutBuf, "S_DU0300_PROMPT", 0, FALSE) != NULL) )
	    {
		SIflush(stdout);
		MEfill(sizeof(OutBuf), ' ', &OutBuf);
		MEfill(sizeof(InBuf), ' ', &InBuf);
		SIgetrec(InBuf, 255, 0);
		WriteFile(InFile, InBuf, sizeof(OutBuf), &BytesWritten, NULL);
	    }
	}

	ExitCode = setuid.ExitCode;
	CloseHandle(Setuid_Handle);
	CloseHandle(InFile);
	DeleteFile(InfileName);
	CloseHandle(OutFile);
	DeleteFile(OutfileName);
	CloseServiceHandle(OpIngSvcHandle);
	CloseServiceHandle(schSCManager);
        return(ExitCode);
    }
    else
    {
	error_exit(GetLastError());
	return(FAIL);
    }
}
Esempio n. 2
0
int
main(int argc, char *argv[])
{
#define 	MAXBUF	4095

	char 	buf[ MAXBUF+1 ];
	int	iarg, ibuf, ichr;
	bool	debug = FALSE;
        CL_ERR_DESC     err_code;
        char		*p1 = NULL;
        char		pid[MAXBUF];
        char    	*database = ERx("");
        char    	*user = ERx("");
        char    	*xmlfile = ERx("");
        char    	sql_fname[LO_NM_LEN + 1];
        char    	*work_dir = NULL;
        char    	directory[MAX_LOC + 1]; 
        char    	*tmp_dir = NULL;
        char		tmp_buf[MAX_LOC + 1];
        char		subdir_buf[MAX_LOC + 1];
        char		sql_loc_buf[MAX_LOC + 1];
	char		*progname; 
        LOCATION    tmp_dir_loc;
        LOCATION    tmp_subdir_loc;
        LOCATION    tmp_buff_loc;
        LOCATION    curr_loc;
        LOCATION    sql_file_loc;
	char        *password = ERx("");
	char        *groupid = ERx("");
	ARGRET  rarg;
        i4      pos;
	LOCATION    xmlfile_loc;
	FILE	    *xmlfile_read;
	STATUS	    stat = FAIL;
	char	    dbuf[256];
	char	    encode[32];
        u_i4        tmppid;
        TM_STAMP    tm_stamp;


	/* Tell EX this is an ingres tool. */
   	(void) EXsetclient(EX_INGRES_TOOL);

	/* Call IIUGinit to initialize character set attribute table */
	if ( IIUGinit() != OK)
	    PCexit(FAIL);

	progname = ERget(F_XM0006_IMPXML);
	FEcopyright(progname, ERx("2001")); 

	/*
	** Get arguments from command line
	*/

	/* required parameters */

	if (FEutaopen(argc, argv, ERx("xmlimport")) != OK)
          PCexit(FAIL);

	/* database name is required */
	if (FEutaget(ERx("database"), 0, FARG_PROMPT, &rarg, &pos) != OK)
          PCexit(FAIL);
	database = rarg.dat.name;

        if (FEutaget(ERx("xmlfile"), 0, FARG_PROMPT, &rarg, &pos) != OK)
            PCexit(FAIL);
        xmlfile = rarg.dat.name;

        if (FEutaget(ERx("user"), 0, FARG_FAIL, &rarg, &pos) == OK)
            user = rarg.dat.name;

        if (FEutaget(ERx("password"), 0, FARG_FAIL, &rarg, &pos) == OK)
        {
            char *IIUIpassword();

            if ((password = IIUIpassword(ERx("-P"))) == NULL)
            {
                FEutaerr(BADARG, 1, ERx(""));
                PCexit(FAIL);
            }
        }

        if (FEutaget(ERx("groupid"), 0, FARG_FAIL, &rarg, &pos) == OK)
          groupid = rarg.dat.name;

        if (FEutaget(ERx("debug"), 0, FARG_FAIL, &rarg, &pos) == OK)
	  debug = TRUE;

        ibuf = STlength(buf); 

        /* b121678: pid is no longer based on process id, but it's
        ** a random number instead.
        */
        PCpid(&tmppid);
        TMget_stamp(&tm_stamp);
        MHsrand2(tmppid * tm_stamp.tms_usec);
        STprintf(pid, "%x", MHrand2());

#ifdef xDEBUG
        SIprintf(" the pid is: %s \n", pid);
#endif

        /* create the sql file */
	/* Avoid a name like "foo.xml.sql" on VMS, use pid.sql instead */
        STcopy(pid, sql_fname); 
        STcat(sql_fname, ".sql");

        /* 
        ** create in the temp location a directory 
        ** with the name pid. set this directory 
        ** as the working directory for impxml
        */

      NMloc (TEMP, PATH, NULL, &tmp_dir_loc);	
      /* make a location for TMP loc */
      /* print location name */
      LOcopy (&tmp_dir_loc, tmp_buf, &tmp_buff_loc);
      LOtos (&tmp_buff_loc, &tmp_dir);

#ifdef xDEBUG
      SIprintf ("temploc: %s \n", tmp_dir);
#endif

      /* make a subdir location with filename, pid */
      STcopy (pid, subdir_buf);				
      /* Initialize result loc so that everyone is happy */
      LOcopy (&tmp_dir_loc, sql_loc_buf, &sql_file_loc); 
      /* Generate location for temp subdirectory */
      if (LOfaddpath (&tmp_dir_loc, subdir_buf, &sql_file_loc) != OK)
      {
	 IIUGerr(E_XM0007_Locname_Failed, UG_ERR_FATAL, 2, tmp_dir, subdir_buf);
	 /* NOTREACHED */
      }

      /* print the location name */
      LOcopy (&sql_file_loc, tmp_buf, &tmp_buff_loc);    
      LOtos (&tmp_buff_loc, &work_dir);

#ifdef xDEBUG
	SIprintf ("work dir loc: %s \n", work_dir);
#endif

      /* create the subdir */
      if (LOcreate (&sql_file_loc) != OK) {
	 IIUGerr(E_XM0008_Create_Temp_Dir, UG_ERR_ERROR, 1, work_dir);
	 PCexit(FAIL);
      }

      STcopy(work_dir, directory);

#ifdef xDEBUG
      SIprintf ("sql file name: %s \n", sql_fname);
      SIprintf ("xml file name: %s \n", xmlfile);
#endif

      /* Execute the command impxml */	
      STprintf (buf, ERx( "impxml -d=\"%s\" -o=\"%s\" " ),  directory, sql_fname);

      /* encoding? */
      if ( (LOfroms(PATH & FILENAME, xmlfile, &xmlfile_loc) != OK)
          ||
	  (SIopen(&xmlfile_loc, "r", &xmlfile_read) != OK)
	  ||
	  (xmlfile_read == NULL)
	 )
      {
	  IIUGerr(E_XM0009_Cannot_Open_File, UG_ERR_ERROR, 1, xmlfile);
          PCexit(FAIL);
      }

      /* scan XML declaration for encoding, if any */
      if (stat = SIgetrec(dbuf, sizeof(dbuf) - 1, xmlfile_read) == OK)
      {
	  char 	*d = dbuf;
	  i4	i = 0;

	  for (d = dbuf; d != (dbuf + sizeof(dbuf)); d++)
	  {
	      if (MEcmp(d, ERx("encoding="), sizeof(ERx("encoding=")) - 1) == 0)
	      {
		  d += sizeof(ERx("encoding="));
		  while (MEcmp (d, "\'", sizeof(char)) && MEcmp(d, "\"", sizeof(char)))
		      MEcopy(d++, sizeof(char), &encode[i++]);
		  encode[i++] = MIN_CHAR;
		  encode[i] = EOS;
		  STcat(buf, ERx("-x="));
		  STcat(buf, encode);
		  break;
	      }
	  }
      }
      else if (stat != ENDFILE)
      {
          /* unable to read file, report error */
	  IIUGerr(E_XM000A_Cannot_Read_File, UG_ERR_ERROR, 1, xmlfile);
	  PCexit(FAIL);
      }

      stat = SIclose(xmlfile_read);

      STcat(buf, xmlfile);

#ifdef xDEBUG
      SIprintf ( " query send: %s \n", buf);
#endif

      /* 	Execute the command.  
      */

      if( PCcmdline((LOCATION *) NULL, buf, PC_WAIT, 
  		(LOCATION *)NULL, &err_code) != OK )
      {
	if (!debug)
	    LOdelete(&sql_file_loc);
	PCexit(FAIL);
      }

      /*
      **	we should run the sql script 
      **	sql dbname < new_filename
      */
      
      /* save the current location */
      LOcopy(&sql_file_loc, tmp_buf, &curr_loc);

      /* make a full location path to the location first */
      LOfroms(FILENAME, sql_fname, &tmp_buff_loc);
      LOstfile(&tmp_buff_loc, &curr_loc);
      LOcopy (&curr_loc, tmp_buf, &tmp_buff_loc);
      LOtos (&tmp_buff_loc, &tmp_dir);

#ifdef xDEBUG
      SIprintf ("sql file is: %s \n", tmp_dir);
#endif

      /* No space between < and input file for VMS */
      STprintf(buf, ERx( "sql -s %s %s %s %s <%s" ),
			database, user, password, groupid, tmp_dir);
#ifdef xDEBUG
      SIprintf (" query send: %s \n", buf);
#endif

      /*
      **	Execute the command.
      */

      if( PCcmdline((LOCATION *) NULL, buf, PC_WAIT, 
              (LOCATION *)NULL, &err_code) != OK )
      {
	if (!debug)
	    LOdelete(&sql_file_loc);
        PCexit(FAIL); 
      }

      /*
      **    Delete the location
      */
      if (!debug)
	LOdelete(&sql_file_loc);

      PCexit(OK);
}
Esempio n. 3
0
void 
main(int argc, char *argv[])
{
#define 	MAXBUF	4095
#define 	MAX_NAME  32	

	char 		buf[ MAXBUF+1 ];
	char 		repbuf[ MAXBUF+1 ];
	int		iarg, ibuf, ichr;
	char		*database = NULL;
	char 		username[MAX_NAME] = {""};
	LOCATION	tloc;
	LOCATION        loc_out;
	LOCATION        loc_in;
	char            loc_buf[MAX_LOC + 1];
	char            tmp_buf[MAX_LOC + 1];
	char			otmp_buf[MAX_LOC + 1];
	char		dev[MAX_LOC + 1];
	char		path[MAX_LOC + 1];
	char		fprefix[MAX_LOC + 1];
	char		fsuffix[MAX_LOC + 1];
	char		version[MAX_LOC + 1];
	char            odev[MAX_LOC + 1];
	char            opath[MAX_LOC + 1];
	char            ofprefix[MAX_LOC + 1];
	char            ofsuffix[MAX_LOC + 1];
	char            oversion[MAX_LOC + 1];
	char            *new_filename;
	char		*temploc;
	CL_ERR_DESC 	err_code;
	char 		*p1 = NULL;
	bool		usergiven = FALSE;
	bool		Repmod = FALSE;
	bool		nowait = TRUE;
	char	 	waitflag[3];
	
	
	if (argc < 2) 
	{
		usage();
	    PCexit(FAIL);
	}
	
	/* Get the temporary path location */	
	NMloc(TEMP, PATH, NULL, &tloc);		
	LOcopy(&tloc, tmp_buf, &loc_in);
	LOtos(&tloc, &temploc);
	LOcopy(&tloc, otmp_buf, &loc_out);
	     	
	/* Get the new filename for path location */	
	LOuniq(ERx("usrmod"), ERx("sql"), &loc_in);	
	LOtos(&loc_in, &new_filename);
	
	LOuniq(ERx("usrmod"), ERx("out"), &loc_out);

	/* Get just the filename for copydb code   */	
	LOdetail(&loc_in, dev, path, fprefix, fsuffix, version); 
	if ( *fsuffix !=  '\0' )
	{
	    STcat(fprefix, ".");
	    STcat(fprefix, fsuffix);
	}
       /* Get just the filename for copydb code   */
         LOdetail(&loc_out, odev, opath, ofprefix, ofsuffix,oversion);
		STcat(ofprefix, ".");
		STcat(ofprefix, ofsuffix);
	

	STprintf(buf, 
        ERx("copydb -with_modify -nodependency_check -with_index -with_comments -no_persist -parallel -no_repmod -group_tab_idx -no_warn -d\"%s\" -infile=\"%s\" -outfile=\"%s\""
	), temploc, fprefix,ofprefix);
	ibuf = STlength(buf); 

	for (iarg = 1; (iarg < argc) && (ibuf < MAXBUF); iarg++) 
	{

	    if( STscompare( argv[ iarg ], 1, ERx( "-" ), 1 ) == 0 )
		{
			p1 = argv[ iarg ]; 
			(void) CMnext( p1 );

			if ( (STlength(p1) == 0) || 
			  !(((STscompare( p1, 1, ERx( "u" ), 1 ) == 0 ) ||
			  (STscompare( p1, 5, ERx( "noint" ), 5 ) == 0 ) || 
			  (STscompare( p1, 6, ERx( "repmod" ), 6 ) == 0 ) || 
			  (STscompare( p1, 1, ERx( "w" ), 6 ) == 0 ) ||
			  (STscompare( p1, 6, ERx( "online"), 6 ) == 0 )) &&
			  ( argc > 2 ) ))
			{
				usage(); 
				PCexit(FAIL);
			}
			/*
			** Get the username if the -u flag is passed in
			** with the input
			*/
			
			if (STscompare( p1, 1, ERx( "u" ), 1 ) == 0 )
			{
				STcopy(&argv[iarg][2] , (char *)&username);
				usergiven = TRUE;
			}
			else if (STscompare( p1, 1, ERx( "r" ), 1 ) == 0 )
			{ 	
				Repmod = TRUE;
				continue;
			}
			else if (STscompare( p1, 1, ERx( "w"), 1 ) == 0)	
			{	
				nowait = TRUE;
				continue;
			}	
                }              	
		
        if( STscompare( argv[ iarg ], 1, ERx( "+" ), 1 ) == 0 )
		{
			p1 = argv[ iarg ];
			(void) CMnext( p1 );
			if (STscompare( p1, 1, ERx( "w" ), 1 ) == 0 )
			{
				nowait = FALSE;	
				continue;
			}
			else
			{
				usage();
				PCexit(FAIL); 
			}
		}

        if((database == NULL) &&
           (STscompare( argv[ iarg ], 1, ERx( "+" ), 1 ) != 0) &&
           (STscompare( argv[ iarg ], 1, ERx( "-" ), 1 ) != 0))
        {
            database =  argv[ iarg ];
        }

	buf[ibuf++] = ' ';
		for (ichr = 0; (argv[iarg][ichr] != '\0') && (ibuf < MAXBUF); 
			ichr++, ibuf++)
		{
			buf[ibuf] = argv[iarg][ichr];
		}
		buf[ibuf] = '\0';
	}

	/*
	**	Execute the command.
	*/

	if( PCcmdline((LOCATION *) NULL, buf, PC_WAIT, 
			(LOCATION *) NULL, &err_code) != OK )
	    PCexit(FAIL);

	/*
	**	we should run the sql script 
	**	  sql dbname < new_filename
	**	if -u flag given then run:
	**	  sql -uusername dbname < new_filename	
	*/

	if (usergiven)
	  STprintf(buf, ERx( "sql -u%s -s %s <%s" ),
			username, database, new_filename );
	else
	  STprintf(buf, ERx( "sql -s %s <%s" ),
				database, new_filename );

	/*
	**	Execute the command.
	*/

        if( PCcmdline((LOCATION *) NULL, buf, PC_WAIT, 
                        (LOCATION *) NULL, &err_code) != OK )
        {
            STprintf(buf, ERx(" Warning: Non-persistent objects associated with the base table\n in the failed query may have been lost. Please refer to\n %s\n to determine whether any corrective action is required.\n"), new_filename);
            SIfprintf(stdout, buf);
	    PCexit(FAIL);
        }

	/* Now execute the repmod command if the replicator 
	** modify is also required by the user (-repmod)
	*/
	
	if (Repmod)
	{
		
	  if (nowait)
	    STcopy("-w", waitflag) ;
	  else
	    STcopy("+w", waitflag) ;
		
	  if (usergiven)
	    STprintf(repbuf, ERx( "repmod -u%s %s %s" ), 
		username, database, waitflag );
	  else
	    STprintf(repbuf, ERx( "repmod %s %s" ), 
		database, waitflag );
            	
	
	  if( PCcmdline((LOCATION *) NULL, repbuf, PC_WAIT,
                 (LOCATION *) NULL, &err_code) != OK )
     	    PCexit(FAIL);

	}	
	/*
	**	Delete the location
	*/
	LOdelete(&loc_in); 
	LOdelete(&loc_out);
	PCexit(OK);
}
Esempio n. 4
0
STATUS
Run_SED_on_file(SEPFILE **Sep_file,LOCATION *Sep_Loc)
{
    STATUS                 ret_val ;
    CL_ERR_DESC            cl_err;

    LOCATION              *sedtmploc = NULL ;
    LOCATION              *filtmploc = NULL ;

    char                  *SEDbuffer = NULL ;
    char                  *sedtmp = NULL ;
    char                  *filtmp = NULL ;
    char                  *cmd_line = NULL ;
    char                  *sed_dev = NULL ;
    char                  *sed_path = NULL ;
    char                  *sed_name = NULL ;
    char                  *sed_type = NULL ;
    char                  *sed_vers = NULL ;
    char                  *fptr1 = NULL ;
    char                  *fptr2 = NULL ;

    FILE                  *SEDfptr = NULL ;
    FILE                  *fptr = NULL ;

    bool                   Sep_file_empty ;

    sed_dev  = SEP_MEalloc(SEP_ME_TAG_SED, LO_DEVNAME_MAX+1,  TRUE, NULL);
    sed_path = SEP_MEalloc(SEP_ME_TAG_SED, LO_PATH_MAX+1,     TRUE, NULL);
    sed_name = SEP_MEalloc(SEP_ME_TAG_SED, LO_FPREFIX_MAX+1,  TRUE, NULL);
    sed_type = SEP_MEalloc(SEP_ME_TAG_SED, LO_FSUFFIX_MAX+1,  TRUE, NULL);
    sed_vers = SEP_MEalloc(SEP_ME_TAG_SED, LO_FVERSION_MAX+1, TRUE, NULL);

    SEDbuffer = SEP_MEalloc(SEP_ME_TAG_SED, SCR_LINE+1, TRUE, NULL);

    /*
    ** Create Sed output file names.
    */
    sedtmploc = (LOCATION *)SEP_MEalloc(SEP_ME_TAG_SED, sizeof(LOCATION),
					TRUE, NULL);
    filtmploc = (LOCATION *)SEP_MEalloc(SEP_ME_TAG_SED, sizeof(LOCATION),
					TRUE, NULL);
    sedtmp    = SEP_MEalloc(SEP_ME_TAG_TOKEN, MAX_LOC+1, TRUE, NULL);
    filtmp    = SEP_MEalloc(SEP_ME_TAG_TOKEN, MAX_LOC+1, TRUE, NULL);

    LOtos(Sep_Loc, &fptr2);
    STcopy(fptr2, sedtmp);
    STcopy(fptr2, filtmp);
    LOfroms(FILENAME & PATH, sedtmp, sedtmploc);
    LOfroms(FILENAME & PATH, filtmp, filtmploc);
    LOdetail(sedtmploc, sed_dev, sed_path, sed_name, sed_type, sed_vers);
    STcopy(ERx("sed"),sed_type);
    SEP_LOcompose(sed_dev, sed_path, sed_name, sed_type, sed_vers, sedtmploc);
    STcopy(ERx("sdr"),sed_type);
    SEP_LOcompose(sed_dev, sed_path, sed_name, sed_type, sed_vers, filtmploc);

    /*
    ** Copy Sep SI_RACC file to a SI_TXT file.
    */
    SEPrewind(*Sep_file, FALSE);
    if ((ret_val = SIfopen(filtmploc,ERx("w"), SI_TXT, SCR_LINE, &fptr))
	!= OK)
	return(ret_val);

    for (Sep_file_empty = TRUE;
	 (ret_val = SEPgetrec(SEDbuffer, *Sep_file)) == OK;
	 SIputrec(SEDbuffer, fptr))
	if (Sep_file_empty)
	    Sep_file_empty = FALSE;

    SIclose(fptr);

    if (Sep_file_empty == FALSE)
    {   /*
	** Create command line for sed command.
	*/
	LOtos(SED_loc, &fptr1);
	LOtos(filtmploc, &fptr2);
	cmd_line = SEP_MEalloc(SEP_ME_TAG_TOKEN, MAX_LOC+1, TRUE, NULL);
	IISTprintf(cmd_line, "sed -f %s %s", fptr1, fptr2);

	/*
	** Close Sep file and run the SED.
	*/
	SEPclose(*Sep_file);
	ret_val = PCcmdline(NULL, cmd_line, PC_WAIT, sedtmploc, &cl_err);
	if(ret_val != OK)
	{
	    SEPopen(Sep_Loc, SCR_LINE, Sep_file);
	    del_floc(sedtmploc);
	    del_floc(filtmploc);
	    MEtfree(SEP_ME_TAG_SED);
	    return(1);
	}

	/*
	** Recreate Sep file.
	*/
#ifdef NT_GENERIC
	LOdelete(Sep_Loc);
#else
	del_floc(Sep_Loc);
#endif
	if ((ret_val = SIfopen(Sep_Loc, ERx("w"), SI_RACC, SCR_LINE, &fptr))
	    != OK)
	    return(ret_val);
	SIclose(fptr);
	SEPopen(Sep_Loc, SCR_LINE, Sep_file);

	/*
	** Open Sed output file.
	*/
	if ((ret_val = SIfopen(sedtmploc, ERx("r"), SI_TXT, SCR_LINE, &SEDfptr))
	    != OK)
	    return(ret_val);

	/*
	** Copy the Sed output file to the Sep file.
	*/
	while((ret_val = SIgetrec(SEDbuffer, SCR_LINE, SEDfptr)) == OK)
	    SEPputrec(SEDbuffer, *Sep_file);

	SEPclose(*Sep_file);
	SIclose(SEDfptr);

	/*
	** Reopen the sep file.
	*/
	SEPopen(Sep_Loc, SCR_LINE, Sep_file);

	/*
	** Clean up.
	*/
	del_floc(sedtmploc);
    }
    del_floc(filtmploc);
    MEtfree(SEP_ME_TAG_SED);
    return(OK);
}