Exemplo n.º 1
0
Arquivo: TTFile.C Projeto: juddy/edcde
void TTFile::TT_Exception
	(
	char *     str
	)
{
#ifdef IOSTREAMSWORKS
    cerr << tt_status_message(tt_pointer_error(str)) << endl;
#else
    fprintf(stderr, "%s\n", tt_status_message(tt_pointer_error(str)));
#endif
}
Exemplo n.º 2
0
/******************************************************************************
 *
 * Initiallize Tooltalk world.
 *
 *****************************************************************************/
static void
ToolTalkError(char *errfmt, Tt_status status)
{
    char	*statmsg;

    if (! tt_is_err(status)) return;

    statmsg = tt_status_message(status);
    DtMsgLogMessage( "Dtexec", DtMsgLogStderr, errfmt, statmsg );
}
Exemplo n.º 3
0
void
_ttDtPrintStatus(
	const char     *whence,
	const char     *expr,
	Tt_status	status
)
{
	_tt_syslog( 0, LOG_ERR, "%s: %s: %s\n",
		    whence, expr, tt_status_message( status ));
}
Exemplo n.º 4
0
/*
 * remover::close_tt()
 */
Tt_status remover::
close_tt()
{
	if (! _tt_opened) {
		return TT_OK;
	}
	Tt_status err = tt_close();
	if (err > TT_WRN_LAST) {
		fprintf( stderr,
			 "%s: tt_close(): %s\n",
			 (char *)_process_name, tt_status_message(err) );
	}
	return err;
}
Exemplo n.º 5
0
/*
 * remover::open_tt()
 */
Tt_status remover::
open_tt()
{
	char *process_id = tt_open();
	Tt_status err = tt_ptr_error( process_id );
	if (err == TT_OK) {
		_process_id = process_id;
		_tt_opened = TRUE;
	} else if (err > TT_WRN_LAST) {
		fprintf( stderr,
			 "%s: tt_open(): %s\n",
			 (char *)_process_name, tt_status_message(err) );
	}
	return err;
}
Exemplo n.º 6
0
/*
 * rcopier::close_tt()
 */
Tt_status rcopier::
close_tt()
{
	if (! _tt_opened) {
		return TT_OK;
	}
	Tt_status err = tt_close();
	if (err > TT_WRN_LAST) {
		fprintf( stderr,
			 "%s: Could not close ToolTalk because %s\n",
			 (char *)_process_name,
#ifndef TT_STATUS_MSG_TO_DO
			 _tt_enumname( (Tt_status)err )
#else
			 tt_status_message( err )
#endif
		       );
	}
	return err;
}
Exemplo n.º 7
0
/*
 * rcopier::open_tt()
 */
Tt_status rcopier::
open_tt()
{
	char *process_id = tt_open();
	Tt_status err = tt_ptr_error( process_id );
	if (err == TT_OK) {
		_process_id = process_id;
		_tt_opened = TRUE;
	} else if (err > TT_WRN_LAST) {
		fprintf( stderr,
			 "%s: Could not initialize ToolTalk because %s\n",
			 (char *)_process_name,
#ifndef TT_STATUS_MSG_TO_DO
			 _tt_enumname( (Tt_status)err )
#else
			 tt_status_message( err )
#endif
		       );
	}
	return err;
}
Exemplo n.º 8
0
/*************************************************
 *
 * Routine to catch identification reply.
 */
