SDDS ToolKit Programs and Libraries for C and Python
All Classes Files Functions Variables Macros Pages
cavput.cc File Reference

Detailed Description

Write Channel Access (CA) and pvAccess (PVA) Process Variable (PV) values from the command line.

This program uses command-line arguments to perform operations on process variables (PVs) using EPICS Channel Access (CA) or PVAccess (PVA). It supports operations such as specifying lists of PVs, ranges, delta-mode updates, and ramping of values. The program provides extensive configurability and error handling for use in control systems.

Usage

cavput [-list=<string>[=<value>][,<string>[=<value>]...]]
[-range=begin=<integer>,end=<integer>[,format=<string>][,interval=<integer>]]
[-pendIoTime=<seconds>]
[-deltaMode[=factor=<value>]]
[-ramp=step=<n>,pause=<sec>]
[-numerical]
[-charArray]
[-blunderAhead[=silently]]
[-provider={ca|pva}]

Options

Option Description
-list Specifies PV name string components, optionally with values.
-range Specifies a range of integers and format string.
-pendIoTime Maximum time to wait for connections and return values. Default: 1.0s.
-dryRun Shows PV names and values without sending them to IOCs.
-deltaMode Specifies values are deltas from present PV values.
-ramp Ramp to value using steps with pauses.
-numerical Forces value conversion to a number for sending. Default for -deltaMode.
-charArray Use when passing a string to a char array PV.
-blunderAhead Executes all possible puts, even if some PVs don't connect.
-provider Specifies provider; defaults to ca (Channel Access).

Incompatibilities

  • -ramp and -deltaMode require:
    • Scalar data types
License
This file is distributed under the terms of the Software License Agreement found in the file LICENSE included with this distribution.
Authors
  • M. Borland
  • R. Soliday

Definition in file cavput.cc.

#include <complex>
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <unistd.h>
#include <cadef.h>
#include <epicsVersion.h>
#include "mdb.h"
#include "scan.h"
#include "match_string.h"
#include "SDDS.h"
#include "pvMultList.h"

Go to the source code of this file.

Functions

void oag_ca_exception_handler (struct exception_handler_args args)
 
int main (int argc, char **argv)
 

Function Documentation

◆ main()

int main ( int argc,
char ** argv )

Definition at line 148 of file cavput.cc.

