1 | /****************************************************************************** |
---|
2 | * SAGE - Scalable Adaptive Graphics Environment |
---|
3 | * |
---|
4 | * Module: fsConsole.cpp - a UI console to control the Free Space Manager |
---|
5 | * Author : Luc Renambot, Byungil Jeong |
---|
6 | * |
---|
7 | * Copyright (C) 2004 Electronic Visualization Laboratory, |
---|
8 | * University of Illinois at Chicago |
---|
9 | * |
---|
10 | * All rights reserved. |
---|
11 | * |
---|
12 | * Redistribution and use in source and binary forms, with or without |
---|
13 | * modification, are permitted provided that the following conditions are met: |
---|
14 | * |
---|
15 | * * Redistributions of source code must retain the above copyright |
---|
16 | * notice, this list of conditions and the following disclaimer. |
---|
17 | * * Redistributions in binary form must reproduce the above |
---|
18 | * copyright notice, this list of conditions and the following disclaimer |
---|
19 | * in the documentation and/or other materials provided with the distribution. |
---|
20 | * * Neither the name of the University of Illinois at Chicago nor |
---|
21 | * the names of its contributors may be used to endorse or promote |
---|
22 | * products derived from this software without specific prior written permission. |
---|
23 | * |
---|
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
---|
25 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
---|
26 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
---|
27 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
---|
28 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
---|
29 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
---|
30 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
---|
31 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
---|
32 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
---|
33 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
---|
34 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
---|
35 | * |
---|
36 | * Direct questions, comments etc about SAGE to sage_users@listserv.uic.edu or |
---|
37 | * http://www.evl.uic.edu/cavern/forum/ |
---|
38 | * |
---|
39 | *****************************************************************************/ |
---|
40 | |
---|
41 | #include "suil.h" |
---|
42 | #include "misc.h" |
---|
43 | #include <pthread.h> |
---|
44 | |
---|
45 | #include <stdio.h> |
---|
46 | #include <stdlib.h> |
---|
47 | #include <string.h> |
---|
48 | |
---|
49 | #include <readline/readline.h> |
---|
50 | #include <readline/history.h> |
---|
51 | |
---|
52 | #if defined(SAGE_NETLOG) |
---|
53 | #include "nl_log.h" |
---|
54 | #endif |
---|
55 | |
---|
56 | // SAGE object |
---|
57 | suil uiLib; |
---|
58 | |
---|
59 | // Application list |
---|
60 | typedef struct _application_t |
---|
61 | { |
---|
62 | char *name; |
---|
63 | int id; |
---|
64 | FILE *log; |
---|
65 | } application_t; |
---|
66 | |
---|
67 | application_t *Applications[64]; |
---|
68 | FILE *playback; |
---|
69 | |
---|
70 | // When non-zero, this means the user is done using this program. |
---|
71 | int done; |
---|
72 | bool zeroPerf; |
---|
73 | char execArg[256]; |
---|
74 | int noRecv, noSend, dispX, dispY, rendX, wholeX, intval = 0; |
---|
75 | |
---|
76 | // A static variable for holding the line. |
---|
77 | static char *line_read = (char *)NULL; |
---|
78 | static char current_command[256]; |
---|
79 | static char exec_arg[256]; |
---|
80 | |
---|
81 | // The names of functions that actually do the work |
---|
82 | int com_help (char *arg); |
---|
83 | int com_exit (char *arg); |
---|
84 | int com_exec (char *arg); |
---|
85 | int com_move (char *arg); |
---|
86 | int com_resize (char *arg); |
---|
87 | int com_bg (char *arg); |
---|
88 | int com_depth (char *arg); |
---|
89 | int com_perf (char *arg); |
---|
90 | int com_zeroperf (char *arg); |
---|
91 | int com_stopperf (char *arg); |
---|
92 | int com_kill (char *arg); |
---|
93 | int com_shutdown (char *arg); |
---|
94 | int com_admin (char *arg); |
---|
95 | int com_rate (char *arg); |
---|
96 | int com_intval (char *arg); |
---|
97 | int com_ptr (char *arg); |
---|
98 | int com_share (char *arg); |
---|
99 | |
---|
100 | |
---|
101 | |
---|
102 | // A structure which contains information on the commands |
---|
103 | // this program can understand. |
---|
104 | |
---|
105 | typedef struct { |
---|
106 | const char *name; // User printable name of the function. |
---|
107 | rl_icpfunc_t *func; // Function to call to do the job. |
---|
108 | const char *doc; // Documentation for this function. |
---|
109 | } COMMAND; |
---|
110 | |
---|
111 | //### |
---|
112 | COMMAND commands[] = { |
---|
113 | |
---|
114 | { "exec", com_exec, |
---|
115 | "Execute an application: <exec app_name config_num (init_x init_y)>" }, |
---|
116 | { "move", com_move, |
---|
117 | "Move the window of an application: <move app_id dx dy>" }, |
---|
118 | { "resize", com_resize, |
---|
119 | "Resize the window of an application: <resize app_id left right bottom top>" }, |
---|
120 | { "bg", com_bg, |
---|
121 | "Change background color: <bg red green blue>" }, |
---|
122 | { "depth", com_depth, |
---|
123 | "Change z-order of the windows: <depth #_of_change app_id1 zVal1 ...>" }, |
---|
124 | { "perf", com_perf, |
---|
125 | "Request performance information: <perf app_id report_period(sec)>" }, |
---|
126 | { "stopperf", com_stopperf, |
---|
127 | "Stop performance information report: <stopperf app_id>" }, |
---|
128 | { "zeroperf", com_zeroperf, |
---|
129 | "set performance numbers zero: <zeroperf>" }, |
---|
130 | { "kill", com_kill, |
---|
131 | "Kill an application: <kill app_id>" }, |
---|
132 | { "shutdown", com_shutdown, |
---|
133 | "Shutdown SAGE: <shutdown>" }, |
---|
134 | { "admin", com_admin, |
---|
135 | "Get administrative information and status: <admin>" }, |
---|
136 | |
---|
137 | { "ptr", com_ptr, "Move the pointer: <move dx dy>" }, |
---|
138 | |
---|
139 | { "help", com_help, "Display this text: <help>" }, |
---|
140 | { "exit", com_exit, "Quit the console: <exit>" }, |
---|
141 | { "quit", com_exit, "Quit the console: <quit>" }, |
---|
142 | { "rate", com_rate, "change the frame rate of apps: <rate app_id frame_rate>" }, |
---|
143 | { "intval", com_intval, "change the pause interval of the udp stream : <intval app_id interval>" }, |
---|
144 | { "share", com_share, "sharing app to another fsManager : <share app_id fs_IP fs_port>" }, |
---|
145 | { "?", com_help, "Synonym for help: <?>" }, |
---|
146 | |
---|
147 | { (char *)NULL, (rl_icpfunc_t *)NULL, (char *)NULL } |
---|
148 | }; |
---|
149 | //### |
---|
150 | |
---|
151 | |
---|
152 | // Functions locally defined |
---|
153 | void* readThread(void *args); |
---|
154 | char* dupstr (char *s); |
---|
155 | char* rl_gets (const char *prompt); |
---|
156 | char* command_generator (const char * text, int state); |
---|
157 | char** fileman_completion (const char * text, int start, int end); |
---|
158 | char* stripwhite (char *thestring); |
---|
159 | int execute_line (char *line); |
---|
160 | |
---|
161 | COMMAND* find_command (char *name); |
---|
162 | |
---|
163 | //////////////////////////////////////////////////////////////////////////////// |
---|
164 | |
---|
165 | |
---|
166 | void* readThread(void *args) |
---|
167 | { |
---|
168 | suil *uiLib = (suil *)args; |
---|
169 | int timestep = 1; |
---|
170 | |
---|
171 | while (1) |
---|
172 | { |
---|
173 | sageMessage msg; |
---|
174 | |
---|
175 | msg.init(READ_BUF_SIZE); |
---|
176 | uiLib->rcvMessageBlk(msg); |
---|
177 | |
---|
178 | if (msg.getCode() == APP_INFO_RETURN) |
---|
179 | { |
---|
180 | char appname[256], cmd[256]; |
---|
181 | int ret; |
---|
182 | int appID, left, right, bottom, top, sailID, zValue; |
---|
183 | |
---|
184 | ret = sscanf((char*)msg.getData(), "%s %d %d %d %d %d %d %d", |
---|
185 | appname, &appID, &left, &right, &bottom, &top, &sailID, &zValue); |
---|
186 | |
---|
187 | if (ret != 8) |
---|
188 | fprintf(stderr, "Something wrong, got only %d fields\n", ret); |
---|
189 | else |
---|
190 | { |
---|
191 | if (Applications[appID] == NULL) |
---|
192 | { |
---|
193 | Applications[appID] = (application_t*)malloc(sizeof(application_t)); |
---|
194 | Applications[appID]->id = appID; |
---|
195 | Applications[appID]->name = strdup(appname); |
---|
196 | |
---|
197 | // Get local time |
---|
198 | time_t local = time(NULL); |
---|
199 | struct tm *current = localtime( & local ); |
---|
200 | |
---|
201 | // Create a file for each application |
---|
202 | char fn[256]; |
---|
203 | memset(fn, 0, 256); |
---|
204 | |
---|
205 | char *sageDir = getenv("SAGE_DIRECTORY"); |
---|
206 | if (!sageDir) { |
---|
207 | sage::printLog("fsConsole: cannot find the environment variable SAGE_DIRECTORY"); |
---|
208 | return NULL; |
---|
209 | } |
---|
210 | |
---|
211 | data_path path; |
---|
212 | std::string found = path.get_file("log"); |
---|
213 | if (found.empty()) { |
---|
214 | sage::printLog("fsConsole: cannot find the directory [%s]", "log"); |
---|
215 | return NULL; |
---|
216 | } |
---|
217 | const char *logPath = found.c_str(); |
---|
218 | |
---|
219 | /* |
---|
220 | if (noRecv == 0) { |
---|
221 | sprintf(fn, "log/%s-%d-%d-%d-%d-%d-%d.log", // year-month-day hour-minute-second |
---|
222 | Applications[appID]->name, |
---|
223 | current->tm_year, current->tm_mon, current->tm_mday, |
---|
224 | current->tm_hour, current->tm_min, current->tm_sec); |
---|
225 | } |
---|
226 | else { |
---|
227 | sprintf(fn, "log/%s-r%d-s%d-%dx%d-i%d.log", Applications[appID]->name, |
---|
228 | noRecv, noSend, dispX, dispY, intval); |
---|
229 | } |
---|
230 | */ |
---|
231 | |
---|
232 | sprintf(fn, "%s/%s-%s.log", logPath, Applications[appID]->name, execArg); |
---|
233 | sage::printLog("fsConsole: opening [%s] log file", fn); |
---|
234 | Applications[appID]->log = fopen(fn, "w+"); |
---|
235 | |
---|
236 | if (noRecv > 0) { |
---|
237 | fprintf(Applications[appID]->log, |
---|
238 | "%s rcv %d send %d dispRes %d %d rendRes %d %d whole %d %d int %d\n", |
---|
239 | Applications[appID]->name, |
---|
240 | noRecv, noSend, dispX, dispY, rendX, dispY, wholeX, dispY, intval); |
---|
241 | } |
---|
242 | |
---|
243 | #if defined(SAGE_NETLOG) |
---|
244 | memset(fn, 0, 256); |
---|
245 | sprintf(fn, "log/%s-%d-%d-%d-%d-%d-%d.nlg", // year-month-day hour-minute-second |
---|
246 | Applications[appID]->name, |
---|
247 | current->tm_year, current->tm_mon, current->tm_mday, |
---|
248 | current->tm_hour, current->tm_min, current->tm_sec); |
---|
249 | NL_logger_module( Applications[appID]->name, fn, NL_LVL_INFO, NL_TYPE_APP, "" ); |
---|
250 | #endif |
---|
251 | |
---|
252 | memset(cmd, 0, 256); |
---|
253 | sprintf(cmd, "%d", appID); |
---|
254 | uiLib->sendMessage(STOP_PERF_INFO, cmd); |
---|
255 | |
---|
256 | memset(cmd, 0, 256); |
---|
257 | sprintf(cmd, "%d %d", appID, 1); // every second |
---|
258 | uiLib->sendMessage(PERF_INFO_REQ, cmd); |
---|
259 | } |
---|
260 | } |
---|
261 | } |
---|
262 | |
---|
263 | else if (msg.getCode() == UI_APP_SHUTDOWN) |
---|
264 | { |
---|
265 | int ret; |
---|
266 | int appID; |
---|
267 | |
---|
268 | ret = sscanf((char*)msg.getData(), "%d", &appID); |
---|
269 | if (ret != 1) |
---|
270 | fprintf(stderr, "Something wrong, got only %d fields\n", ret); |
---|
271 | else |
---|
272 | { |
---|
273 | if (Applications[appID]->log) |
---|
274 | { |
---|
275 | fprintf(stderr, "Closing log file for application [%s]\n", Applications[appID]->name); |
---|
276 | fclose(Applications[appID]->log); |
---|
277 | } |
---|
278 | } |
---|
279 | |
---|
280 | } |
---|
281 | |
---|
282 | else if (msg.getCode() == UI_PERF_INFO) |
---|
283 | { |
---|
284 | char appname[256], cmd[256]; |
---|
285 | int ret; |
---|
286 | int appID, dispNodes, renderNodes, numStreamR; |
---|
287 | float dispBandWidth, dispFrameRate, renderBandWidth, renderFrameRate, packetLoss; |
---|
288 | |
---|
289 | ret = sscanf((char*)msg.getData(), "%d\nDisplay %f %f %f %d\nRendering %f %f %d", |
---|
290 | &appID, |
---|
291 | &dispBandWidth, &dispFrameRate, &packetLoss, &dispNodes, |
---|
292 | &renderBandWidth, &renderFrameRate, &renderNodes); |
---|
293 | |
---|
294 | if (ret != 8) |
---|
295 | fprintf(stderr, "Something wrong, got only %d fields\n", ret); |
---|
296 | else |
---|
297 | { |
---|
298 | if (zeroPerf) { |
---|
299 | fprintf(Applications[appID]->log, "%d 0.0 0.0 0.0 0.0 %d %d %s\n", timestep, dispNodes, renderNodes, exec_arg); |
---|
300 | } |
---|
301 | else { |
---|
302 | fprintf(Applications[appID]->log, "%d %f %f %f %f %f %d %d %s\n", |
---|
303 | timestep, dispBandWidth, dispFrameRate, packetLoss, renderBandWidth, |
---|
304 | renderFrameRate, dispNodes, renderNodes, exec_arg); |
---|
305 | } |
---|
306 | |
---|
307 | fflush(Applications[appID]->log); |
---|
308 | |
---|
309 | #if defined(SAGE_NETLOG) |
---|
310 | NL_flush = 1; |
---|
311 | NL_write( Applications[appID]->name, NL_LVL_INFO, "display", "bandwidth=d framerate=d", dispBandWidth, dispFrameRate); |
---|
312 | NL_write( Applications[appID]->name, NL_LVL_INFO, "render", "bandwidth=d framerate=d", renderBandWidth, renderFrameRate); |
---|
313 | #endif |
---|
314 | |
---|
315 | timestep += 1; |
---|
316 | } |
---|
317 | } |
---|
318 | |
---|
319 | else |
---|
320 | { |
---|
321 | fprintf(stdout, "\n\tMessage: %d\n\t[%s]\n", msg.getCode(), (char *)msg.getData()); |
---|
322 | } |
---|
323 | |
---|
324 | } |
---|
325 | |
---|
326 | return NULL; |
---|
327 | } |
---|
328 | |
---|
329 | |
---|
330 | |
---|
331 | char *dupstr (const char *s) |
---|
332 | { |
---|
333 | char *r; |
---|
334 | |
---|
335 | r = (char*)malloc (strlen (s) + 1); |
---|
336 | strcpy (r, s); |
---|
337 | return (r); |
---|
338 | } |
---|
339 | |
---|
340 | // Read a string, and return a pointer to it. |
---|
341 | // Returns NULL on EOF. |
---|
342 | char *rl_gets (const char *prompt) |
---|
343 | { |
---|
344 | /* If the buffer has already been allocated, |
---|
345 | return the memory to the free pool. */ |
---|
346 | if (line_read) |
---|
347 | { |
---|
348 | free (line_read); |
---|
349 | line_read = (char *)NULL; |
---|
350 | } |
---|
351 | |
---|
352 | /* Get a line from the user. */ |
---|
353 | line_read = readline (prompt); |
---|
354 | |
---|
355 | /* If the line has any text in it, |
---|
356 | save it on the history. */ |
---|
357 | if (line_read && *line_read) add_history (line_read); |
---|
358 | |
---|
359 | return (line_read); |
---|
360 | } |
---|
361 | |
---|
362 | // Generator function for command completion. STATE lets us |
---|
363 | // know whether to start from scratch; without any state |
---|
364 | // (i.e. STATE == 0), then we start at the top of the list. |
---|
365 | char* |
---|
366 | command_generator (const char * text, int state) |
---|
367 | { |
---|
368 | static int list_index, len; |
---|
369 | const char *name; |
---|
370 | |
---|
371 | /* If this is a new word to complete, initialize now. This |
---|
372 | includes saving the length of TEXT for efficiency, and |
---|
373 | initializing the index variable to 0. */ |
---|
374 | if (!state) |
---|
375 | { |
---|
376 | list_index = 0; |
---|
377 | len = strlen (text); |
---|
378 | } |
---|
379 | |
---|
380 | /* Return the next name which partially matches from the |
---|
381 | command list. */ |
---|
382 | while (name = commands[list_index].name) |
---|
383 | { |
---|
384 | list_index++; |
---|
385 | |
---|
386 | if (strncmp (name, text, len) == 0) |
---|
387 | { |
---|
388 | memset(current_command, 0, 256); |
---|
389 | strcpy(current_command, name); |
---|
390 | return dupstr(name); |
---|
391 | } |
---|
392 | } |
---|
393 | |
---|
394 | /* If no names matched, then return NULL. */ |
---|
395 | return ((char *)NULL); |
---|
396 | } |
---|
397 | |
---|
398 | // Attempt to complete on the contents of TEXT. START and END |
---|
399 | // bound the region of rl_line_buffer that contains the word to |
---|
400 | // complete. TEXT is the word to complete. We can use the entire |
---|
401 | // contents of rl_line_buffer in case we want to do some simple |
---|
402 | // parsing. Returnthe array of matches, or NULL if there aren't any. |
---|
403 | char** |
---|
404 | fileman_completion (const char * text, int start, int end) |
---|
405 | { |
---|
406 | char **matches; |
---|
407 | |
---|
408 | matches = (char **)NULL; |
---|
409 | |
---|
410 | /* If this word is at the start of the line, then it is a command |
---|
411 | to complete. Otherwise it is the name of a file in the current |
---|
412 | directory. */ |
---|
413 | if (start == 0) |
---|
414 | { |
---|
415 | matches = rl_completion_matches (text, command_generator); |
---|
416 | } |
---|
417 | else |
---|
418 | { |
---|
419 | // If match found, display the corresponding documentation |
---|
420 | COMMAND *cm = find_command(current_command); |
---|
421 | if (cm) |
---|
422 | { |
---|
423 | matches = (char**)malloc(3*sizeof(char*)); |
---|
424 | matches[0] = dupstr(""); |
---|
425 | matches[1] = dupstr(cm->doc); |
---|
426 | matches[2] = NULL; |
---|
427 | } |
---|
428 | } |
---|
429 | |
---|
430 | return (matches); |
---|
431 | } |
---|
432 | |
---|
433 | // Look up NAME as the name of a command, and return a pointer to that |
---|
434 | // command. Return a NULL pointer if NAME isn't a command name. |
---|
435 | COMMAND *find_command (char *name) |
---|
436 | { |
---|
437 | register int i; |
---|
438 | |
---|
439 | for (i = 0; commands[i].name; i++) |
---|
440 | if (strcmp (name, commands[i].name) == 0) |
---|
441 | return (&commands[i]); |
---|
442 | |
---|
443 | return ((COMMAND *)NULL); |
---|
444 | } |
---|
445 | |
---|
446 | // Strip whitespace from the start and end of STRING. Return a pointer |
---|
447 | // into STRING. |
---|
448 | char* stripwhite (char *thestring) |
---|
449 | { |
---|
450 | register char *s, *t; |
---|
451 | |
---|
452 | for (s = thestring; whitespace (*s); s++) |
---|
453 | ; |
---|
454 | |
---|
455 | if (*s == 0) |
---|
456 | return (s); |
---|
457 | |
---|
458 | t = s + strlen (s) - 1; |
---|
459 | while (t > s && whitespace (*t)) |
---|
460 | t--; |
---|
461 | *++t = '\0'; |
---|
462 | |
---|
463 | return s; |
---|
464 | } |
---|
465 | |
---|
466 | |
---|
467 | |
---|
468 | // Execute a command line |
---|
469 | int execute_line (char *line) |
---|
470 | { |
---|
471 | register int i; |
---|
472 | COMMAND *command; |
---|
473 | char *word; |
---|
474 | |
---|
475 | /* Isolate the command word. */ |
---|
476 | i = 0; |
---|
477 | while (line[i] && whitespace (line[i])) |
---|
478 | i++; |
---|
479 | word = line + i; |
---|
480 | |
---|
481 | while (line[i] && !whitespace (line[i])) |
---|
482 | i++; |
---|
483 | |
---|
484 | if (line[i]) |
---|
485 | line[i++] = '\0'; |
---|
486 | |
---|
487 | command = find_command (word); |
---|
488 | |
---|
489 | if (!command) |
---|
490 | { |
---|
491 | fprintf (stderr, "%s: No such command.\n", word); |
---|
492 | return (-1); |
---|
493 | } |
---|
494 | |
---|
495 | /* Get argument to command, if any. */ |
---|
496 | while (whitespace (line[i])) |
---|
497 | i++; |
---|
498 | |
---|
499 | word = line + i; |
---|
500 | |
---|
501 | /* Call the function. */ |
---|
502 | return ((*(command->func)) (word)); |
---|
503 | } |
---|
504 | |
---|
505 | |
---|
506 | int |
---|
507 | main(int argc, char **argv) |
---|
508 | { |
---|
509 | pthread_t thId; |
---|
510 | char *line, *s; |
---|
511 | char com[256]; |
---|
512 | |
---|
513 | zeroPerf = false; |
---|
514 | |
---|
515 | // File containing commands |
---|
516 | playback = NULL; |
---|
517 | if (argc >= 2) |
---|
518 | { |
---|
519 | playback = fopen(argv[1], "r"); |
---|
520 | if (playback == NULL) |
---|
521 | fprintf(stderr, "Cannot open playback file <%s>\n", argv[1]); |
---|
522 | } |
---|
523 | |
---|
524 | if (argc > 2) { |
---|
525 | strcpy(execArg, argv[2]); |
---|
526 | } |
---|
527 | else |
---|
528 | strcpy(execArg, "no"); |
---|
529 | |
---|
530 | if (argc > 8) |
---|
531 | intval = atoi(argv[8]); |
---|
532 | |
---|
533 | // Setup the completion function |
---|
534 | rl_attempted_completion_function = fileman_completion; |
---|
535 | |
---|
536 | // Clear application list |
---|
537 | for (int k=0;k<64;k++) Applications[k] = NULL; |
---|
538 | |
---|
539 | // Connect to SAGE |
---|
540 | uiLib.init("fsManager.conf"); |
---|
541 | uiLib.connect(NULL); |
---|
542 | |
---|
543 | uiLib.sendMessage(SAGE_UI_REG," "); |
---|
544 | |
---|
545 | // Start the receiving thread |
---|
546 | if(pthread_create(&thId, 0, readThread, (void*)&uiLib) != 0) |
---|
547 | { |
---|
548 | return -1; |
---|
549 | } |
---|
550 | |
---|
551 | #if defined(SAGE_NETLOG) |
---|
552 | // Get local time |
---|
553 | time_t local = time(NULL); |
---|
554 | struct tm *current = localtime( & local ); |
---|
555 | char fn[256]; |
---|
556 | |
---|
557 | memset(fn, 0, 256); |
---|
558 | sprintf(fn, "log/%s-%d-%d-%d-%d-%d-%d.nlg", // year-month-day hour-minute-second |
---|
559 | "fsConsole", |
---|
560 | current->tm_year, current->tm_mon, current->tm_mday, |
---|
561 | current->tm_hour, current->tm_min, current->tm_sec); |
---|
562 | NL_logger_module( "fsConsole", fn, NL_LVL_INFO, NL_TYPE_APP, "" ); |
---|
563 | #endif |
---|
564 | |
---|
565 | /* Loop reading and executing lines until the user quits. */ |
---|
566 | for ( ; done == 0; ) |
---|
567 | { |
---|
568 | if (playback && !feof(playback)) |
---|
569 | { |
---|
570 | memset(com, 0, 256); |
---|
571 | if ( fgets(com, 256, playback) ) |
---|
572 | { |
---|
573 | // trailing \n |
---|
574 | com[ strlen(com)-1 ] = '\0'; |
---|
575 | s = stripwhite (com); |
---|
576 | int v, pause; |
---|
577 | v = sscanf(s, "pause %d", &pause); |
---|
578 | if (v == 1) |
---|
579 | { |
---|
580 | fprintf(stderr, "PB> Pausing %d sec\n", pause); |
---|
581 | sleep(pause); |
---|
582 | } |
---|
583 | else |
---|
584 | if (*s) |
---|
585 | { |
---|
586 | add_history (s); |
---|
587 | fprintf(stderr, "PB> Exec <%s>\n", s); |
---|
588 | execute_line (s); |
---|
589 | } |
---|
590 | } |
---|
591 | } |
---|
592 | else |
---|
593 | { |
---|
594 | line = rl_gets(">>> "); |
---|
595 | |
---|
596 | if (!line) break; |
---|
597 | |
---|
598 | /* Remove leading and trailing whitespace from the line. |
---|
599 | Then, if there is anything left, add it to the history list |
---|
600 | and execute it. */ |
---|
601 | s = stripwhite (line); |
---|
602 | |
---|
603 | if (*s) |
---|
604 | { |
---|
605 | add_history (s); |
---|
606 | execute_line (s); |
---|
607 | } |
---|
608 | } |
---|
609 | } |
---|
610 | |
---|
611 | // Close the command file |
---|
612 | if (playback != NULL) |
---|
613 | fclose(playback); |
---|
614 | |
---|
615 | return 0; |
---|
616 | } |
---|
617 | |
---|
618 | |
---|
619 | |
---|
620 | |
---|
621 | |
---|
622 | // **************************************************************** |
---|
623 | // |
---|
624 | // Commands |
---|
625 | // |
---|
626 | // **************************************************************** |
---|
627 | |
---|
628 | |
---|
629 | int com_exec (char *arg) |
---|
630 | { |
---|
631 | #if defined(SAGE_NETLOG) |
---|
632 | NL_flush = 1; |
---|
633 | NL_write( "fsConsole", NL_LVL_INFO, "exec", "arg=s", arg); |
---|
634 | #endif |
---|
635 | uiLib.sendMessage(EXEC_APP, arg); |
---|
636 | strcpy(exec_arg, arg); |
---|
637 | return 0; |
---|
638 | } |
---|
639 | |
---|
640 | int com_move (char *arg) |
---|
641 | { |
---|
642 | #if defined(SAGE_NETLOG) |
---|
643 | NL_flush = 1; |
---|
644 | NL_write( "fsConsole", NL_LVL_INFO, "move", "arg=s", arg); |
---|
645 | #endif |
---|
646 | uiLib.sendMessage(MOVE_WINDOW, arg); |
---|
647 | return 0; |
---|
648 | } |
---|
649 | |
---|
650 | int com_ptr (char *arg) |
---|
651 | { |
---|
652 | #if defined(SAGE_NETLOG) |
---|
653 | NL_flush = 1; |
---|
654 | NL_write( "fsConsole", NL_LVL_INFO, "ptr", "arg=s", arg); |
---|
655 | #endif |
---|
656 | uiLib.sendMessage(MOVE_OBJECT, arg); |
---|
657 | return 0; |
---|
658 | } |
---|
659 | |
---|
660 | int com_resize (char *arg) |
---|
661 | { |
---|
662 | #if defined(SAGE_NETLOG) |
---|
663 | NL_flush = 1; |
---|
664 | NL_write( "fsConsole", NL_LVL_INFO, "resize", "arg=s", arg); |
---|
665 | #endif |
---|
666 | uiLib.sendMessage(RESIZE_WINDOW, arg); |
---|
667 | return 0; |
---|
668 | } |
---|
669 | |
---|
670 | int com_bg (char *arg) |
---|
671 | { |
---|
672 | #if defined(SAGE_NETLOG) |
---|
673 | NL_flush = 1; |
---|
674 | NL_write( "fsConsole", NL_LVL_INFO, "bg", "arg=s", arg); |
---|
675 | #endif |
---|
676 | uiLib.sendMessage(SAGE_BG_COLOR, arg); |
---|
677 | return 0; |
---|
678 | } |
---|
679 | |
---|
680 | int com_depth (char *arg) |
---|
681 | { |
---|
682 | #if defined(SAGE_NETLOG) |
---|
683 | NL_flush = 1; |
---|
684 | NL_write( "fsConsole", NL_LVL_INFO, "depth", "arg=s", arg); |
---|
685 | #endif |
---|
686 | uiLib.sendMessage(SAGE_Z_VALUE, arg); |
---|
687 | return 0; |
---|
688 | } |
---|
689 | |
---|
690 | int com_zeroperf (char *arg) |
---|
691 | { |
---|
692 | zeroPerf = true; |
---|
693 | return 0; |
---|
694 | } |
---|
695 | |
---|
696 | int com_rate (char *arg) |
---|
697 | { |
---|
698 | uiLib.sendMessage(APP_FRAME_RATE, arg); |
---|
699 | return 0; |
---|
700 | } |
---|
701 | |
---|
702 | int com_intval (char *arg) |
---|
703 | { |
---|
704 | uiLib.sendMessage(APP_PAUSE_INTV, arg); |
---|
705 | return 0; |
---|
706 | } |
---|
707 | |
---|
708 | int com_share (char *arg) |
---|
709 | { |
---|
710 | uiLib.sendMessage(SAGE_APP_SHARE, arg); |
---|
711 | return 0; |
---|
712 | } |
---|
713 | |
---|
714 | int com_perf (char *arg) |
---|
715 | { |
---|
716 | #if defined(SAGE_NETLOG) |
---|
717 | NL_flush = 1; |
---|
718 | NL_write( "fsConsole", NL_LVL_INFO, "perf", "arg=s", arg); |
---|
719 | #endif |
---|
720 | zeroPerf = false; |
---|
721 | uiLib.sendMessage(PERF_INFO_REQ, arg); |
---|
722 | return 0; |
---|
723 | } |
---|
724 | |
---|
725 | int com_stopperf (char *arg) |
---|
726 | { |
---|
727 | #if defined(SAGE_NETLOG) |
---|
728 | NL_flush = 1; |
---|
729 | NL_write( "fsConsole", NL_LVL_INFO, "stopperf", "arg=s", arg); |
---|
730 | #endif |
---|
731 | uiLib.sendMessage(STOP_PERF_INFO, arg); |
---|
732 | return 0; |
---|
733 | } |
---|
734 | |
---|
735 | int com_kill (char *arg) |
---|
736 | { |
---|
737 | #if defined(SAGE_NETLOG) |
---|
738 | NL_flush = 1; |
---|
739 | NL_write( "fsConsole", NL_LVL_INFO, "kill", "arg=s", arg); |
---|
740 | #endif |
---|
741 | uiLib.sendMessage(SHUTDOWN_APP, arg); |
---|
742 | return 0; |
---|
743 | } |
---|
744 | |
---|
745 | int com_shutdown (char *arg) |
---|
746 | { |
---|
747 | #if defined(SAGE_NETLOG) |
---|
748 | //NL_flush = 1; |
---|
749 | //NL_write( "fsConsole", NL_LVL_INFO, "shutdown", "arg=s", arg); |
---|
750 | #endif |
---|
751 | // Close all the log files |
---|
752 | for (int k=0;k<64;k++) |
---|
753 | if (Applications[k]) |
---|
754 | fclose(Applications[k]->log); |
---|
755 | |
---|
756 | #if defined(SAGE_NETLOG) |
---|
757 | NL_logger_del(); |
---|
758 | #endif |
---|
759 | |
---|
760 | // Send the message |
---|
761 | uiLib.sendMessage(SAGE_SHUTDOWN, "shutdown"); |
---|
762 | done = 1; |
---|
763 | |
---|
764 | return 0; |
---|
765 | } |
---|
766 | |
---|
767 | int com_admin (char *arg) |
---|
768 | { |
---|
769 | #if defined(SAGE_NETLOG) |
---|
770 | NL_flush = 1; |
---|
771 | NL_write( "fsConsole", NL_LVL_INFO, "admin", "arg=s", arg); |
---|
772 | #endif |
---|
773 | uiLib.sendMessage(SAGE_ADMIN_CHECK, "admin"); |
---|
774 | return 0; |
---|
775 | } |
---|
776 | |
---|
777 | |
---|
778 | // Print out help for ARG, or for all of the commands |
---|
779 | // if ARG is not present. |
---|
780 | int com_help (char *arg) |
---|
781 | { |
---|
782 | register int i; |
---|
783 | int printed = 0; |
---|
784 | |
---|
785 | #if defined(SAGE_NETLOG) |
---|
786 | NL_flush = 1; |
---|
787 | NL_write( "fsConsole", NL_LVL_INFO, "help", "arg=s", arg); |
---|
788 | #endif |
---|
789 | |
---|
790 | for (i = 0; commands[i].name; i++) |
---|
791 | { |
---|
792 | if (!*arg || (strcmp (arg, commands[i].name) == 0)) |
---|
793 | { |
---|
794 | printf ("%-8s\t\t%s.\n", commands[i].name, commands[i].doc); |
---|
795 | printed++; |
---|
796 | } |
---|
797 | } |
---|
798 | |
---|
799 | if (!printed) |
---|
800 | { |
---|
801 | printf ("No commands match `%s'. Possibilties are:\n", arg); |
---|
802 | |
---|
803 | for (i = 0; commands[i].name; i++) |
---|
804 | { |
---|
805 | /* Print in six columns. */ |
---|
806 | if (printed == 6) |
---|
807 | { |
---|
808 | printed = 0; |
---|
809 | printf ("\n"); |
---|
810 | } |
---|
811 | |
---|
812 | printf ("%s\t", commands[i].name); |
---|
813 | printed++; |
---|
814 | } |
---|
815 | |
---|
816 | if (printed) |
---|
817 | printf ("\n"); |
---|
818 | } |
---|
819 | return (0); |
---|
820 | } |
---|
821 | |
---|
822 | // The user wishes to quit using this program. |
---|
823 | // Just set DONE non-zero. |
---|
824 | int com_exit (char *arg) |
---|
825 | { |
---|
826 | #if defined(SAGE_NETLOG) |
---|
827 | NL_flush = 1; |
---|
828 | NL_write( "fsConsole", NL_LVL_INFO, "exit", "arg=s", arg); |
---|
829 | #endif |
---|
830 | |
---|
831 | std::cout << "\t Done with SAGE..." << std::endl; |
---|
832 | |
---|
833 | done = 1; |
---|
834 | return (0); |
---|
835 | } |
---|