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' **/