-
Notifications
You must be signed in to change notification settings - Fork 0
/
genSubr.c
426 lines (404 loc) · 10.7 KB
/
genSubr.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
/* $Id$
* Author: Roger A. Cole
* Date: 03-29-90
*
* Experimental Physics and Industrial Control System (EPICS)
*
* Copyright 1991, the Regents of the University of California,
* and the University of Chicago Board of Governors.
*
* This software was produced under U.S. Government contracts:
* (W-7405-ENG-36) at the Los Alamos National Laboratory,
* and (W-31-109-ENG-38) at Argonne National Laboratory.
*
* Initial development by:
* The Controls and Automation Group (AT-8)
* Ground Test Accelerator
* Accelerator Technology Division
* Los Alamos National Laboratory
*
* Co-developed with
* The Controls and Computing Group
* Accelerator Systems Division
* Advanced Photon Source
* Argonne National Laboratory
*
* Modification Log:
* -----------------
* .00 03-29-90 rac initial version
* .01 06-18-91 rac installed in SCCS
* .02 01-29-92 rac added wildMatch function
* .03 08-11-93 mrk removed ifdef V5_vxWorks
* .04 07-06-94 mrk added ifndef VMS for genShellCommand
*
* make options
* -DvxWorks makes a version for VxWorks
* -DNDEBUG don't compile assert() checking
* -DDEBUG compile various debug code, including checks on
* malloc'd memory
*/
/*+/mod***********************************************************************
* TITLE genSubr.c - some general use routines
*
* DESCRIPTION
* This file contains some routines which are generally useful for
* EPICS programs. Some routines are for SunOS vs. VxWorks
* compatibility.
*
* QUICK REFERENCE
* assert( expression)
* assertAlways( expression)
* char *genMalloc( nBytes)
* void genBufCheck( pBuf)
* void genFree( pBuf)
* void genShellCommand(cmdBuf, resultBuf, resultDim)
* void genSigInit( pHandler)
* int perror( string)
* int wildMatch( string, pattern, ignoreCase)
*
* SEE ALSO
* genDefs.h
*-***************************************************************************/
#include <genDefs.h>
#ifdef vxWorks
# include <vxWorks.h>
# include <stdioLib.h>
# include <taskLib.h>
# include <sigLib.h>
# include <ctype.h>
#else
# include <stdlib.h>
# include <stdio.h>
# include <string.h>
# include <signal.h>
# include <ctype.h>
#endif
/*+/macro*********************************************************************
* NAME assert - check assertion
*
* DESCRIPTION
* Checks to see if an expression is true. If the expression is false,
* an error message is printed and a signal is raised (SIGABRT or, for
* VxWorks, SIGUSR1).
*
* This is actually a macro provided by genDefs.h . If the preprocessor
* symbol NDEBUG is defined, then the expression isn't evaluated or
* checked.
*
* USAGE
* assert(expression);
* assertAlways(expression); (same as assert(), but isn't disabled
* by defining NDEBUG)
*
* RETURNS
* void
*
* NOTES
* 1. Since evaluation of the expression is conditional (depending on
* whether NDEBUG is defined), it is poor practice to use expressions
* which have side effects.
* 2. assertAlways(0) is recommended rather than abort().
*
*-*/
/*----------------------------------------------------------------------------
* assertFail - handle assertion failure
* For SunOS, call abort().
* For VxWorks, try to deliver a SIGUSR1 signal. If that's not
* possible, generate a bus error.
*---------------------------------------------------------------------------*/
int
assertFail(fileName, lineNum)
char *fileName;
int lineNum;
{
(void)fprintf(stderr, "assertFail: in file %s line %d\n",
fileName, lineNum);
#ifdef vxWorks
if (kill(taskIdSelf(), SIGUSR1) == ERROR) {
int *j;
j = (int *)(-1);
j = (int *)(*j);
}
exit(1);
#else
abort();
#endif
return (0);
}
/*+/subr**********************************************************************
* NAME genMalloc - malloc() and free() 'pre-processor' with "guards"
*
* DESCRIPTION
* These routines support catching overwriting a block of memory
* obtained by malloc(). A 'guard' field is added at the beginning
* and end of the block of memory when genMalloc() is called to
* allocate the block. The 'guard' field is checked by genFree().
*
* genMalloc() works the same as malloc(), returning a pointer to
* the 'usable' part of the memory block. (I.e., the guard fields are
* 'hidden' from the caller.)
*
* genFree() works the same as free(), except it checks to see if
* the guard field has been clobbered.
*
* A third routine, genBufCheck() allows checking at arbitrary times
* (even from dbx) on whether a block has been clobbered.
*
*****************************************************************************/
#if 0 /* a simple demonstration of usage */
main()
{
int *x;
int i;
x = (int *)genMalloc(100);
genBufCheck(x);
for (i=0; i<26; i++)
*(x+i) = i;
genFree(x);
exit(0);
}
#endif
# define CHK_MALLOC_FILL_PATTERN 1
/*----------------------------------------------------------------------------
* malloc a block with the following layout, with the block and guard
* fields aligned on longword boundaries
*
* longword 0 nLong for block, including this longword and the
* 'guard' longwords
* longword 1 &longword 0
* user bytes
* longword n &longword 0
*---------------------------------------------------------------------------*/
char *genMalloc(nBytes)
int nBytes;
{
long *ptrL;
int i;
unsigned nLong, sizeC;
nLong = 3 + (nBytes+sizeof(long)-1)/sizeof(long);
sizeC = nLong * sizeof(long);
ptrL = (long *)malloc(sizeC);
if (ptrL != NULL) {
for (i=0; i<sizeC; )
((char *)ptrL)[i++] = CHK_MALLOC_FILL_PATTERN;
*ptrL = nLong;
*(ptrL+1) = *(ptrL+nLong-1) = (long)ptrL;
return (char *)(ptrL+2);
}
return NULL;
}
void genBufCheck(ptr)
void *ptr;
{
long *ptrL;
unsigned nLong;
assert(ptr != NULL);
ptrL = (long *)ptr - 2;
if (*(ptrL+1) != (long)ptrL) {
(void)fprintf(stderr, "genBufCheck: guard at begin clobbered\n");
assertAlways(0);
}
nLong = *ptrL;
if (*(ptrL+nLong-1) != (long)ptrL) {
(void)fprintf(stderr, "genBufCheck: guard at end clobbered\n");
assertAlways(0);
}
}
void genFree(ptr)
void *ptr;
{
long *ptrL;
genBufCheck(ptr);
ptrL = (long *)ptr - 2;
(void)free((char *)ptrL);
return;
}
/*+/subr**********************************************************************
* NAME genShellCommand - issue a command to the "sh" shell
*
* DESCRIPTION
* Issues a command to the Bourne shell, "sh". The text which results
* from executing the command is returned in the buffer supplied by
* the caller.
*
* RETURNS
* void
*
* NOTES
* 1. Any errors which are explicitly detected by this routine result in
* an error message in the caller's result buffer.
* 2. This routine will result in a SIGCHLD signal, which the caller will
* have to handle.
* 3. If no output results from executing the command, then resultBuf[0]
* will be set to '\0'.
*
*-*/
#ifndef vxWorks
#ifndef VMS /* MLR added this */
#ifndef _WIN32
void
genShellCommand(cmdBuf, resultBuf, resultDim)
char *cmdBuf; /* I line to send to shell */
char *resultBuf; /* O buffer to hold result of shell command */
int resultDim; /* I size of result buffer */
{
FILE *shellPipe;
int i;
if ((shellPipe = popen(cmdBuf, "r")) == NULL) {
strcpy(resultBuf, "couldn't issue shell command\n");
return;
}
i = fread(resultBuf, 1, resultDim-1, shellPipe);
resultBuf[i] = '\0';
pclose(shellPipe);
}
#endif
#endif
#endif
/*+/subr**********************************************************************
* NAME genSigInit - initialize for catching signals
*
* DESCRIPTION
* Set up for catching signals.
*
* RETURNS
* void
*
* BUGS
* o it isn't clear how multiple calls fit in with SunOS lwp library
*
* NOTES
* 1. Under VxWorks, assert() generates SIGUSR1, rather than the
* customary UNIX SIGABRT.
*
* EXAMPLE
* #include <setjmp.h>
* #include <signal.h> (or <sigLib.h> for VxWorks)
*
* jmp_buf mySigEnv;
*
* void myHandler(sigNum)
* int sigNum;
* {
* signal(sigNum, SIG_DFL);
* longjmp(mySigEnv, sigNum);
* }
*
* main()
* {
* int sigNum;
*
* genSigInit(myHandler);
* if ((sigNum = setjmp(mySigEnv)) != 0)
* goto sigOccurred;
* .
* .
* exit(0);
* sigOccurred:
* printf("signal %d detected\n", sigNum);
* exit(1);
* }
*
*-*/
void
genSigInit(handler)
void (* handler)(int); /* I pointer to signal handler */
{
(void)signal(SIGTERM, handler); /* SunOS plain kill (not -9) */
#ifndef _WIN32
(void)signal(SIGQUIT, handler); /* SunOS ^\ */
#endif
(void)signal(SIGINT, handler); /* SunOS ^C */
(void)signal(SIGILL, handler); /* illegal instruction */
#ifndef vxWorks
(void)signal(SIGABRT, handler); /* SunOS assert */
#else
(void)signal(SIGUSR1, handler); /* VxWorks assert */
#endif
#ifndef _WIN32
(void)signal(SIGBUS, handler); /* bus error */
#endif
(void)signal(SIGSEGV, handler); /* segmentation violation */
(void)signal(SIGFPE, handler); /* arithmetic exception */
#ifndef _WIN32
(void)signal(SIGPIPE, handler); /* write to disconnected socket */
#endif
}
int doMatch();
/*+/subr**********************************************************************
* NAME wildMatch - do wildcard matching on strings
*
* DESCRIPTION
* Search a text string for a match of a pattern, where the pattern
* can contain wildcard characters.
*
* The wildcard characters and their meanings are:
* ? matches any single character
* * matches any sequence of zero or more characters
*
* RETURNS
* 1 if a match is obtained, or
* 0
*
*-*/
int
wildMatch(text, p, ignoreCase)
char *text; /* I the text to be checked */
char *p; /* I the pattern, possibly with wildcards */
int ignoreCase; /* I 0,1 to honor,ignore upper/lower case differences */
{
char *starP=NULL; /* pointer at beginning of * wildcard */
char *starText=NULL; /* pointer at beginning of * wildcard */
int matched; /* char in text matches char in pattern */
char a, b;
if (*text == '\0')
return 0;
while (*p != '\0' && *text != '\0') {
switch (*p) {
case '*':
starP = ++p;
if (*p == '\0')
return 1;
starText = text;
break;
default:
matched = (*text == *p || *p == '?') ? 1 : 0;
if (ignoreCase && !matched) {
a = *text; b = *p;
if (isascii(a) && isascii(b) && isalpha(a) && isalpha(b)) {
if (isupper(a)) a = tolower(a);
if (isupper(b)) b = tolower(b);
if (a == b)
matched = 1;
}
}
if (matched) {
text++, p++;
if (*p == '\0') {
if (*text == '\0' || *(p-1) == '*')
return 1;
text = ++starText;
if (starP == NULL)
return 0;
p = starP;
}
}
else if (starP == NULL)
return 0;
else {
text = ++starText;
p = starP;
}
break;
}
}
if (*text == '\0') {
if (*p == '\0')
return 1;
if (*p != '*')
return 0;
if (*(++p) == '\0')
return 1;
}
return 0;
}