1 /*
2  * Part of WCM Commander
3  * https://github.com/corporateshark/WCMCommander
4  * wcm@linderdaum.com
5  */
6 
7 #include "file-exec.h"
8 #include "file-util.h"
9 #include "ncwin.h"
10 #include "ltext.h"
11 #include "string-util.h"
12 #include "panel.h"
13 #include "strmasks.h"
14 #include "ext-app.h"
15 
16 #ifndef _WIN32
17 #  include <signal.h>
18 #  include <sys/wait.h>
19 #  include "ux_util.h"
20 #else
21 #	include "w32util.h"
22 #endif
23 
24 
25 #define TERMINAL_THREAD_ID 1
26 
27 
ReturnToDefaultSysDir()28 void ReturnToDefaultSysDir()
29 {
30 #ifdef _WIN32
31 	wchar_t buf[4096] = L"";
32 
33 	if ( GetSystemDirectoryW( buf, 4096 ) > 0 )
34 	{
35 		SetCurrentDirectoryW( buf );
36 	}
37 
38 #else
39 	chdir( "/" );
40 #endif
41 }
42 
43 
44 enum
45 {
46 	CMD_RC_RUN = 999,
47 	CMD_RC_OPEN_0 = 1000
48 };
49 
50 static const int CMD_OPEN_FILE = 1000;
51 static const int CMD_EXEC_FILE = 1001;
52 
53 
54 struct AppMenuData
55 {
56 	struct Node
57 	{
58 		unicode_t* cmd;
59 		bool terminal;
NodeAppMenuData::Node60 		Node() : cmd( 0 ), terminal( 0 ) {}
NodeAppMenuData::Node61 		Node( unicode_t* c, bool t ) : cmd( c ), terminal( t ) {}
62 	};
63 
64 	ccollect<clPtr<MenuData>> mData;
65 	ccollect<Node> nodeList;
66 	MenuData* AppendAppList( AppList* list );
67 };
68 
AppendAppList(AppList * list)69 MenuData* AppMenuData::AppendAppList( AppList* list )
70 {
71 	if ( !list )
72 	{
73 		return 0;
74 	}
75 
76 	clPtr<MenuData> p = new MenuData();
77 
78 	for ( int i = 0; i < list->Count(); i++ )
79 	{
80 		if ( list->list[i].sub.ptr() )
81 		{
82 			MenuData* sub = AppendAppList( list->list[i].sub.ptr() );
83 			p->AddSub( list->list[i].name.data(), sub );
84 		}
85 		else
86 		{
87 			p->AddCmd( nodeList.count() + CMD_RC_OPEN_0, list->list[i].name.data() );
88 			nodeList.append( Node( list->list[i].cmd.data(), list->list[i].terminal ) );
89 		}
90 	}
91 
92 	MenuData* ret = p.ptr();
93 	mData.append( p );
94 	return ret;
95 }
96 
97 
FileExecutor(NCWin * NCWin,StringWin & editPref,NCHistory & history,TerminalWin_t & terminal)98 FileExecutor::FileExecutor( NCWin* NCWin, StringWin& editPref, NCHistory& history, TerminalWin_t& terminal )
99 	: m_NCWin( NCWin )
100 	, m_EditPref( editPref )
101 	, m_History( history )
102 	, m_Terminal( terminal )
103 	, m_ExecId( -1 )
104 {
105 	m_ExecSN[0] = 0;
106 }
107 
ShowFileContextMenu(cpoint point,PanelWin * Panel)108 void FileExecutor::ShowFileContextMenu( cpoint point, PanelWin* Panel )
109 {
110 	FSNode* p = Panel->GetCurrent();
111 
112 	if ( !p || p->IsDir() )
113 	{
114 		return;
115 	}
116 
117 	clPtr<AppList> appList = GetAppList( Panel->UriOfCurrent().GetUnicode() );
118 
119 	//if (!appList.data()) return;
120 
121 	AppMenuData data;
122 	MenuData mdRes, *md = data.AppendAppList( appList.ptr() );
123 
124 	if ( !md )
125 	{
126 		md = &mdRes;
127 	}
128 
129 	if ( p->IsExe() )
130 	{
131 		md->AddCmd( CMD_RC_RUN, _LT( "Execute" ) );
132 	}
133 
134 	if ( !md->Count() )
135 	{
136 		return;
137 	}
138 
139 	int ret = DoPopupMenu( 0, m_NCWin, md, point.x, point.y );
140 
141 	m_NCWin->SetCommandLineFocus();
142 
143 	if ( ret == CMD_RC_RUN )
144 	{
145 		ExecuteFile( Panel );
146 		return;
147 	}
148 
149 	ret -= CMD_RC_OPEN_0;
150 
151 	if ( ret < 0 || ret >= data.nodeList.count() )
152 	{
153 		return;
154 	}
155 
156 	StartExecute( data.nodeList[ret].cmd, Panel->GetFS(), Panel->GetPath(), !data.nodeList[ret].terminal );
157 }
158 
IsCommand_CD(const unicode_t * p)159 bool IsCommand_CD( const unicode_t* p )
160 {
161 #ifdef _WIN32
162 	return (p[0] == 'c' || p[0] == 'C') && (p[1] == 'd' || p[1] == 'D') && (!p[2] || p[2] == ' ');
163 #else
164 	return (p[0] == 'c' && p[1] == 'd' && (!p[2] || p[2] == ' '));
165 #endif
166 }
167 
ApplyEnvVariable(const char * EnvVarName,std::vector<unicode_t> * Out)168 bool ApplyEnvVariable( const char* EnvVarName, std::vector<unicode_t>* Out )
169 {
170 	if ( !Out )
171 	{
172 		return false;
173 	}
174 
175 	std::string Value = GetEnvVariable( EnvVarName );
176 
177 	if ( Value.empty() )
178 	{
179 		return false;
180 	}
181 
182 	*Out = utf8_to_unicode( Value.c_str() );
183 	return true;
184 }
185 
186 // handle the "cd" command, convert its argument to a valid path, expand ~ and env variables
ConvertCDArgToPath(const unicode_t * p)187 std::vector<unicode_t> ConvertCDArgToPath( const unicode_t* p )
188 {
189 	std::vector<unicode_t> Out;
190 	std::vector<unicode_t> Temp;
191 
192 	while ( p && *p )
193 	{
194 		unicode_t Ch = 0;
195 
196 		if ( *p == '~' )
197 		{
198 			if ( LookAhead( p, &Ch ) )
199 			{
200 				if ( (IsPathSeparator( Ch ) || Ch == 0) && ApplyEnvVariable( "HOME", &Temp ) )
201 				{
202 					// replace ~ with the HOME path
203 					Out.insert( Out.end(), Temp.begin(), Temp.end() );
204 					PopLastNull( &Out );
205 				}
206 			}
207 		}
208 		else if ( *p == '$' )
209 		{
210 			// skip `$`
211 			std::string EnvVarName = unicode_to_utf8( p + 1 );
212 
213 			for ( auto i = EnvVarName.begin(); i != EnvVarName.end(); i++ )
214 			{
215 				if ( IsPathSeparator( *i ) )
216 				{
217 					*i = 0;
218 					break;
219 				}
220 			}
221 
222 			if ( ApplyEnvVariable( EnvVarName.data(), &Temp ) )
223 			{
224 				// replace the var name with its value
225 				Out.insert( Out.end(), Temp.begin(), Temp.end() );
226 				PopLastNull( &Out );
227 				// skip var name
228 				p += strlen( EnvVarName.data() );
229 			}
230 		}
231 		else if ( IsPathSeparator( *p ) )
232 		{
233 			if ( !LastCharEquals( Out, '/' ) && !LastCharEquals( Out, '\\' ) )
234 			{
235 				Out.push_back( DIR_SPLITTER );
236 			}
237 		}
238 		else
239 		{
240 			Out.push_back( *p );
241 		}
242 
243 		p++;
244 	}
245 
246 	Out.push_back( 0 );
247 
248 	// debug
249 	//	std::vector<char> U = unicode_to_utf8( Out.data() );
250 	//	const char* UTF = U.data();
251 
252 	return Out;
253 }
254 
ProcessCommand_CD(const unicode_t * cmd,PanelWin * Panel)255 bool FileExecutor::ProcessCommand_CD( const unicode_t* cmd, PanelWin* Panel )
256 {
257 	// make a mutable copy
258 	std::vector<unicode_t> copy = new_unicode_str( cmd );
259 
260 	unicode_t* p = copy.data();
261 
262 	//change dir
263 	m_History.Put( p );
264 	p += 2;
265 
266 	SkipSpaces( p );
267 
268 	std::vector<unicode_t> Path = ConvertCDArgToPath( p );
269 
270 	if ( Path.empty() || !Path[0] )
271 	{
272 #if defined(_WIN32)
273 		StartExecute( cmd, Panel->GetFS(), Panel->GetPath() );
274 #else
275 		OpenHomeDir( Panel );
276 #endif
277 		return true;
278 	}
279 
280 	p = Path.data();
281 
282 	unicode_t* lastNoSpace = nullptr;
283 
284 	for ( unicode_t* s = p; *s; s++ )
285 	{
286 		if ( *s != ' ' )
287 		{
288 			lastNoSpace = s;
289 		}
290 	}
291 
292 	if ( lastNoSpace )
293 	{
294 		lastNoSpace[1] = 0;
295 	} //erase last spaces
296 
297 	FSPath path = Panel->GetPath();
298 
299 	ccollect<unicode_t, 0x100> pre;
300 	int sc = 0;
301 
302 	while ( *p )
303 	{
304 		if ( sc )
305 		{
306 			if ( *p == sc )
307 			{
308 				sc = 0;  p++; continue;
309 			}
310 		}
311 		else if ( *p == '\'' || *p == '"' )
312 		{
313 			sc = *p;
314 			p++;
315 			continue;
316 		}
317 
318 #ifndef _WIN32
319 
320 		if ( *p == '\\' && !sc )
321 		{
322 			p++;
323 		}
324 
325 #endif
326 
327 		if ( !p )
328 		{
329 			break;
330 		}
331 
332 		pre.append( *p );
333 		p++;
334 	}
335 
336 	pre.append( 0 );
337 	p = pre.ptr();
338 
339 	const std::vector<clPtr<FS>> checkFS =
340 	{
341 		Panel->GetFSPtr(),
342 		m_NCWin->GetOtherPanel( Panel )->GetFSPtr()
343 	};
344 
345 	clPtr<FS> fs = ParzeURI( p, path, checkFS );
346 
347 	if ( fs.IsNull() )
348 	{
349 		char buf[4096];
350 		FSString name = p;
351 		Lsnprintf( buf, sizeof( buf ), _LT( "can`t change directory to:%s\n" ), name.GetUtf8() );
352 		NCMessageBox( m_NCWin, "CD", buf, true );
353 	}
354 	else
355 	{
356 		Panel->LoadPath( fs, path, 0, 0, PanelWin::SET );
357 	}
358 
359 	return true;
360 }
361 
ProcessCommand_CLS(const unicode_t * cmd)362 bool FileExecutor::ProcessCommand_CLS( const unicode_t* cmd )
363 {
364 	m_Terminal.TerminalReset( true );
365 	return true;
366 }
367 
ProcessBuiltInCommands(const unicode_t * cmd,PanelWin * Panel)368 bool FileExecutor::ProcessBuiltInCommands( const unicode_t* cmd, PanelWin* Panel )
369 {
370 #if defined( _WIN32 ) || defined( __APPLE__ )
371 	bool CaseSensitive = false;
372 #else
373 	bool CaseSensitive = true;
374 #endif
375 
376 	if ( IsEqual_Unicode_CStr( cmd, "cls", CaseSensitive ) )
377 	{
378 		ProcessCommand_CLS( cmd );
379 		return true;
380 	}
381 
382 	if ( IsCommand_CD( cmd ) )
383 	{
384 		ProcessCommand_CD( cmd, Panel );
385 		return true;
386 	}
387 
388 	return false;
389 }
390 
StartCommand(const std::vector<unicode_t> & CommandString,PanelWin * Panel,bool ForceNoTerminal,bool ReplaceSpecialChars)391 bool FileExecutor::StartCommand( const std::vector<unicode_t>& CommandString, PanelWin* Panel, bool ForceNoTerminal, bool ReplaceSpecialChars )
392 {
393 	std::vector<unicode_t> Command = ReplaceSpecialChars ? MakeCommand( CommandString, Panel->GetCurrentFileName() ) : CommandString;
394 
395 	const unicode_t* p = Command.data();
396 
397 	SkipSpaces( p );
398 
399 	//	printf( "StartCommand %s, %i\n", (const char*)p, (int)ForceNoTerminal );
400 
401 	if ( !*p )
402 	{
403 		return false;
404 	}
405 
406 	if ( *p )
407 	{
408 		m_History.ResetToLast();
409 
410 		if ( !ProcessBuiltInCommands( p, Panel ) )
411 		{
412 			bool NoTerminal = (p[0] == '&' || ForceNoTerminal);
413 
414 			if ( NoTerminal )
415 			{
416 				m_History.Put( p );
417 
418 				if ( p[0] == '&' )
419 				{
420 					p++;
421 				}
422 			}
423 
424 			FS* fs = Panel->GetFS();
425 
426 			if ( fs && fs->Type() == FS::SYSTEM )
427 			{
428 				StartExecute( Command.data(), fs, Panel->GetPath(), NoTerminal );
429 			}
430 			else
431 			{
432 				NCMessageBox( m_NCWin, _LT( "Execute" ), _LT( "Can`t execute command in non system fs" ), true );
433 			}
434 		}
435 	}
436 
437 	return true;
438 }
439 
ApplyCommand(const std::vector<unicode_t> & cmd,PanelWin * Panel)440 void FileExecutor::ApplyCommand( const std::vector<unicode_t>& cmd, PanelWin* Panel )
441 {
442 	clPtr<FSList> list = Panel->GetSelectedList();
443 
444 	if ( !cmd.data() || !list.ptr() || list->Count() <= 0 )
445 	{
446 		return;
447 	}
448 
449 	std::vector<FSNode*> nodes = list->GetArray();
450 
451 	m_NCWin->SetMode( NCWin::TERMINAL );
452 
453 	for ( auto i = nodes.begin(); i != nodes.end(); i++ )
454 	{
455 		FSNode* Node = *i;
456 
457 		const unicode_t* Name = Node->GetUnicodeName();
458 
459 		std::vector<unicode_t> Command = MakeCommand( cmd, Name );
460 
461 		StartExecute( Command.data(), Panel->GetFS(), Panel->GetPath() );
462 	}
463 }
464 
FindFileAssociation(const unicode_t * FileName) const465 const clNCFileAssociation* FileExecutor::FindFileAssociation( const unicode_t* FileName ) const
466 {
467 	const auto& Assoc = g_Env.GetFileAssociations();
468 
469 	for ( const auto& i : Assoc )
470 	{
471 		std::vector<unicode_t> Mask = i.GetMask();
472 
473 		clMultimaskSplitter Splitter( Mask );
474 
475 		if ( Splitter.CheckAndFetchAllMasks( FileName ) )
476 		{
477 			return &i;
478 		}
479 	}
480 
481 	return nullptr;
482 }
483 
StartFileAssociation(PanelWin * panel,eFileAssociation Mode)484 bool FileExecutor::StartFileAssociation( PanelWin* panel, eFileAssociation Mode )
485 {
486 	const unicode_t* FileName = panel->GetCurrentFileName();
487 
488 	const clNCFileAssociation* Assoc = FindFileAssociation( FileName );
489 
490 	if ( !Assoc )
491 	{
492 		return false;
493 	}
494 
495 	std::vector<unicode_t> Cmd = MakeCommand( Assoc->Get( Mode ), FileName );
496 
497 	if ( Cmd.data() && *Cmd.data() )
498 	{
499 		StartExecute( Cmd.data(), panel->GetFS(), panel->GetPath(), !Assoc->GetHasTerminal() );
500 		return true;
501 	}
502 
503 	return false;
504 }
505 
ExecuteFileByEnter(PanelWin * Panel,bool Shift)506 void FileExecutor::ExecuteFileByEnter( PanelWin* Panel, bool Shift )
507 {
508 	FSNode* p = Panel->GetCurrent();
509 
510 	bool cmdChecked = false;
511 	std::vector<unicode_t> cmd;
512 	bool terminal = true;
513 	const unicode_t* pAppName = 0;
514 	clPtr<FS> LocalFs = Panel->GetFSPtr();
515 	FSPath LocalPath = Panel->GetPath();
516 
517 	FSString Uri;
518 
519 	if ( !(LocalFs->Flags() & FS::HAVE_SEEK) )
520 	{
521 		// append file name to the path
522 		LocalPath.Push( CS_UTF8, p->name.GetUtf8() );
523 
524 		// try to load virtual system file to local temp file
525 		if ( !LoadToTempFile( m_NCWin, &LocalFs, &LocalPath ) )
526 		{
527 			return;
528 		}
529 
530 		// get full URI to the loaded temp local file
531 		Uri = LocalFs->Uri( LocalPath );
532 
533 		// remove file name from the dir path
534 		LocalPath.Pop();
535 	}
536 	else
537 	{
538 		Uri = Panel->UriOfCurrent();
539 	}
540 
541 	if ( Shift )
542 	{
543 		ExecuteDefaultApplication( Uri.GetUnicode() );
544 		return;
545 	}
546 
547 	if ( StartFileAssociation( Panel, eFileAssociation_Execute ) )
548 	{
549 		return;
550 	}
551 
552 	if ( g_WcmConfig.systemAskOpenExec )
553 	{
554 		cmd = GetOpenCommand( Uri.GetUnicode(), &terminal, &pAppName );
555 		cmdChecked = true;
556 	}
557 
558 	if ( p->IsExe() )
559 	{
560 #ifndef _WIN32
561 
562 		if ( g_WcmConfig.systemAskOpenExec && cmd.data() )
563 		{
564 			ButtonDataNode bListOpenExec[] = { { "&Open", CMD_OPEN_FILE }, { "&Execute", CMD_EXEC_FILE }, { "&Cancel", CMD_CANCEL }, { 0, 0 } };
565 
566 			static unicode_t emptyStr[] = { 0 };
567 
568 			if ( !pAppName )
569 			{
570 				pAppName = emptyStr;
571 			}
572 
573 			int ret = NCMessageBox( m_NCWin, "Open",
574 				carray_cat<char>( "Executable file: ", p->name.GetUtf8(), "\ncan be opened by: ", unicode_to_utf8( pAppName ).data(), "\nExecute or Open?" ).data(),
575 				false, bListOpenExec );
576 
577 			if ( ret == CMD_CANCEL )
578 			{
579 				return;
580 			}
581 
582 			if ( ret == CMD_OPEN_FILE )
583 			{
584 				StartExecute( cmd.data(), LocalFs.ptr(), LocalPath, !terminal );
585 				return;
586 			}
587 		}
588 
589 #endif
590 		ExecuteFile( Panel );
591 		return;
592 	}
593 
594 	if ( !cmdChecked )
595 	{
596 		cmd = GetOpenCommand( Uri.GetUnicode(), &terminal, 0 );
597 	}
598 
599 	if ( cmd.data() )
600 	{
601 		StartExecute( cmd.data(), LocalFs.ptr(), LocalPath, !terminal );
602 	}
603 }
604 
ExecuteFile(PanelWin * panel)605 void FileExecutor::ExecuteFile( PanelWin* panel )
606 {
607 	FSNode* p = panel->GetCurrent();
608 
609 	if ( !p || p->IsDir() || !p->IsExe() )
610 	{
611 		return;
612 	}
613 
614 	FS* fs = panel->GetFS();
615 
616 	if ( !fs || fs->Type() != FS::SYSTEM )
617 	{
618 		NCMessageBox( m_NCWin, _LT( "Run" ), _LT( "Can`t execute file in not system fs" ), true );
619 		return;
620 	}
621 
622 #ifdef _WIN32
623 
624 	static unicode_t w[2] = { '"', 0 };
625 	StartExecute( carray_cat<unicode_t>( w, panel->UriOfCurrent().GetUnicode(), w ).data(), fs, panel->GetPath() );
626 
627 #else
628 
629 	const unicode_t*   fName = p->GetUnicodeName();
630 	int len = unicode_strlen( fName );
631 	std::vector<unicode_t> cmd( 2 + len + 1 );
632 	cmd[0] = '.';
633 	cmd[1] = '/';
634 	memcpy( cmd.data() + 2, fName, len * sizeof( unicode_t ) );
635 	cmd[2 + len] = 0;
636 	StartExecute( cmd.data(), fs, panel->GetPath() );
637 
638 #endif
639 }
640 
StartExecute(const unicode_t * cmd,FS * fs,FSPath & path,bool NoTerminal)641 void FileExecutor::StartExecute( const unicode_t* cmd, FS* fs, FSPath& path, bool NoTerminal )
642 {
643 	SkipSpaces( cmd );
644 
645 	if ( DoStartExecute( m_EditPref.Get(), cmd, fs, path ) )
646 	{
647 		m_History.Put( cmd );
648 		m_NCWin->SetMode( NCWin::TERMINAL );
649 	}
650 
651 	ReturnToDefaultSysDir();
652 }
653 
DoStartExecute(const unicode_t * pref,const unicode_t * cmd,FS * fs,FSPath & path,bool NoTerminal)654 bool FileExecutor::DoStartExecute( const unicode_t* pref, const unicode_t* cmd, FS* fs, FSPath& path, bool NoTerminal )
655 {
656 #ifdef _WIN32
657 
658 	if ( !m_Terminal.Execute( m_NCWin, TERMINAL_THREAD_ID, cmd, 0, fs->Uri( path ).GetUnicode() ) )
659 	{
660 		return false;
661 	}
662 
663 #else
664 
665 	static unicode_t empty[] = {0};
666 	static unicode_t newLine[] = { '\n', 0 };
667 
668 	if ( !pref )
669 	{
670 		pref = empty;
671 	}
672 
673 	if ( !*cmd )
674 	{
675 		return false;
676 	}
677 
678 	m_Terminal.TerminalReset();
679 
680 	if ( NoTerminal )
681 	{
682 		unsigned fg = 0xB;
683 		unsigned bg = 0;
684 
685 		m_Terminal.TerminalPrint( newLine, fg, bg );
686 		m_Terminal.TerminalPrint( pref, fg, bg );
687 		m_Terminal.TerminalPrint( cmd, fg, bg );
688 		m_Terminal.TerminalPrint( newLine, fg, bg );
689 
690 		char* dir = 0;
691 
692 		if ( fs && fs->Type() == FS::SYSTEM )
693 		{
694 			dir = (char*) path.GetString( sys_charset_id );
695 		}
696 
697 		FSString s = cmd;
698 		sys_char_t* SysCmd = (sys_char_t*) s.Get( sys_charset_id );
699 
700 		pid_t pid = fork();
701 		if ( pid < 0 )
702 		{
703 			return false;
704 		}
705 
706 		if ( pid )
707 		{
708 			waitpid( pid, 0, 0 );
709 		}
710 		else
711 		{
712 			if ( !fork() )
713 			{
714 				//printf("exec: %s\n", SysCmd);
715 				signal( SIGINT, SIG_DFL );
716 				static char shell[] = "/bin/sh";
717 				const char* params[] = { shell, "-c", SysCmd, NULL };
718 
719 				if ( dir )
720 				{
721 					chdir( dir );
722 				}
723 
724 				execv( shell, (char**) params );
725 				exit( 1 );
726 			}
727 
728 			exit( 0 );
729 		}
730 	}
731 	else
732 	{
733 		unsigned fg_pref = 0xB;
734 		unsigned fg_cmd = 0xF;
735 		unsigned bg = 0;
736 
737 		m_Terminal.TerminalPrint( newLine, fg_pref, bg );
738 		m_Terminal.TerminalPrint( pref, fg_pref, bg );
739 		m_Terminal.TerminalPrint( cmd, fg_cmd, bg );
740 		m_Terminal.TerminalPrint( newLine, fg_cmd, bg );
741 
742 		int l = unicode_strlen( cmd );
743 		int i;
744 
745 		if ( l >= 64 )
746 		{
747 			for ( i = 0; i < 64 - 1; i++ )
748 			{
749 				m_ExecSN[i] = cmd[i];
750 			}
751 
752 			m_ExecSN[60] = '.';
753 			m_ExecSN[61] = '.';
754 			m_ExecSN[62] = '.';
755 			m_ExecSN[63] = 0;
756 		}
757 		else
758 		{
759 			for ( i = 0; i < l; i++ )
760 			{
761 				m_ExecSN[i] = cmd[i];
762 			}
763 
764 			m_ExecSN[l] = 0;
765 		}
766 
767 		m_Terminal.Execute( m_NCWin, TERMINAL_THREAD_ID, cmd, (sys_char_t*) path.GetString( sys_charset_id ) );
768 	}
769 
770 #endif
771 
772 	return true;
773 }
774 
StopExecute()775 void FileExecutor::StopExecute()
776 {
777 #ifdef _WIN32
778 
779 	if ( NCMessageBox( m_NCWin, _LT( "Stop" ), _LT( "Drop current console?" ), false, bListOkCancel ) == CMD_OK )
780 	{
781 		m_Terminal.DropConsole();
782 	}
783 
784 #else
785 
786 	if ( m_ExecId > 0 )
787 	{
788 		int ret = KillCmdDialog( m_NCWin, m_ExecSN );
789 
790 		if ( m_ExecId > 0 )
791 		{
792 			if ( ret == CMD_KILL_9 )
793 			{
794 				kill( m_ExecId, SIGKILL );
795 			}
796 			else if ( ret == CMD_KILL )
797 			{
798 				kill( m_ExecId, SIGTERM );
799 			}
800 		}
801 	}
802 
803 #endif
804 }
805 
ThreadSignal(int id,int data)806 void FileExecutor::ThreadSignal( int id, int data )
807 {
808 	if ( id == TERMINAL_THREAD_ID )
809 	{
810 		m_ExecId = data;
811 	}
812 }
813 
ThreadStopped(int id,void * data)814 void FileExecutor::ThreadStopped( int id, void* data )
815 {
816 	if ( id == TERMINAL_THREAD_ID )
817 	{
818 		m_ExecId = -1;
819 		m_ExecSN[0] = 0;
820 	}
821 }
822