Line data Source code
1 : /********************************************************************\
2 :
3 : Name: mchart.c
4 : Created by: Pierre-Andre Amaudruz
5 :
6 : Contents: Periodic Midas chart graph data generator.
7 : Generate the proper configuration and data files for
8 : the gstripchart application or the GH (Gertjan Hofman)
9 : stripchart.tcl
10 : standard running description is:
11 : mchart -f <file> -q <ODB tree> -c
12 : ex: mchart -f trigger -q /equipment/trigger/statistics -c
13 : produce trigger.conf and trigger (data)
14 :
15 : mchart -f <file>[.conf] -g
16 : ex: mchart -f trigger[.conf] -gg
17 : produce periodically trigger and spawn gstripchart for
18 : display of the data.
19 : See mchart -h for further info.
20 :
21 : $Id$
22 :
23 : \********************************************************************/
24 :
25 : #include <fcntl.h>
26 : #include "midas.h"
27 : #include "msystem.h"
28 :
29 : #define CONF_CREATE 1
30 : #define CONF_APPEND 2
31 :
32 : char color[][16] =
33 : { "blue", "red", "brown", "black", "orange", "cyan", "yellow", "beige", "DarkCyan",
34 : "DarkOliveGreen", "goldenrod", "DeepPink"
35 : };
36 : INT max_element = 8;
37 : DWORD delta_time;
38 : BOOL keep = FALSE, debug = FALSE, create_only = FALSE;
39 : BOOL create = FALSE, config_done = FALSE;
40 : INT graph = 0, element = 0;
41 :
42 : INT mchart_compose(HNDLE hDB, char *confpath, char *datapath, char *eqpstr);
43 : INT conf_compose(INT action, char *confpath, char *datapath, char *field, float val);
44 : float toplimit = 0., botlimit = 0.;
45 :
46 : /*------------------------------------------------------------------*/
47 0 : INT conf_compose(INT action, char *confpath, char *datapath, char *field, float val)
48 : {
49 : FILE *f;
50 : float minval, maxval;
51 :
52 0 : if (config_done)
53 0 : return 0;
54 :
55 0 : switch (action) {
56 0 : case CONF_CREATE:
57 0 : if (keep)
58 0 : return 1;
59 : /* open device */
60 0 : f = fopen(confpath, "w+");
61 0 : if (f == NULL) {
62 0 : printf("Cannot open configuration strip file.\n");
63 0 : return 0;
64 : }
65 0 : fprintf(f, "#Equipment: >%s", field);
66 0 : fprintf(f, "\n");
67 0 : fprintf(f, "menu: on\n");
68 0 : fprintf(f, "slider: on\n");
69 0 : fprintf(f, "type: gtk\n");
70 :
71 0 : fprintf(f, "minor_ticks: 12\n");
72 0 : fprintf(f, "major_ticks: 6\n");
73 :
74 0 : fprintf(f, "chart-interval: 1.000\n");
75 0 : fprintf(f, "chart-filter: 0.500\n");
76 0 : fprintf(f, "slider-interval: 0.200\n");
77 0 : fprintf(f, "slider-filter: 0.200\n");
78 0 : fclose(f);
79 0 : break;
80 :
81 0 : case CONF_APPEND:
82 0 : if (keep)
83 0 : return 1;
84 :
85 0 : f = fopen(confpath, "a+");
86 0 : if (f == NULL) {
87 0 : printf("Cannot open configuration strip file.\n");
88 0 : return 0;
89 : }
90 0 : if ((element % max_element) == 0)
91 0 : element = 0;
92 :
93 0 : minval = maxval = val;
94 : /* check upper limits */
95 0 : if (toplimit == 0.) { /* use current value */
96 0 : if (val == 0.)
97 0 : maxval = 5.;
98 0 : else if (val > 0.)
99 0 : maxval *= 2.;
100 : else
101 0 : maxval /= 2.;
102 : } else /* use arg value */
103 0 : maxval = toplimit;
104 :
105 : /* check lower limits */
106 0 : if (botlimit == 0.) { /* use current value */
107 0 : if (val == 0.)
108 0 : minval = -5.;
109 0 : else if (val > 0.)
110 0 : minval /= 2.;
111 : else
112 0 : minval *= 2.;
113 : } else /* use arg value */
114 0 : minval = botlimit;
115 :
116 0 : fprintf(f, "begin: %s\n", field);
117 0 : fprintf(f, " filename: %s\n", datapath);
118 0 : fprintf(f, " fields: 2\n");
119 0 : fprintf(f, " pattern: %s\n", field);
120 0 : fprintf(f, " equation: $2\n");
121 0 : fprintf(f, " color: %s\n", color[element++]);
122 0 : fprintf(f, " maximum: %6.2f\n", maxval);
123 0 : fprintf(f, " minimum: %6.2f\n", minval);
124 0 : fprintf(f, " id_char: 1\n");
125 0 : fprintf(f, "end: %s\n", field);
126 0 : fclose(f);
127 0 : break;
128 0 : default:
129 0 : printf(" unknown command \n");
130 : }
131 0 : return 1;
132 : }
133 :
134 : /*------------------------------------------------------------------*/
135 0 : INT mchart_get_names(HNDLE hDB, char *eqpstr, char *element, char **pname, INT * esize)
136 : {
137 : char *pslash, *p;
138 : char strtmp[128];
139 : HNDLE hKeyS, hSubKey;
140 : KEY key;
141 : INT i, size;
142 0 : BOOL bslash = FALSE;
143 :
144 : /* convert to upper */
145 0 : p = eqpstr;
146 0 : for (i = 0; i < 128; i++)
147 0 : strtmp[i] = 0;
148 0 : int len_eqpstr = strlen(eqpstr);
149 0 : for (i=0 ; i<len_eqpstr; i++)
150 0 : eqpstr[i] = tolower(eqpstr[i]);
151 :
152 : /* I don't remember what I'm doing here but it's useful! */
153 0 : if (strncmp(eqpstr, "equipment/", 10) == 0)
154 0 : bslash = TRUE;
155 0 : if (strncmp(eqpstr, "/equipment/", 11) == 0) {
156 : /* if the -q starts with /equipment and 2 more slash are following
157 : OR
158 : if the -q starts with equipment and 1 more slash are following
159 : then I search the Settings for the names of the variables */
160 0 : pslash = strchr(eqpstr, '/');
161 0 : pslash = strchr(pslash + 1, '/');
162 0 : if (!bslash)
163 0 : pslash = strchr(pslash + 1, '/');
164 0 : if (pslash) {
165 0 : strncpy(strtmp, eqpstr, pslash - eqpstr);
166 0 : strcat(strtmp, "/settings");
167 :
168 0 : if (db_find_key(hDB, 0, strtmp, &hKeyS) == DB_SUCCESS) {
169 0 : db_get_key(hDB, hKeyS, &key);
170 0 : for (i = 0;; i++) { /* search first for "Names element" */
171 0 : db_enum_key(hDB, hKeyS, i, &hSubKey);
172 0 : if (!hSubKey)
173 0 : break;
174 0 : db_get_key(hDB, hSubKey, &key);
175 0 : if (key.name[5] && key.type == TID_STRING) { /* fmt Names xxxx */
176 0 : p = &(key.name[6]);
177 0 : if (strstr(p, element) == NULL)
178 0 : continue;
179 0 : *esize = key.item_size;
180 0 : size = *esize * key.num_values;
181 0 : *pname = (char*)malloc(size);
182 0 : db_get_data(hDB, hSubKey, *pname, &size, key.type);
183 0 : return key.num_values;
184 : }
185 : }
186 : /* rescan dir for "Names" only now */
187 0 : db_get_key(hDB, hKeyS, &key);
188 0 : for (i = 0;; i++) {
189 0 : db_enum_key(hDB, hKeyS, i, &hSubKey);
190 0 : if (!hSubKey)
191 0 : break;
192 0 : db_get_key(hDB, hSubKey, &key);
193 0 : if (strncmp(key.name, "Names", 5) == 0) { /* fmt Names (only) */
194 0 : *esize = key.item_size;
195 0 : size = *esize * key.num_values;
196 0 : *pname = (char*)malloc(size);
197 0 : db_get_data(hDB, hSubKey, *pname, &size, key.type);
198 0 : return key.num_values;
199 : }
200 : }
201 : }
202 : }
203 : }
204 0 : return 0;
205 : }
206 :
207 : /*------------------------------------------------------------------*/
208 0 : INT mchart_get_array(FILE * f, char *eqpstr, HNDLE hDB, HNDLE hSubkey, KEY key,
209 : char *confpath, char *datapath)
210 : {
211 : char field[128];
212 : INT nfound, status, i, size, esize;
213 0 : char *pspace, *pdata = NULL, *pname = NULL;
214 : float value;
215 :
216 0 : size = key.num_values * key.item_size;
217 0 : pdata = (char*)malloc(size);
218 0 : status = db_get_data(hDB, hSubkey, pdata, &size, key.type);
219 0 : if (status != DB_SUCCESS) {
220 0 : free(pdata);
221 0 : return 0;
222 : }
223 :
224 0 : if (debug)
225 0 : printf("%s : size:%d\n", key.name, size);
226 :
227 0 : nfound = mchart_get_names(hDB, eqpstr, key.name, &pname, &esize);
228 :
229 0 : if (debug)
230 0 : printf("#name:%d #Values:%d\n", nfound, key.num_values);
231 : /* if names found but no array then use variable names */
232 0 : if (key.num_values == 1)
233 0 : nfound = FALSE;
234 0 : for (i = 0; i < key.num_values; i++) {
235 0 : if (nfound)
236 0 : strcpy(field, (pname + (i * esize)));
237 : else {
238 0 : if (key.num_values == 1)
239 0 : sprintf(field, "%s", key.name);
240 : else /* if no settings/Names ... found then compose names here */
241 0 : sprintf(field, "%s[%i]", key.name, i);
242 : }
243 :
244 : /* substitution for tcl */
245 0 : while ((pspace = strstr(field, " ")))
246 0 : *pspace = '_';
247 0 : while ((pspace = strstr(field, "%")))
248 0 : *pspace = '_';
249 :
250 : /* fill data file */
251 0 : if (key.type == TID_INT) {
252 0 : value = (float) *((INT *) (pdata + (i * key.item_size)));
253 0 : fprintf(f, "%s %d\n", field, *((INT *) (pdata + (i * key.item_size))));
254 0 : } else if (key.type == TID_WORD) {
255 0 : value = (float) *((WORD *) (pdata + (i * key.item_size)));
256 0 : fprintf(f, "%s %d\n", field, *((WORD *) (pdata + (i * key.item_size))));
257 0 : } else if (key.type == TID_DWORD) {
258 0 : value = (float) *((DWORD *) (pdata + (i * key.item_size)));
259 0 : fprintf(f, "%s %d\n", field, *((DWORD *) (pdata + (i * key.item_size))));
260 0 : } else if (key.type == TID_FLOAT) {
261 0 : value = *((float *) (pdata + (i * key.item_size)));
262 0 : fprintf(f, "%s %f\n", field, *((float *) (pdata + (i * key.item_size))));
263 0 : } else if (key.type == TID_DOUBLE) {
264 0 : value = (float) *((double *) (pdata + (i * key.item_size)));
265 0 : fprintf(f, "%s %e\n", field, *((double *) (pdata + (i * key.item_size))));
266 : } else
267 0 : continue;
268 :
269 0 : if (!config_done) {
270 0 : if (debug)
271 0 : printf("Field:%s Values:%f\n", field, value);
272 0 : conf_compose(CONF_APPEND, confpath, datapath, field, value);
273 : }
274 : }
275 0 : if (pdata)
276 0 : free(pdata);
277 0 : if (pname)
278 0 : free(pname);
279 0 : return 1;
280 : }
281 :
282 : /*------------------------------------------------------------------*/
283 0 : INT mchart_compose(HNDLE hDB, char *confpath, char *datapath, char *eqpstr)
284 : {
285 : FILE *fHandle;
286 : INT i, status;
287 : KEY key;
288 : HNDLE hKey, hSubkey;
289 :
290 : /* check if dir exists */
291 0 : if ((status = db_find_key(hDB, 0, eqpstr, &hKey)) == DB_SUCCESS) {
292 0 : fHandle = fopen(datapath, "w+");
293 0 : if (fHandle == NULL) {
294 0 : printf("Cannot open config %s file.\n", confpath);
295 0 : return -1;
296 : }
297 :
298 0 : db_get_key(hDB, hKey, &key);
299 0 : if (key.type != TID_KEY) {
300 0 : status = mchart_get_array(fHandle, eqpstr, hDB, hKey, key, confpath, datapath);
301 0 : if (status < 1) {
302 0 : printf("Error: cannot get array for %s\n", eqpstr);
303 0 : return -2;
304 : }
305 : } else
306 0 : for (i = 0;; i++) {
307 0 : db_enum_key(hDB, hKey, i, &hSubkey);
308 0 : if (!hSubkey)
309 0 : break;
310 0 : db_get_key(hDB, hSubkey, &key);
311 : status =
312 0 : mchart_get_array(fHandle, eqpstr, hDB, hSubkey, key, confpath, datapath);
313 0 : if (status < 1) {
314 0 : printf("Error: cannot get array for %s\n", eqpstr);
315 0 : return -3;
316 : }
317 : } /* get value */
318 : } /* equ found */
319 : else {
320 0 : printf("Error: Equipment:%s not found\n", eqpstr);
321 0 : return 0;
322 : }
323 0 : fclose(fHandle);
324 0 : config_done = TRUE;
325 0 : return 1;
326 : }
327 :
328 : /*------------------------------------------------------------------*/
329 0 : int main(int argc, char **argv)
330 : {
331 : char command[512];
332 0 : BOOL daemon, keep_strip = FALSE;
333 0 : INT status, last_time = 0;
334 : //DWORD i;
335 : HNDLE hDB, hKey;
336 : char host_name[HOST_NAME_LENGTH], expt_name[NAME_LENGTH];
337 0 : char eqpstr[128] = { '\0' };
338 : char cmdline[256];
339 : signed char ch;
340 0 : char mchart_dir[128] = { '\0' };
341 : char mchart_data[128];
342 : char mchart_conf[128+10];
343 : INT msg, childpid;
344 : int sys_err;
345 : /* set default */
346 0 : cm_get_environment(host_name, sizeof(host_name), expt_name, sizeof(expt_name));
347 0 : delta_time = 5000;
348 0 : daemon = FALSE;
349 :
350 : /* retrieve environment */
351 0 : if (getenv("MCHART_DIR")) {
352 0 : strcpy(mchart_dir, getenv("MCHART_DIR"));
353 0 : if (mchart_dir[strlen(mchart_dir) - 1] != DIR_SEPARATOR)
354 0 : strcat(mchart_dir, DIR_SEPARATOR_STR);
355 : }
356 :
357 : /* get parameters parse command line parameters */
358 0 : for (int i = 1; i < argc; i++) {
359 0 : if (argv[i][0] == '-' && argv[i][1] == 'd')
360 0 : debug = TRUE;
361 0 : else if (argv[i][0] == '-' && argv[i][1] == 'c')
362 0 : create_only = TRUE;
363 0 : else if (argv[i][0] == '-' && argv[i][1] == 's')
364 0 : keep = TRUE;
365 0 : else if (argv[i][0] == '-' && argv[i][1] == 'g' && argv[i][2] == 'g')
366 0 : graph = 2;
367 0 : else if (argv[i][0] == '-' && argv[i][1] == 'g' && argv[i][2] == 'h')
368 0 : graph = 3;
369 0 : else if (argv[i][0] == '-' && argv[i][1] == 'g')
370 0 : graph = 1;
371 0 : else if (argv[i][0] == '-' && argv[i][1] == 'k')
372 0 : keep_strip = TRUE;
373 0 : else if (argv[i][0] == '-' && argv[i][1] == 'D')
374 0 : daemon = TRUE;
375 0 : else if (argv[i][0] == '-') {
376 0 : if (i + 1 >= argc || (argv[i + 1][0] == '-' && !isdigit(argv[i + 1][1])))
377 0 : goto usage;
378 0 : if (strncmp(argv[i], "-u", 2) == 0)
379 0 : delta_time = 1000 * (atoi(argv[++i]));
380 0 : else if (strncmp(argv[i], "-f", 2) == 0) {
381 : char *pt;
382 0 : pt = strstr(argv[++i], ".conf");
383 0 : if (pt)
384 0 : *pt = '\0';
385 0 : strcpy(mchart_data, mchart_dir);
386 0 : strcat(mchart_data, argv[i]);
387 0 : sprintf(mchart_conf, "%s.conf", mchart_data);
388 0 : } else if (strncmp(argv[i], "-e", 2) == 0)
389 0 : strcpy(expt_name, argv[++i]);
390 0 : else if (strncmp(argv[i], "-h", 2) == 0)
391 0 : strcpy(host_name, argv[++i]);
392 0 : else if (strncmp(argv[i], "-q", 2) == 0) {
393 0 : if (argv[++i][0] != '/')
394 0 : strcpy(eqpstr, "/");
395 0 : strcat(eqpstr, argv[i]);
396 0 : create = TRUE;
397 0 : } else if (strncmp(argv[i], "-b", 2) == 0)
398 0 : botlimit = (float) atof(argv[++i]);
399 0 : else if (strncmp(argv[i], "-t", 2) == 0)
400 0 : toplimit = (float) atof(argv[++i]);
401 : } else {
402 0 : usage:
403 0 : printf("usage: mchart -u updates (5sec)\n");
404 0 : printf(" -f configuration or data file name\n");
405 0 : printf(" -q equipment\n");
406 0 : printf(" (override all) -b bot_limit -t top_limit (only with -q) \n");
407 0 : printf(" -c create config only \n");
408 0 : printf(" -k keep spawned stripchart or gstripchart\n");
409 : printf
410 0 : (" -g spawn Hofman stripchart or gstripchart if possible\n");
411 0 : printf(" -gg forces gstripchart spawning\n");
412 0 : printf(" -gh forces stripchart spawning\n");
413 0 : printf(" -D start as daemon (prevented if -c or -q)\n");
414 0 : printf(" requires $MCHART_DIR\n");
415 0 : printf(" [-h Hostname] [-e Experiment]\n\n");
416 0 : printf("ex: Creation : mchart -e myexpt -h myhost -c \n");
417 0 : printf(" -f mydata -q /equipement/myeqp/variables\n");
418 0 : printf(" Running : mchart -e myexpt -h myhost -f mydata \n");
419 0 : printf(" Run/Graph : mchart -e myexpt -h myhost -f mydata -g\n");
420 0 : printf(" MCHART_DIR: environment variable for mchar directory\n\n");
421 0 : return 0;
422 : }
423 : }
424 :
425 : /* Daemon start */
426 0 : if (daemon && !(create || create_only)) {
427 0 : printf("Becoming a daemon...\n");
428 0 : ss_daemon_init(FALSE);
429 : }
430 :
431 0 : if (daemon)
432 0 : printf("arg -D ignored due to creation request! \n");
433 :
434 : /* connect to experiment */
435 0 : status = cm_connect_experiment(host_name, expt_name, "MChart", 0);
436 0 : if (status != CM_SUCCESS)
437 0 : return 1;
438 :
439 0 : if (debug)
440 0 : cm_set_watchdog_params(TRUE, 0);
441 :
442 : /* turn off message display, turn on message logging */
443 0 : cm_set_msg_print(MT_ALL, 0, NULL);
444 :
445 : /* connect to the database */
446 0 : cm_get_experiment_database(&hDB, &hKey);
447 :
448 : /* initialize ss_getchar() */
449 0 : ss_getchar(0);
450 :
451 : /* recompose command line */
452 0 : sprintf(cmdline, "%s ", argv[1]);
453 0 : for (int i = 2; i < argc; i++) {
454 0 : strcat(cmdline, " ");
455 0 : strcat(cmdline, argv[i]);
456 : }
457 :
458 : /* check if creation required */
459 0 : if (!create) {
460 : /* extract equipment key */
461 : FILE *f;
462 : char strtmp[128];
463 : char *peqp;
464 : char *s;
465 :
466 0 : config_done = TRUE;
467 0 : create = FALSE;
468 : /* Overwrite the -q using the file.conf content */
469 0 : f = fopen(mchart_conf, "r");
470 0 : if (f == NULL) {
471 0 : printf("Error: Cannot open %s\n", mchart_conf);
472 0 : goto error;
473 : }
474 0 : s = fgets(strtmp, 128, f);
475 0 : if (s == NULL) {
476 0 : printf("Error: Cannot read %s\n", mchart_conf);
477 0 : goto error;
478 : }
479 0 : if (strstr(strtmp, "#Equipment")) {
480 0 : peqp = strstr(strtmp, ">");
481 0 : sprintf(eqpstr, "%s", peqp + 1);
482 : }
483 0 : fclose(f);
484 0 : peqp = strstr(eqpstr, "\n");
485 0 : *peqp = 0;
486 : } else {
487 : /* creation of config file requested */
488 : /* check if equipment string is a valifd key in order to
489 : prevent overwriting the configuration file */
490 0 : if (db_find_key(hDB, 0, eqpstr, &hKey) != DB_SUCCESS) {
491 0 : printf("unknown odb path under -q arg. (%s)\n", eqpstr);
492 0 : goto error;
493 : }
494 0 : status = conf_compose(CONF_CREATE, mchart_conf, mchart_data, eqpstr, (float) argc);
495 0 : if (status != 1)
496 0 : goto error;
497 : }
498 :
499 : do {
500 0 : if ((ss_millitime() - last_time) > delta_time) {
501 0 : last_time = ss_millitime();
502 0 : status = mchart_compose(hDB, mchart_conf, mchart_data, eqpstr);
503 0 : if (status != 1)
504 0 : goto error;
505 0 : if (create_only) {
506 0 : printf("mchart file %s created\n", mchart_conf);
507 0 : goto out;
508 : }
509 : }
510 :
511 : /* spawn graph once if possible */
512 0 : if (graph == 1) {
513 : char command[512];
514 0 : char *list = NULL;
515 : INT i, nfile;
516 :
517 0 : char strip[][32] = { "/usr/local/bin", "stripchart",
518 : "/usr/bin", "gstripchart",
519 : "/home/midas/bin", "stripchart",
520 : "/usr/sbin", "gstripchart",
521 : "/home/chaos/bin", "stripchart",
522 : "/sbin", "gstripchart",
523 : ""
524 : };
525 :
526 0 : i = 0;
527 0 : while (strip[i][0]) {
528 0 : nfile = ss_file_find(strip[i], strip[i + 1], &list);
529 0 : free(list);
530 0 : if (nfile == 1)
531 0 : break;
532 0 : i += 2;
533 : }
534 0 : if (strip[i][0] == 0) {
535 0 : printf("No graphic package found in following dir:\n");
536 0 : i = 0;
537 0 : while (strip[i][0]) {
538 0 : printf("Package : %s/%s \n", strip[i], strip[i + 1]);
539 0 : i += 2;
540 : }
541 0 : break;
542 : }
543 0 : if (i % 2)
544 0 : sprintf(command, "gstripchart -g 500x200-200-800 -f %s", mchart_conf);
545 : else
546 0 : sprintf(command, "stripchart %s", mchart_conf);
547 :
548 0 : if (!daemon)
549 0 : printf("Spawning graph with %s ...\nUse '!' to exit\n", command);
550 0 : ss_exec(command, &childpid);
551 0 : } else if (graph == 2) { /* Gnu graph */
552 0 : sprintf(command, "gstripchart -g 500x200-200-800 -f %s", mchart_conf);
553 0 : if (!daemon)
554 0 : printf("Spawning graph with %s ...\nUse '!' to exit\n", command);
555 0 : ss_exec(command, &childpid);
556 0 : } else if (graph == 3) { /* Hofman graph */
557 0 : if (debug) {
558 0 : sprintf(command, "stripchart -debug %s", mchart_conf);
559 0 : if (!daemon)
560 0 : printf("Spawning graph with %s ...in DEBUG mode \nUse '!' to exit\n",
561 : command);
562 0 : sys_err = system(command);
563 0 : printf("system error return %d \n", sys_err);
564 0 : cm_disconnect_experiment();
565 0 : return 1;
566 :
567 : } else {
568 0 : sprintf(command, "stripchart %s", mchart_conf);
569 0 : if (!daemon)
570 0 : printf("Spawning graph with %s .... \nUse '!' to exit\n", command);
571 0 : ss_exec(command, &childpid);
572 : }
573 :
574 : }
575 :
576 0 : graph = 0;
577 0 : ch = 0;
578 0 : while (ss_kbhit()) {
579 0 : ch = ss_getchar(0);
580 0 : if (ch == -1)
581 0 : ch = getchar();
582 0 : if (ch == 'R')
583 0 : ss_clear_screen();
584 0 : if ((char) ch == '!')
585 0 : break;
586 : }
587 0 : msg = cm_yield(200);
588 :
589 : /* exit this process if no stripchart associated to it */
590 0 : if (!keep_strip && !ss_existpid(childpid))
591 0 : break;
592 :
593 0 : } while (msg != RPC_SHUTDOWN && msg != SS_ABORT && ch != '!');
594 :
595 0 : out:
596 0 : error:
597 0 : printf("\n");
598 :
599 : /* reset terminal */
600 0 : ss_getchar(TRUE);
601 :
602 0 : cm_disconnect_experiment();
603 0 : return 1;
604 : }
|