1    | /*****
2    |  ** ** Module Header ******************************************************* **
3    |  ** 									     **
4    |  **   Modules Revision 3.0						     **
5    |  **   Providing a flexible user environment				     **
6    |  ** 									     **
7    |  **   File:		cmdMisc.c					     **
8    |  **   First Edition:	1991/10/23					     **
9    |  ** 									     **
10   |  **   Authors:	John Furlan, jlf@behere.com				     **
11   |  **		Jens Hamisch, jens@Strawberry.COM			     **
12   |  ** 									     **
13   |  **   Description:	The Tcl 'system' command			     **
14   |  ** 									     **
15   |  **   Exports:		cmdSystem					     **
16   |  ** 									     **
17   |  **   Notes:		The Following code was written by Don Libes, NIST    **
18   |  **			It was taken from his tool, 'expect' ...	     **
19   |  **  			I have edited parts of it...			     **
20   |  ** 									     **
21   |  ** ************************************************************************ **
22   |  ****/
23   | 
24   | /** ** Copyright *********************************************************** **
25   |  ** 									     **
26   |  ** Copyright 1991-1994 by John L. Furlan.                      	     **
27   |  ** see LICENSE.GPL, which must be provided, for details		     **
28   |  ** 									     ** 
29   |  ** ************************************************************************ **/
30   | 
31   | static char Id[] = "@(#)$Id: cmdMisc.c.src.html,v 1.6 2006/01/18 05:35:11 rkowen Exp $";
32   | static void *UseId[] = { &UseId, Id };
33   | 
34   | /** ************************************************************************ **/
35   | /** 				      HEADERS				     **/
36   | /** ************************************************************************ **/
37   | 
38   | #include "modules_def.h"
39   | 
40   | /** ************************************************************************ **/
41   | /** 				  LOCAL DATATYPES			     **/
42   | /** ************************************************************************ **/
43   | 
44   | /** not applicable **/
45   | 
46   | /** ************************************************************************ **/
47   | /** 				     CONSTANTS				     **/
48   | /** ************************************************************************ **/
49   | 
50   | #define MAX_ARGLIST 10240
51   | 
52   | /** ************************************************************************ **/
53   | /**				      MACROS				     **/
54   | /** ************************************************************************ **/
55   | 
56   | /** not applicable **/
57   | 
58   | /** ************************************************************************ **/
59   | /** 				    LOCAL DATA				     **/
60   | /** ************************************************************************ **/
61   | 
62   | static	char	module_name[] = "cmdMisc.c";	/** File name of this module **/
63   | #if WITH_DEBUGGING_CALLBACK
64   | static	char	_proc_cmdSystem[] = "cmdSystem";
65   | #endif
66   | 
67   | /** ************************************************************************ **/
68   | /**				    PROTOTYPES				     **/
69   | /** ************************************************************************ **/
70   | 
71   | /** not applicable **/
72   | 
73   | 
74   | /*++++
75   |  ** ** Function-Header ***************************************************** **
76   |  ** 									     **
77   |  **   Function:		cmdSystem					     **
78   |  ** 									     **
79   |  **   Description:	Callback function for 'system'			     **
80   |  ** 									     **
81   |  **   First Edition:	1991/10/23					     **
82   |  ** 									     **
83   |  **   Parameters:	ClientData	 client_data			     **
84   |  **			Tcl_Interp	*interp		According Tcl interp.**
85   |  **			int		 argc		Number of arguments  **
86   |  **			char		*argv[]		Argument array	     **
87   |  ** 									     **
88   |  **   Result:		int	TCL_OK		Successfull completion	     **
89   |  **				TCL_ERROR	Any error		     **
90   |  ** 									     **
91   |  **   Attached Globals:	g_flags		These are set up accordingly before  **
92   |  **					this function is called in order to  **
93   |  **					control everything		     **
94   |  ** 									     **
95   |  ** ************************************************************************ **
96   |  ++++*/
97   | 
98   | int	cmdSystem(	ClientData	 clientData, 
99   | 	  		Tcl_Interp	*interp, 
100  | 	  		int		 argc, 
101  | 	  		CONST84 char	*argv[])
102  | {
103  |     int		 i;
104  |     int		 saved_stdout;
105  |     char	 buf[ MAX_ARGLIST];
106  |     char	*bufp = buf;
107  |     int		 total_len = 0,
108  |     		 arg_len;
109  | 
110  | #if WITH_DEBUGGING_CALLBACK
111  |     ErrorLogger( NO_ERR_START, LOC, _proc_cmdSystem, NULL);
112  | #endif
113  | 
114  |     /**
115  |      **  Whatis mode
116  |      **/
117  | 
118  |     if( g_flags & (M_WHATIS | M_HELP))
119  |         return( TCL_OK);		/** -------- EXIT (SUCCESS) -------> **/
120  | 
121  |     /**
122  |      **  Display mode?
123  |      **/
124  | 
125  |     if( g_flags & M_DISPLAY) {
126  | 	fprintf( stderr, "%s\t\t ", argv[ 0]);
127  | 	for( i=1; i<argc; i++)
128  | 	    fprintf( stderr, "%s ", argv[ i]);
129  | 	fprintf( stderr, "\n");
130  |         return( TCL_OK);		/** ------- EXIT PROCEDURE -------> **/
131  |     }
132  | 
133  |     /**
134  |      **  Prepare a buffer to hold the complete 'system' call
135  |      **  Watch over the commands complete length while copying ...
136  |      **/
137  | 
138  |     for( i = 1; i<argc; i++) {
139  | 
140  |         total_len += (1 + (arg_len = strlen(argv[i])));
141  |         if( total_len > MAX_ARGLIST) {
142  | 	    if( OK != ErrorLogger( ERR_ARGSTOLONG, LOC, argv[0], (sprintf( buf,
143  | 		"%d", total_len), buf), NULL))
144  | 		return( TCL_ERROR);	/** -------- EXIT (FAILURE) -------> **/
145  |         }
146  | 
147  | 	/**
148  |  	 **  Copy the argument ov the buffer and put a space at its end
149  | 	 **/
150  | 
151  |         memcpy( bufp, argv[i], arg_len);
152  |         bufp += arg_len;
153  |         memcpy( bufp, " ", 1);
154  |         bufp += 1;
155  |     }
156  | 
157  |     /**
158  |      **  For Modules, stdout must be directed to stderr so it
159  |      **  isn't parsed by the evaluating shell.  We also must save it here so it
160  |      **  can be restored after this command has been executed.
161  |      **/
162  | 
163  |     saved_stdout = TieStdout();
164  | 
165  |     *(bufp-1) = '\0';
166  |     i = system( buf);
167  | 
168  |     /**
169  |      **  Following the style of Tcl_ExecCmd, we can just return the
170  |      **  raw result (appropriately shifted and masked) to Tcl
171  |      **/
172  | 
173  |     sprintf( buf, "%d", (0xff & (i >> 8)));
174  |     Tcl_SetResult( interp, buf, TCL_VOLATILE);
175  | 
176  |     /*
177  |      *  Restore stdout.
178  |      */
179  | 
180  |     UnTieStdout( saved_stdout);
181  |     
182  | #if WITH_DEBUGGING_CALLBACK
183  |     ErrorLogger( NO_ERR_END, LOC, _proc_cmdSystem, NULL);
184  | #endif
185  | 
186  |     return( TCL_OK);
187  | 
188  | } /** End of 'cmdSystem' **/