Tt_callback_action IdSelfToCallerReplyCB(
    Tt_message msg,
    Tt_pattern pattern)
{
    Tt_state state;
    Tt_status status;
    char *errorMsg;


    status = tt_message_status(msg);
    state = tt_message_state(msg);

    if (state == TT_FAILED) {
	/*
	 * tjg: At some point, may want to dump the following error
	 * message into a log file.  May have to wrap long messages.
	 */
	if (status < TT_ERR_LAST)
	    errorMsg = tt_status_message(status);
	else
	    errorMsg = tt_message_status_string(msg);

	dtexec_tttk_message_destroy(msg);
	DetachFromTooltalk(NULL);
    }
    else if (state == TT_HANDLED) {
	dtexec_tttk_message_destroy(msg);
	/*
	 * Nothing substantial to do with the request-reply in the current
	 * implementation.
	 */
    }
    else {
    }

    return( (Tt_callback_action) TT_CALLBACK_PROCESSED );
}
Exemplo n.º 9
0
int
_DtCmdCommandInvokerExecute (
    char *errorMessage,		/* MODIFIED */
    DtSvcMsgContext replyContext,	/* OBSOLETE -- always NULL */
    int  winMask,
    char *contextHost,
    char *contextDir,
    char *contextFile,		/* OBSOLETE -- always NULL */
    char *execParms,
    char *execHost,
    char *execString,
    char *procId,
    char *tmpFiles,
    DtCmdInvExecuteProc success_proc,
    void *success_data,
    DtCmdInvExecuteProc failure_proc,
    void *failure_data)