148 {
149 int32_t beginRange, endRange, rangeInterval, rampSteps;
150 long dryRun;
151 long PVs, j, i_arg, numerical, iramp;
152 unsigned long blunderAhead;
153 PV_VALUE *PVvalue;
154 TERM_LIST *List;
155 unsigned long flags, dummyFlags;
156 SCANNED_ARG *s_arg;
157 char *ptr, *rangeFormat;
158 double pendIOTime;
159 chid *channelID = NULL;
160 short deltaMode, doRamp, charArray=0;
161 double *presentValue, deltaFactor, rampPause;
162 long providerMode = 0;
163#if (EPICS_VERSION > 3)
164 PVA_OVERALL pva;
165 double *rampDeltas = NULL;
166#endif
167
168 argc = scanargs(&s_arg, argc, argv);
169 if (argc < 2)
170 bomb(NULL, USAGE);
171
172 PVvalue = NULL;
173 presentValue = NULL;
174 List = NULL;
175 PVs = dryRun = 0;
176 pendIOTime = 1.0;
177 deltaMode = numerical = 0;
178 deltaFactor = 1;
179 blunderAhead = 0;
180 rampSteps = 1;
181 rampPause = 0.1;
182 doRamp = 0;
183
184 for (i_arg = 1; i_arg < argc; i_arg++) {
185 if (s_arg[i_arg].arg_type == OPTION) {
186 delete_chars(s_arg[i_arg].list[0], (char *)"_");
187 switch (match_string(s_arg[i_arg].list[0], commandline_option, COMMANDLINE_OPTIONS, 0)) {
188 case CLO_LIST:
189 if (s_arg[i_arg].n_items < 2)
190 SDDS_Bomb((char *)"invalid -list syntax (cavput)");
191 List = (TERM_LIST *)trealloc(List, sizeof(*List) * (s_arg[i_arg].n_items - 1));
192 for (j = 1; j < s_arg[i_arg].n_items; j++) {
193 List[j - 1].flags = 0;
194 if ((ptr = strchr(s_arg[i_arg].list[j], '=')))
195 *ptr++ = 0;
196 List[j - 1].string = s_arg[i_arg].list[j];
197 if (ptr) {
198 List[j - 1].flags |= VALUE_GIVEN;
199 List[j - 1].value = ptr;
200 }
201 }
202 multiplyWithList(&PVvalue, &PVs, List, s_arg[i_arg].n_items - 1);
203 break;
204 case CLO_RANGE:
205 s_arg[i_arg].n_items--;
206 rangeFormat = NULL;
207 rangeInterval = 1;
208 if (!scanItemList(&flags, s_arg[i_arg].list + 1, &s_arg[i_arg].n_items, 0,
209 "begin", SDDS_LONG, &beginRange, 1, BEGIN_GIVEN,
210 "end", SDDS_LONG, &endRange, 1, END_GIVEN,
211 "interval", SDDS_LONG, &rangeInterval, 1, INTERVAL_GIVEN,
212 "format", SDDS_STRING, &rangeFormat, 1, FORMAT_GIVEN,
213 NULL) ||
214 !(flags & BEGIN_GIVEN) || !(flags & END_GIVEN) || beginRange > endRange ||
215 (flags & FORMAT_GIVEN && SDDS_StringIsBlank(rangeFormat)))
216 SDDS_Bomb((char *)"invalid -range syntax/values");
217 if (!rangeFormat)
218 rangeFormat = (char *)"%ld";
219 multiplyWithRange(&PVvalue, &PVs, beginRange, endRange, rangeInterval, rangeFormat);
220 s_arg[i_arg].n_items++;
221 break;
222 case CLO_PENDIOTIME:
223 if (s_arg[i_arg].n_items != 2)
224 bomb((char *)"wrong number of items for -pendIoTime", NULL);
225 if (sscanf(s_arg[i_arg].list[1], "%lf", &pendIOTime) != 1 ||
226 pendIOTime <= 0)
227 SDDS_Bomb((char *)"invalid -pendIoTime value (cavget)");
228 break;
229 case CLO_DRYRUN:
230 dryRun = 1;
231 break;
232 case CLO_EZCATIMING:
233 fprintf(stderr, "warning (cavput): -ezcaTiming option is obsolete. Use -pendIoTime\n");
234 break;
235 case CLO_NOGROUPS:
236 fprintf(stderr, "warning (cavput): -noGroups option is obsolete.\n");
237 break;
238 case CLO_DELTAMODE:
239 deltaMode = 1;
240 s_arg[i_arg].n_items--;
241 if (!scanItemList(&dummyFlags, s_arg[i_arg].list + 1, &s_arg[i_arg].n_items, 0,
242 "factor", SDDS_DOUBLE, &deltaFactor, 1, 0,
243 NULL))
244 SDDS_Bomb((char *)"invalid -deltaMode syntax/values");
245 s_arg[i_arg].n_items++;
246 break;
247 case CLO_NUMERICAL:
248 numerical = 1;
249 break;
250 case CLO_CHARARRAY:
251 charArray = 1;
252 break;
253 case CLO_BLUNDERAHEAD:
254 s_arg[i_arg].n_items--;
255 if (!scanItemList(&blunderAhead, s_arg[i_arg].list + 1, &s_arg[i_arg].n_items, 0,
256 "silently", -1, NULL, 0, BLUNDER_SILENTLY,
257 NULL))
258 SDDS_Bomb((char *)"invalid -blunderAhead syntax/values");
259 blunderAhead |= DO_BLUNDERAHEAD;
260 s_arg[i_arg].n_items++;
261 break;
262 case CLO_RAMP:
263 s_arg[i_arg].n_items--;
264 rangeFormat = NULL;
265 rangeInterval = 1;
266 if (!scanItemList(&flags, s_arg[i_arg].list + 1, &s_arg[i_arg].n_items, 0,
267 "steps", SDDS_LONG, &rampSteps, 1, 0,
268 "pause", SDDS_DOUBLE, &rampPause, 1, 0, NULL) ||
269 (rampSteps <= 1) || (rampPause < 0))
270 SDDS_Bomb((char *)"invalid -ramp syntax/values");
271 doRamp = 1;
272 s_arg[i_arg].n_items++;
273 break;
274 case CLO_PROVIDER:
275 if (s_arg[i_arg].n_items != 2)
276 SDDS_Bomb((char *)"no value given for option -provider");
277 if ((providerMode = match_string(s_arg[i_arg].list[1], providerOption,
278 PROVIDER_COUNT, 0)) < 0)
279 SDDS_Bomb((char *)"invalid -provider");
280 break;
281 default:
282 bomb((char *)"unknown option (cavput)", NULL);
283 break;
284 }
285 } else
286 bomb((char *)"unknown option", NULL);
287 }
288
289 for (j = 0; j < PVs; j++)
290 if (!PVvalue[j].value) {
291 fprintf(stderr, "Error: no value given for %s\n", PVvalue[j].name);
292 exit(EXIT_FAILURE);
293 }
294
295 if (dryRun) {
296 for (j = 0; j < PVs; j++) {
297 if (strncmp(PVvalue[j].name, "pva://", 6) == 0) {
298 PVvalue[j].name += 6;
299 printf("%32s %s\n", PVvalue[j].name, PVvalue[j].value);
300 PVvalue[j].name -= 6;
301 } else if (strncmp(PVvalue[j].name, "ca://", 5) == 0) {
302 PVvalue[j].name += 5;
303 printf("%32s %s\n", PVvalue[j].name, PVvalue[j].value);
304 PVvalue[j].name -= 5;
305 } else {
306 printf("%32s %s\n", PVvalue[j].name, PVvalue[j].value);
307 }
308 }
309 } else {
310#if (EPICS_VERSION > 3)
311 //Allocate memory for pva structure
312 allocPVA(&pva, PVs, 0);
313 //List PV names
314 epics::pvData::shared_vector<std::string> names(pva.numPVs);
315 epics::pvData::shared_vector<std::string> provider(pva.numPVs);
316 for (j = 0; j < pva.numPVs; j++) {
317 if (strncmp(PVvalue[j].name, "pva://", 6) == 0) {
318 PVvalue[j].name += 6;
319 names[j] = PVvalue[j].name;
320 PVvalue[j].name -= 6;
321 provider[j] = "pva";
322 } else if (strncmp(PVvalue[j].name, "ca://", 5) == 0) {
323 PVvalue[j].name += 5;
324 names[j] = PVvalue[j].name;
325 PVvalue[j].name -= 5;
326 provider[j] = "ca";
327 } else {
328 names[j] = PVvalue[j].name;
329 if (providerMode == PROVIDER_PVA) {
330 provider[j] = "pva";
331 } else {
332 provider[j] = "ca";
333 }
334 }
335 }
336 pva.pvaChannelNames = freeze(names);
337 pva.pvaProvider = freeze(provider);
338 //Connect to PVs
339 ConnectPVA(&pva, pendIOTime);
340
341 for (j = 0; j < PVs; j++) {
342 if (!pva.isConnected[j]) {
343 if (!(blunderAhead & BLUNDER_SILENTLY))
344 fprintf(stderr, "Channel not connected: %s\n", PVvalue[j].name);
345 if (!blunderAhead && (doRamp || deltaMode))
346 exit(EXIT_FAILURE);
347 continue;
348 }
349 }
350 //Is there a way to check write access rights? If so, add it here.
351
352 //Get the current values. This is mostly done to prepopulate the PVstructure which makes it easier to change the values later.
353 if (GetPVAValues(&pva) == 1) {
354 return (EXIT_FAILURE);
355 }
356
357 //Do not allow ramp or delta modes for non-scalar data
358 if (doRamp || deltaMode) {
359 for (j = 0; j < PVs; j++) {
360 if (pva.isConnected[j]) {
361 if (pva.pvaData[j].fieldType != epics::pvData::scalar) {
362 fprintf(stderr, "error (cavput): %s is not a scalar type PV, delta and ramp options are only available for scalar type PVs\n", PVvalue[j].name);
363 return (EXIT_FAILURE);
364 }
365 }
366 }
367 }
368 //Extract PV values given on the commandline and place them in the pva data structure
369 if (PrepPVAPutValues(&pva, PVvalue, charArray)) {
370 return (EXIT_FAILURE);
371 }
372
373 //Modify the put value because if it was a delta value
374 if (deltaMode) {
375 for (j = 0; j < PVs; j++) {
376 if (pva.isConnected[j] && (pva.pvaData[j].fieldType == epics::pvData::scalar) && pva.pvaData[j].numeric) {
377 pva.pvaData[j].putData[0].values[0] = pva.pvaData[j].putData[0].values[0] * deltaFactor + pva.pvaData[j].getData[0].values[0];
378 }
379 }
380 }
381
382 if (doRamp) {
383 double *fValues;
384 //Calculate ramp step sizes
385 rampDeltas = (double *)malloc(sizeof(double) * PVs);
386 fValues = (double *)malloc(sizeof(double) * PVs);
387 for (j = 0; j < PVs; j++) {
388 if (pva.isConnected[j] && (pva.pvaData[j].fieldType == epics::pvData::scalar) && pva.pvaData[j].numeric) {
389 fValues[j] = pva.pvaData[j].putData[0].values[0];
390 rampDeltas[j] = (pva.pvaData[j].putData[0].values[0] - pva.pvaData[j].getData[0].values[0]) / rampSteps;
391 pva.pvaData[j].putData[0].values[0] = pva.pvaData[j].getData[0].values[0];
392 }
393 }
394 //Put ramp values
395 for (iramp = 1; iramp <= rampSteps; iramp++) {
396 for (j = 0; j < PVs; j++) {
397 if (pva.isConnected[j] && (pva.pvaData[j].fieldType == epics::pvData::scalar) && pva.pvaData[j].numeric) {
398 if (iramp == rampSteps) {
399 pva.pvaData[j].putData[0].values[0] = fValues[j];
400 } else {
401 pva.pvaData[j].putData[0].values[0] = pva.pvaData[j].putData[0].values[0] + rampDeltas[j];
402 }
403 pva.pvaData[j].numPutElements = 1;
404 }
405 }
406 if (PutPVAValues(&pva) == 1) {
407 return (EXIT_FAILURE);
408 }
409 if ((rampPause > 0) && (iramp < rampSteps)) {
410 usleepSystemIndependent(rampPause * 1000000);
411 }
412 }
413 free(rampDeltas);
414 } else {
415 //Put values
416 if (PutPVAValues(&pva) == 1) {
417 return (EXIT_FAILURE);
418 }
419 }
420 //Free memory and exit
421 if (PVvalue) {
422 for (j = 0; j < PVs; j++) {
423 if (PVvalue[j].name)
424 free(PVvalue[j].name);
425 if (PVvalue[j].value)
426 free(PVvalue[j].value);
427 }
428 free(PVvalue);
429 }
430 freePVA(&pva);
431 if (List)
432 free(List);
433 free_scanargs(&s_arg, argc);
434 return (EXIT_SUCCESS);
435#else
436 ca_task_initialize();
437 ca_add_exception_event(oag_ca_exception_handler, NULL);
438 if (!(channelID = (chid *)malloc(sizeof(*channelID) * PVs)))
439 bomb((char *)"memory allocation failure (cavput)", NULL);
440 for (j = 0; j < PVs; j++) {
441 if (ca_search(PVvalue[j].name, channelID + j) != ECA_NORMAL) {
442 fprintf(stderr, "error (cavput): problem doing search for %s\n",
443 PVvalue[j].name);
444 ca_task_exit();
445 exit(EXIT_FAILURE);
446 }
447#ifdef DEBUG
448 fprintf(stderr, "ca_search initiated for %s\n", PVvalue[j].name);
449#endif
450 }
451 ca_pend_io(pendIOTime);
452#ifdef DEBUG
453 fprintf(stderr, "ca_pend_io returned\n");
454#endif
455 if (doRamp || deltaMode) {
456 for (j = 0; j < PVs; j++) {
457 if (ca_state(channelID[j]) != cs_conn) {
458 if (!(blunderAhead & BLUNDER_SILENTLY))
459 fprintf(stderr, "error (cavput): no connection for %s\n",
460 PVvalue[j].name);
461 if (!blunderAhead) {
462 ca_task_exit();
463 exit(EXIT_FAILURE);
464 }
465 }
466 }
467 if (!(presentValue = (double *)malloc(sizeof(*presentValue) * PVs))) {
468 fprintf(stderr, "error (cavput): memory allocation failure\n");
469 ca_task_exit();
470 exit(EXIT_FAILURE);
471 }
472 for (j = 0; j < PVs; j++) {
473 presentValue[j] = DBL_MAX;
474 if (ca_state(channelID[j]) != cs_conn)
475 continue;
476 if (ca_get(DBR_DOUBLE, channelID[j], presentValue + j) != ECA_NORMAL) {
477 fprintf(stderr, "error (cavput): problem doing get for %s\n",
478 PVvalue[j].name);
479 ca_task_exit();
480 exit(EXIT_FAILURE);
481 }
482 }
483 ca_pend_io(pendIOTime);
484 for (j = 0; j < PVs; j++) {
485 if (ca_state(channelID[j]) != cs_conn)
486 continue;
487 if (presentValue[j] == DBL_MAX) {
488 fprintf(stderr, "error (cavput): no value returned in time for %s\n",
489 PVvalue[j].name);
490 ca_task_exit();
491 exit(EXIT_FAILURE);
492 }
493 if (sscanf(PVvalue[j].value, "%le", &PVvalue[j].numericalValue) != 1) {
494 fprintf(stderr, "error (cavput): value (%s) for %s is not numerical--can't use -deltaMode or -ramp\n",
495 PVvalue[j].value, PVvalue[j].name);
496 ca_task_exit();
497 exit(EXIT_FAILURE);
498 }
499 }
500 numerical = 1;
501 }
502 if (deltaMode) {
503 for (j = 0; j < PVs; j++) {
504 PVvalue[j].numericalValue = PVvalue[j].numericalValue * deltaFactor + presentValue[j];
505 }
506 }
507 if (!doRamp) {
508#ifdef DEBUG
509 fprintf(stderr, "doing non-ramped puts\n");
510#endif
511 for (j = 0; j < PVs; j++) {
512 if (ca_state(channelID[j]) != cs_conn) {
513 if (!(blunderAhead & BLUNDER_SILENTLY))
514 fprintf(stderr, "Channel not connected: %s\n", PVvalue[j].name);
515 continue;
516 }
517#ifdef DEBUG
518 fprintf(stderr, "%s is connected\n", PVvalue[j].name);
519#endif
520 if (ca_write_access(channelID[j]) == 0) {
521 fprintf(stderr, "Write access denied on : %s\n", PVvalue[j].name);
522 }
523 if (!numerical) {
524 if (ca_put(DBR_STRING, channelID[j], PVvalue[j].value) != ECA_NORMAL) {
525 if (!(blunderAhead & BLUNDER_SILENTLY))
526 fprintf(stderr, "error (cavput): problem doing put for %s\n",
527 PVvalue[j].name);
528 if (!blunderAhead) {
529 ca_task_exit();
530 exit(EXIT_FAILURE);
531 }
532 }
533#ifdef DEBUG
534 fprintf(stderr, "ca_put of %s for %s done\n", PVvalue[j].value, PVvalue[j].name);
535#endif
536 } else {
537 if (!deltaMode) {
538 if (sscanf(PVvalue[j].value, "%le", &PVvalue[j].numericalValue) != 1) {
539 fprintf(stderr,
540 "error (cavput): value (%s) for %s is not scannable as a number---can't use -numerical.\n",
541 PVvalue[j].value, PVvalue[j].name);
542 ca_task_exit();
543 exit(EXIT_FAILURE);
544 }
545 }
546 if (ca_put(DBR_DOUBLE, channelID[j], &PVvalue[j].numericalValue) != ECA_NORMAL) {
547 if (!(blunderAhead & BLUNDER_SILENTLY))
548 fprintf(stderr, "error (cavput): problem doing put for %s\n",
549 PVvalue[j].name);
550 if (!blunderAhead) {
551 ca_task_exit();
552 exit(EXIT_FAILURE);
553 }
554 }
555#ifdef DEBUG
556 fprintf(stderr, "ca_put of %f for %s done\n", PVvalue[j].numericalValue, PVvalue[j].name);
557#endif
558 }
559 }
560 } else {
561 /*do ramp */
562 for (iramp = 0; iramp < rampSteps; iramp++) {
563 for (j = 0; j < PVs; j++) {
564 rampDelta = (PVvalue[j].numericalValue - presentValue[j]) / rampSteps;
565 rampValue = presentValue[j] + (iramp + 1) * rampDelta;
566 if (ca_put(DBR_DOUBLE, channelID[j], &rampValue) != ECA_NORMAL) {
567 if (!(blunderAhead & BLUNDER_SILENTLY))
568 fprintf(stderr, "error (cavput): problem doing put for %s\n",
569 PVvalue[j].name);
570 if (!blunderAhead) {
571 ca_task_exit();
572 exit(EXIT_FAILURE);
573 }
574 }
575 }
576 if ((status = ca_pend_io(pendIOTime)) != ECA_NORMAL) {
577 fprintf(stderr, "Problem processing one or more puts (cavput):\n%s\n",
578 ca_message(status));
579 ca_task_exit();
580 exit(EXIT_FAILURE);
581 }
582 if (rampPause > 0) {
583 ca_pend_event(rampPause);
584 } else {
585 ca_poll();
586 }
587 }
588 }
589
590 if ((status = ca_pend_io(pendIOTime)) != ECA_NORMAL) {
591 fprintf(stderr, "Problem processing one or more puts (cavput):\n%s\n",
592 ca_message(status));
593 ca_task_exit();
594 exit(EXIT_FAILURE);
595 }
596 ca_pend_event(0.5);
597#ifdef DEBUG
598 fprintf(stderr, "ca_pend_io returned\n");
599#endif
600
601 ca_task_exit();
602#ifdef DEBUG
603 fprintf(stderr, "ca_task_exit returned\n");
604#endif
605
606#endif
607 }
608
609#ifdef DEBUG
610 fprintf(stderr, "starting to free memory\n");
611#endif
612
613 if (channelID)
614 free(channelID);
615#ifdef DEBUG
616 fprintf(stderr, "free'd channelID\n");
617#endif
618
619 for (j = 0; j < PVs; j++) {
620 if (PVvalue[j].name)
621 free(PVvalue[j].name);
622 /* if (PVvalue[j].value) free(PVvalue[j].value); THIS CAUSES PROBLEMS*/
623 PVvalue[j].name = PVvalue[j].value = NULL;
624 }
625 free(PVvalue);
626#ifdef DEBUG
627 fprintf(stderr, "free'd PVvalue lists\n");
628#endif
629
630 if (presentValue)
631 free(presentValue);
632
633 free_scanargs(&s_arg, argc);
634#ifdef DEBUG
635 fprintf(stderr, "free_scanargs returned\n");
636#endif
637
638 if (List)
639 free(List);
640#ifdef DEBUG
641 fprintf(stderr, "free'd List\n");
642#endif
643
644#ifdef DEBUG
645 fprintf(stderr, "exiting main routine\n");
646#endif
647
648 return (EXIT_SUCCESS);
649}
int32_t SDDS_StringIsBlank(char *s)
Checks if a string is blank (contains only whitespace characters).
void SDDS_Bomb(char *message)
Terminates the program after printing an error message and recorded errors.
Definition SDDS_utils.c:342
#define SDDS_STRING
Identifier for the string data type.
Definition SDDStypes.h:85
#define SDDS_LONG
Identifier for the signed 32-bit integer data type.
Definition SDDStypes.h:61
#define SDDS_DOUBLE
Identifier for the double data type.
Definition SDDStypes.h:37
void * trealloc(void *old_ptr, uint64_t size_of_block)
Reallocates a memory block to a new size.
Definition array.c:181
void bomb(char *error, char *usage)
Reports error messages to the terminal and aborts the program.
Definition bomb.c:26
char * delete_chars(char *s, char *t)
Removes all occurrences of characters found in string t from string s.
void usleepSystemIndependent(long usec)
Sleep for a given number of microseconds, system-independently.
long match_string(char *string, char **option, long n_options, long mode)
Matches a given string against an array of option strings based on specified modes.
int scanargs(SCANNED_ARG **scanned, int argc, char **argv)
Definition scanargs.c:36
void free_scanargs(SCANNED_ARG **scanned, int argc)
Definition scanargs.c:584
long scanItemList(unsigned long *flags, char **item, long *items, unsigned long mode,...)
Scans a list of items and assigns values based on provided keywords and types.