{
    int ioMode, i, index1;
    int windowType;
    pid_t commandPid;
    char context[MAXPATHLEN];
    char tmpDir [MAXPATHLEN];
    char **commandArray;
    SPC_Channel_Ptr cmdChannel;
    char *theCommand = NULL;
    Boolean terminalRequest = False;
    char *commandArray2[MAX_EXEC_ARGS];
    Boolean localExecution = True;
    Boolean xhostError;
    static unsigned long requestNum = 0;
    char *toolRequest = NULL;	/* backward compatibility kludge */


    myassert( !(contextFile && replyContext) );

    /*
     * Check for a valid window-type.
     * This check is probably redundant but it converts the mask bits into
     * small integer values used by the rest of the command invoker code.
     */
    if ((windowType=
                DtCmdGetWindowType(winMask))== -1)
    {
        (void) sprintf (errorMessage, errorRequest, toolRequest,
                        DtTERMINAL, DtPERM_TERMINAL, DtOUTPUT_ONLY,
                        DtSHARED_OUTPUT, "" /* Obsolete shell window */,
                        DtNO_STDIO);
        return (_CMD_EXECUTE_FATAL);
    }

    /*
     * Create the command to be exec'ed.
     */
    if (windowType == PERM_TERMINAL || windowType == TERMINAL)
    {
        _DtCmdCreateTerminalCommand (&theCommand, windowType, execString,
                                     execParms, execHost, procId, tmpFiles);
        terminalRequest = True;
    }
    else
    {
        /*
         * NO-STDIO || START-SESSION request.
         */

        theCommand = XtMalloc(
                         + strlen (cmd_Resources.dtexecPath)
                         + strlen(" -open ") + 4 /* waitTime len */
                         + strlen(" -ttprocid ") + strlen(_DtActNULL_GUARD(procId))
                         + strlen(_DtActNULL_GUARD(tmpFiles))
                         + strlen (execString)
                         + 5 /* for 2 quotes,2 blanks,null */);

        sprintf(theCommand,"%s -open %d -ttprocid '%s' %s %s",
                cmd_Resources.dtexecPath,
                0 /* wait time zero for NO_STDIO */,
                _DtActNULL_GUARD(procId),
                _DtActNULL_GUARD(tmpFiles),
                execString);

    }

    /*
     * See if the request requires Remote Execution.
     */
    localExecution = _DtIsSameHost(execHost,NULL);

    /*
     * If this is a terminalRequest and the Command Invoker subprocess
     * is not executable, return now.
     */
    if (localExecution && terminalRequest && !cmd_Globals.subprocess_ok)
    {
        if (!(_DtCmdCheckForExecutable (cmd_Resources.dtexecPath)))
        {
            (void) sprintf (errorMessage, cmd_Globals.error_subprocess,
                            cmd_Resources.dtexecPath);
            XtFree ((char *) theCommand);
            return (_CMD_EXECUTE_FAILURE);
        }
        else
            cmd_Globals.subprocess_ok = True;
    }

    /*
     * If this is a terminalRequest and the terminal emulator
     * is not executable, return now.
     */
    if (localExecution && terminalRequest && !cmd_Globals.terminal_ok)
    {
        if (!(_DtCmdCheckForExecutable (cmd_Resources.localTerminal)))
        {
            (void) sprintf (errorMessage, cmd_Globals.error_terminal,
                            cmd_Resources.localTerminal);
            XtFree ((char *) theCommand);
            return (_CMD_EXECUTE_FAILURE);
        }
        else
            cmd_Globals.terminal_ok = True;
    }

    /*
     * Break the command into something execvp or SPCSpawn can handle
     * and then free "theCommand" if this is a termianl-based request.
     */
    commandArray = (char **) XtMalloc (MAX_EXEC_ARGS * sizeof (char *));
    _DtCmdStringToArrayOfStrings (theCommand, commandArray);

    XtFree (theCommand);

    if (!localExecution)
    {
        char *netfile;
        char *argv[4];
        char *tmp;

        /* REMOTE Execution */

        ioMode = SPCIO_NOIO | SPCIO_SYNC_TERMINATOR | SPCIO_FORCE_CONTEXT;

        if ((cmdChannel = (_DtSPCOpen(execHost,
                                      ioMode,
                                      errorMessage))) == SPC_ERROR)
        {
            Cmd_FreeAllocatedStringVector (commandArray);
            return (_CMD_EXECUTE_FAILURE);
        }

        /* Old syntax should no longer appear in contextHost/Dir */
        myassert( (contextHost?*contextHost != '*':1) &&
                  (contextDir?*contextDir != '*':1) );
        /*
         * Create a "netfile" for the cwd to be used.
         */
        netfile = (char *) tt_host_file_netfile (
                      ((contextHost == NULL) ? execHost : contextHost),
                      ((contextDir  == NULL) ? (char *) getenv ("HOME") : contextDir));

        if (tt_pointer_error (netfile) != TT_OK) {
            (void) sprintf (errorMessage, cmd_Globals.error_directory_name_map,
                            ((contextDir  == NULL) ? (char *) getenv ("HOME") : contextDir),
                            ((contextHost == NULL) ? execHost : contextHost),
                            tt_status_message (tt_pointer_error(netfile)));
            Cmd_FreeAllocatedStringVector (commandArray);
            return (_CMD_EXECUTE_FAILURE);
        }
        (void) strcpy (context, netfile);
        tt_free (netfile);

        /*
         * First check to see if the "dtexecPath" is executable on
         * the remote execution host by executing it with no
         * options which will cause it to immediately die.
         *
         * There is no need to set up termination handler for this
         * because we don't care when it dies, we only care about
         * whether or not it can be executed.
         */

        argv[0] = cmd_Resources.dtexecPath;
        argv[1] = (char *) NULL;

        if ((_DtSPCSpawn(argv[0], context, argv, NULL, cmdChannel,
                         execHost, contextHost, contextDir, errorMessage))
                == SPC_ERROR)
        {
            if (DtSPCErrorNumber != SPC_cannot_Chdir &&
                    DtSPCErrorNumber != SPC_Cannot_Fork  &&
                    DtSPCErrorNumber != SPC_Env_Too_Big  &&
                    DtSPCErrorNumber != SPC_Arg_Too_Long)
                /*
                 * The Error message must mention that the dtexec
                 * process is not executable so must overwrite the
                 * error message returned by the Spawn function with
                 * an appropriate message.
                 */
                (void) sprintf (errorMessage, errorRemoteSubprocess, execHost,
                                cmd_Resources.dtexecPath);
            DtSPCClose(cmdChannel);
            Cmd_FreeAllocatedStringVector (commandArray);
            return (_CMD_EXECUTE_FAILURE);
        }

        /* The dtexec process is now known to exist on the remote host */

        /*
         *  Now run a test to see if the command is executable
         *  on this exec host.
         */
        _DtCmdStringToArrayOfStrings (execString, commandArray2);

        tmp = (char *) XtMalloc (strlen (commandArray2[0]) +
                                 strlen ("whence ") + 2);
        (void) sprintf (tmp, "whence %s", commandArray2[0]);

        _DtCmdFreeStringVector (commandArray2);

        argv[0] = "ksh";
        argv[1] = "-c";
        argv[2] = tmp;
        argv[3] = (char *) NULL;

        /*
         * Reopen the channel
         */
        if ((cmdChannel = (_DtSPCOpen(execHost,
                                      ioMode,
                                      errorMessage))) == SPC_ERROR)
        {
            Cmd_FreeAllocatedStringVector (commandArray);
            return (_CMD_EXECUTE_FAILURE);
        }

        /*
         * Set up a callback to be invoked when the test command
         * terminates.
         */
        _DtSvcProcessLock();
        if ((DtSPCRegisterTerminator(cmdChannel,
                                     (SPC_TerminateHandlerType) CheckCommandTerminator,
                                     (void *) ++requestNum)) == SPC_ERROR)
        {
            DtSPCClose(cmdChannel);
            Cmd_FreeAllocatedStringVector (commandArray);
            (void) strcpy (errorMessage, errorSpcTerminator);
            XtFree ((char *) tmp);
            _DtSvcProcessUnlock();
            return (_CMD_EXECUTE_FAILURE);
        }

        if ((_DtSPCSpawn(argv[0], context, argv, NULL, cmdChannel,
                         execHost, contextHost, contextDir, errorMessage))
                == SPC_ERROR)
        {
            DtSPCClose(cmdChannel);
            (void) sprintf (errorMessage, errorRemoteSubprocess, execHost,
                            argv[0]);
            Cmd_FreeAllocatedStringVector (commandArray);
            XtFree ((char *) tmp);
            _DtSvcProcessUnlock();
            return (_CMD_EXECUTE_FAILURE);
        }
        /*
         * The command line checking process has been spawned.
         * There is nothing left to do but to queue the request
         * and return to the client's main loop.  The command
         * line will be executed after the above spawned process
         * terminates.
         */
        QueueRequest (cmdChannel, context, execHost, execString,
                      commandArray, windowType, requestNum, replyContext,
                      success_proc, success_data, failure_proc, failure_data);
        _DtSvcProcessUnlock();
        XtFree(tmp);
        return (_CMD_EXECUTE_QUEUED);
    }
    else
    {
        /* LOCAL Execution */

        /*
         * Must first check to see if the execvp will potentially fail.
         *
         * Since the terminal emulator is pre-appended onto the execution
         * string, don't want to check it (should have been done during
         * startup (in _DtInitializeCommandInvoker)) but must check the
         * execution string that was passed in as part of the message.
         */
        /* Break the command into something execvp can handle */
        _DtCmdStringToArrayOfStrings (execString, commandArray2);

        if (!_DtCmdCheckForExecutable (commandArray2[0]))
        {
            (void) sprintf (errorMessage, errorExec, commandArray2[0]);
            Cmd_FreeAllocatedStringVector (commandArray);
            _DtCmdFreeStringVector (commandArray2);
            return (_CMD_EXECUTE_FAILURE);
        }
        _DtCmdFreeStringVector (commandArray2);

        /*
         * Save the current directory and then "chdir" to the directory
         * to do the execution.  If the chdir fails, return.
         */
        (void) getcwd (tmpDir, MAXPATHLEN);

        if (!_DtCmdValidDir (_cmdClientHost, contextDir, contextHost))
        {
            Cmd_FreeAllocatedStringVector (commandArray);
            (void) sprintf (errorMessage, errorChdir, contextDir, execHost);
            (void) chdir (tmpDir);
            return (_CMD_EXECUTE_FAILURE);
        }

        /*
         * Restore the original environment and remove any DT
         * specific environment variables that were added.
         */
        (void) _DtEnvControl (DT_ENV_RESTORE_PRE_DT);

        /* Fork and then execvp the execution string */
        for (index1 = 0; (index1 < 10) &&
                ((commandPid = fork ()) < 0); index1++)
        {
            /* Out of resources ? */
            if (errno != EAGAIN)
                break;
            /* If not out of resources, sleep and try again */
            (void) sleep ((unsigned long) 2);
        }

        if (commandPid < 0)
        {
            Cmd_FreeAllocatedStringVector (commandArray);
            (void) chdir (tmpDir);
            (void) sprintf(errorMessage, errorFork, execHost);
            (void) _DtEnvControl (DT_ENV_RESTORE_POST_DT);
            return (_CMD_EXECUTE_FAILURE);
        }

        if (commandPid == 0)
        {

#if defined(__hp_osf) || defined(__osf__) || defined(CSRG_BASED)
            setsid() ;
#else
            (void) setpgrp ();
#endif

            if (!terminalRequest )
            {
                int fd;

                /*
                 * Close stdout and redirect it to /dev/null.  If this
                 * is not done and the request writes to stdout, the
                 * output will be queued in an "unlinked" file in
                 * /tmp until the client using this code terminates.
                 */
                if ((fd = open ("/dev/null", O_RDWR)) > 0)
                    (void) dup2 (fd, fileno (stdout));
            }

            /*
             * Mark file descriptiors >=3 as "Close on Exec".
             */
            {
                long	open_max;

                open_max = sysconf(_SC_OPEN_MAX);
                if (open_max == -1)
                {
#ifdef _SUN_OS
                    open_max = NOFILE;
#else
#if defined(USL) || defined(__uxp__) || defined(_AIX)
                    open_max = FOPEN_MAX;
#else
                    open_max = FD_SETSIZE;
#endif
#endif /* _SUN_OS */
                }

                for (i=3; i < open_max; i++)
                    (void) fcntl (i, F_SETFD, 1);
            }


            (void) execvp (commandArray[0], commandArray);

            /* Should never get here, but if you do, must exit */

            /*
             * The following message will be written to the errorlog
             * file if the request is not a terminal requests or
             * to the terminal window if the request requires a
             * terminal.
             */
            (void) sprintf (errorMessage, errorExec, commandArray[0]);
            (void) printf ("%s\n", errorMessage);
            (void) _exit (1);
        }

        /*
         * Restore the pre-fork environment.
         */
        (void) chdir (tmpDir);
        (void) _DtEnvControl (DT_ENV_RESTORE_POST_DT);
    }

    Cmd_FreeAllocatedStringVector (commandArray);

    return (_CMD_EXECUTE_SUCCESS);
}
Exemplo n.º 10
0
DtMail::Session::Session(DtMailEnv & error, const char * app_name)
: _events(16), _valid_keys(2048)
{
    _DtMutex = MutexInit();

    error.clear();

    _object_signature = 0;
    _cur_key = 0;

    // Create the ToolTalk session for managing file locking,
    // if one doesn't exist.
    _tt_channel = tt_default_procid();
    if (tt_pointer_error(_tt_channel) != TT_OK) {
	_tt_channel = ttdt_open(&_tt_fd, app_name, "SunSoft", "%I", 0);
	if (tt_pointer_error(_tt_channel) != TT_OK) {
	    error.setError(DTME_TTFailure);
	    DebugPrintf(1,
			"DtMail::createSession - ttdt_open returns %s\n",
			tt_status_message(tt_pointer_error(_tt_channel)));
	    return;
	}
    }
    else {
	_tt_fd = tt_fd();
    }

    // The event_fd is how we allow async behavior to occur in a
    // compatible way. We use a Unix domain socket as the file descriptor.
    // The client will watch for activity on this file descriptor, and
    // call our event routine when there is activity (either from XtMainLoop,
    // or through some other method).
    //
    pipe(_event_fd);

    _app_name = strdup(app_name);

    DtMailEnv b_error;

    _mail_rc = new MailRc(error, this);

    buildImplTable(error);
    if (error.isSet()) {
	return;
    }

    _obj_mutex = MutexInit();

    // The default implementation is specified via the DEFAULT_BACKEND
    // variable. If this is not set in the .mailrc, then choose entry
    // zero.
    //
    const char * value;
    _mail_rc->getValue(b_error, "DEFAULT_BACKEND", &value);
    if (b_error.isNotSet()) {
	_default_impl = lookupImpl(value);
	if (_default_impl < 0) {
	    _default_impl = 0;
	}
    }
    else {
	b_error.clear();
	_default_impl = 0;
    }

    DtMailSigChldList = new DtVirtArray<SigChldInfo *>(8);

    _busy_cb = NULL;
    _busy_cb_data = NULL;
    _canAutoSave = DTM_TRUE;

    _object_signature = SessionSignature;

    return;
}
Exemplo n.º 11
0
/*
 * remover::ttrm_path() - tt_file_destroy() this path.
 */
Tt_status remover::
_ttrm_paths( _Tt_string_list_ptr paths )
{
	Tt_status	worst_err = TT_OK;
	Tt_status	err;
	bool_t		abort = FALSE;

	while ((! paths->is_empty()) && (! abort)) {
		_Tt_string		path     = paths->top();
		_Tt_string_list_ptr	children;

		paths->pop();
		if (! this->can_rm( path )) {
			continue;
		}
		if (_recurse) {
			_Tt_string_list_ptr children = _tt_dir_entries(path,
								       FALSE);
			err = this->_ttrm_paths( children );
			if (err > TT_WRN_LAST) {
				switch (err) {
				    case TT_ERR_DBAVAIL:
				    case TT_ERR_PATH:
					break;
				    case TT_ERR_NOMP:
				    case TT_ERR_DBEXIST:
				    default:
					abort = TRUE;
					break;
				}
			}
		}
		if (! abort) {
			err = tt_file_destroy( (char *)path );
			if (err > TT_WRN_LAST) {
				worst_err = err;
				if (! _force) {
					fprintf( stderr,
						 catgets(_ttcatd, 8, 7,
							 "%s: Could not remove "
							 "ToolTalk objects of "
							 "%s because %s\n"),
						 (char *)_process_name,
						 (char *)path,
						 tt_status_message(err) );
				}
				switch (err) {
				    case TT_ERR_DBAVAIL:
				    case TT_ERR_PATH:
					break;
				    case TT_ERR_NOMP:
				    case TT_ERR_DBEXIST:
				    default:
					abort = TRUE;
					break;
				}
			}
		}
	}
	return worst_err;

} /* ttrm_paths() */
Exemplo n.º 12
0
Arquivo: copier.C Projeto: juddy/edcde
/*
 * copier::do_ttcp() - Use tttar(1) to copy the objects of the _from_paths.
 *
 * Algorithm:
 *
 * if (_clonedir_mode) {
 *         cd _from_path; tttar cfhL - . | (cd ../_to_path; tttar xfLp? -)
 * } else {
 *         if (_to_path_is_dir) {
 *                 tttar cfhL - _from_paths | (cd _to_path ; tttar xfLp? - )
 *         } else {
 *                 tttar cfhL - _from_path | tttar xfLp? - -rename from to
 *         }
 * }
 */