◆ oag_ca_exception_handler()

void oag_ca_exception_handler ( struct exception_handler_args args)

Definition at line 651 of file cavput.cc.

651 {
652 char *pName;
653 int severityInt;
654 static const char *severity[] =
655 {
656 "Warning",
657 "Success",
658 "Error",
659 "Info",
660 "Fatal",
661 "Fatal",
662 "Fatal",
663 "Fatal"};
664
665 severityInt = CA_EXTRACT_SEVERITY(args.stat);
666
667 if ((severityInt != 1) && (severityInt != 3)) {
668 fprintf(stderr, "CA.Client.Exception................\n");
669 fprintf(stderr, " %s: \"%s\"\n",
670 severity[severityInt],
671 ca_message(args.stat));
672
673 if (args.ctx) {
674 fprintf(stderr, " Context: \"%s\"\n", args.ctx);
675 }
676 if (args.chid) {
677 pName = (char *)ca_name(args.chid);
678 fprintf(stderr, " Channel: \"%s\"\n", pName);
679 fprintf(stderr, " Type: \"%s\"\n", dbr_type_to_text(args.type));
680 }
681 fprintf(stderr, "This sometimes indicates an IOC that is hung up.\n");
682 _exit(EXIT_FAILURE);
683 } else {
684 fprintf(stdout, "CA.Client.Exception................\n");
685 fprintf(stdout, " %s: \"%s\"\n",
686 severity[severityInt],
687 ca_message(args.stat));
688
689 if (args.ctx) {
690 fprintf(stdout, " Context: \"%s\"\n", args.ctx);
691 }
692 if (args.chid) {
693 pName = (char *)ca_name(args.chid);
694 fprintf(stdout, " Channel: \"%s\"\n", pName);
695 fprintf(stdout, " Type: \"%s\"\n", dbr_type_to_text(args.type));
696 }
697 }
698}