Tt_status copier::
do_ttcp()
{
    _Tt_string		cmd;
    _Tt_string_list_cursor	from_path_cursor( _from_paths );
    Tt_status		err;

    if (_clonedir_mode) {
#ifdef DO_TTTAR_AFTER_CP
        if (mkdir( (char *)_to_path, S_IRWXU ) != 0) {
            return TT_ERR_PATH;
        }
#endif
        cmd = cmd.cat( "cd " ).cat( _from_paths->top()).cat( " ; ");
    }
    cmd = cmd.cat( "tttar cfhL -" );
    while (from_path_cursor.next()) {
        _Tt_string from_path = *from_path_cursor;
        if (! this->can_cp( from_path )) {
            /*
             * Don't tttar any paths we know that cp(1) will
             * reject. We do this for clonedir mode, too, so
             * we can return if the cloning shouldn't be done.
             */
            from_path_cursor.remove();
        } else {
            /*
             * tt_file_destroy() any path that cp(1) will delete
             */
            _Tt_string path2zap = _to_path;
            if (_to_path_is_dir) {
                /*
                 * cp(1) will overwrite any entry in _to_path
                 * that has the same name as a _from_path.
                 */
                _Tt_string dir, base;
                base = from_path.rsplit( '/', dir );
                path2zap = _to_path.cat( "/" ).cat( base );
            }
            err = tt_file_destroy( (char *)path2zap );
            if (err > TT_WRN_LAST) {
                fprintf( stderr,
                         catgets(_ttcatd, 8, 12,
                                 "%s: Could not remove "
                                 "ToolTalk objects of %s "
                                 "because %s\n"),
                         (char *)_process_name,
                         (char *)path2zap,
                         tt_status_message(err) );
            }
        }
    }
    if (_from_paths->count() <= 0) {
        return TT_OK;
    }
    if (_clonedir_mode) {
        /*
         * In clonedir mode, we just tttar up everything in
         * the directory we're cloning.
         */
        cmd = cmd.cat( " ." );
    } else {
        from_path_cursor.reset();
        while (from_path_cursor.next()) {
            cmd = cmd.cat( " " ).cat( *from_path_cursor );
        }
    }
    cmd = cmd.cat( " |" );
    if (_to_path_is_dir) {
        cmd = cmd.cat( " ( cd " );
        if (_clonedir_mode) {
            char		realpath_buf[ MAXPATHLEN ];

            /*
             * If we're in _clonedir_mode, then we'll be
             * cd'ing down into _from_path, and so we want
             * a realpath of _to_path to cd over to,
             * because if _from_path is a symlink then
             * in _from_path "../_to_path" is _not_ _to_path.
             */
            char *real_to_path = _tt_get_realpath( (char *)_to_path,
                                                   realpath_buf );
            if (real_to_path == NULL) {
                fprintf( stderr, "%s: %s: %s\n",
                         (char *)_process_name,
                         (char *)_to_path, strerror(errno) );
                return TT_ERR_PATH;
            }
            cmd = cmd.cat( real_to_path );
        } else {
            cmd = cmd.cat( _to_path );
        }
        cmd = cmd.cat( " ;" );
    }
    cmd = cmd.cat( " tttar xfL" );
    if (_preserve) {
        cmd = cmd.cat( "p" );
    }
    cmd = cmd.cat( " -" );
    /*
     * Use the hack we built into tttar(1) to rename paths
     * as they're extracted.  Rename each _from_path to _to_path.
     */
    from_path_cursor.reset();
    while (from_path_cursor.next()) {
        _Tt_string from_path = *from_path_cursor;
        cmd = cmd.cat( " -rename " ).cat( from_path )
              .cat( " " ).cat( _to_path );
        /*
         * If the copy is to be made in a subdirectory of _to_path,
         * make tttar maps _from_path to the appropriate
         * subdirectory of _to_path as it extracts.
         */
        if ((_to_path_is_dir) && (! _clonedir_mode)) {
            _Tt_string dir_name;
            cmd = cmd.cat( "/" )
                  .cat( from_path.rsplit( '/', dir_name ));
        }
    }
    if (_to_path_is_dir) {
        cmd = cmd.cat( " )" );
    }
    //printf( "Invoking: %s\n", (char *)cmd );
    int sys_status = system( (char *)cmd );
#ifdef DO_TTTAR_AFTER_CP
    if (_clonedir_mode) {
        /*
         * remove the target directory, so that cp(1) won't
         * see it and make _from_path a subdirectory of it.
         */
        if (rmdir( (char *)_to_path ) != 0) {
            fprintf( stderr, "%s: rmdir(\"%s\"): %s\n",
                     (char *)_process_name, (char *)_to_path,
                     strerror(errno) );
            return TT_ERR_PATH;
        }
    }
#endif
    if (WIFEXITED(sys_status)) {
        if (WEXITSTATUS(sys_status) == 0) {
            return TT_OK;
        } else {
            return TT_ERR_INTERNAL;
        }
    } else {
        fprintf( stderr,
                 "%s: system(\"%s\"): %d\n",
                 (char *)_process_name, sys_status );
        return TT_ERR_INTERNAL;
    }

} /* do_ttcp() */