Subversion Repositories tendra.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 7u83 1
/*
2
    		 Crown Copyright (c) 1997
3
 
4
    This TenDRA(r) Computer Program is subject to Copyright
5
    owned by the United Kingdom Secretary of State for Defence
6
    acting through the Defence Evaluation and Research Agency
7
    (DERA).  It is made available to Recipients with a
8
    royalty-free licence for its use, reproduction, transfer
9
    to other parties and amendment for any purpose not excluding
10
    product development provided that any such use et cetera
11
    shall be deemed to be acceptance of the following conditions:-
12
 
13
        (1) Its Recipients shall ensure that this Notice is
14
        reproduced upon any copies or amended versions of it;
15
 
16
        (2) Any amended version of it shall be clearly marked to
17
        show both the nature of and the organisation responsible
18
        for the relevant amendment or amendments;
19
 
20
        (3) Its onward transfer from a recipient to another
21
        party shall be deemed to be that party's acceptance of
22
        these conditions;
23
 
24
        (4) DERA gives no warranty or assurance as to its
25
        quality or suitability for any purpose and DERA accepts
26
        no liability whatsoever in relation to any use to which
27
        it may be put.
28
*/
29
 
30
 
31
#include "config.h"
32
#if FS_STDARG
33
#include <stdarg.h>
34
#else
35
#include <varargs.h>
36
#endif
37
#include <sys/types.h>
38
#include <errno.h>
39
#include <sys/stat.h>
40
#include "name.h"
41
#include "utility.h"
42
 
43
#ifdef FS_NO_MODE_T
44
typedef unsigned short mode_t ;
45
#endif
46
 
47
#ifndef errno
48
extern int errno ;
49
#endif
50
 
51
 
52
/*
53
    INPUT BUFFER
54
 
55
    This buffer is used to store strings in various contexts.
56
*/
57
 
58
char *buffer = null ;
59
 
60
 
61
/*
62
    ERROR VARIABLES
63
 
64
    The value exit_status gives the overall status of the program.  It
65
    can be EXIT_SUCCESS or EXIT_FAILURE.  The variable progname gives
66
    the name of the program, which is used in error reports.  filename
67
    and line_no give the current file position.
68
*/
69
 
70
int exit_status = EXIT_SUCCESS ;
71
int no_errors = 0 ;
72
int warnings = 1 ;
73
char *progname = "tspec" ;
74
char *progvers = "2.8" ;
75
time_t progdate = 0 ;
76
char *filename = null ;
77
int line_no = 1 ;
78
 
79
 
80
/*
81
    PRINT AN ERROR MESSAGE
82
 
83
    This routine prints an error message s (a printf-style string,
84
    which may be followed by any number of arguments) of severity e
85
    (see utility.h).
86
*/
87
 
88
void error
89
    PROTO_V ( ( int e, char *s, ... ) ) /* VARARGS */
90
{
91
    va_list args ;
92
    char *errtype = null ;
93
    boolean show_line = 1 ;
94
#if FS_STDARG
95
    va_start ( args, s ) ;
96
#else
97
    int e ;
98
    char *s ;
99
    va_start ( args ) ;
100
    e = va_arg ( args, int ) ;
101
    s = va_arg ( args, char * ) ;
102
#endif
103
    switch ( e ) {
104
	case ERR_FATAL : {
105
	    exit_status = EXIT_FAILURE ;
106
	    errtype = "Fatal" ;
107
	    no_errors++ ;
108
	    break ;
109
	}
110
	case ERR_INTERNAL : {
111
	    exit_status = EXIT_FAILURE ;
112
	    errtype = "Internal" ;
113
	    no_errors++ ;
114
	    break ;
115
	}
116
	case ERR_SERIOUS : {
117
	    exit_status = EXIT_FAILURE ;
118
	    errtype = "Error" ;
119
	    no_errors++ ;
120
	    break ;
121
	}
122
	case ERR_WARNING : {
123
	    if ( !warnings ) {
124
		va_end ( args ) ;
125
		return ;
126
	    }
127
	    errtype = "Warning" ;
128
	    break ;
129
	}
130
	case ERR_INFO : {
131
	    errtype = "Info" ;
132
	    show_line = 0 ;
133
	    break ;
134
	}
135
    }
136
    if ( progname ) IGNORE fprintf ( stderr, "%s: ", progname ) ;
137
    if ( errtype ) IGNORE fprintf ( stderr, "%s: ", errtype ) ;
138
    IGNORE vfprintf ( stderr, s, args ) ;
139
    if ( filename && show_line ) {
140
	IGNORE fprintf ( stderr, ", %s, line %d", filename, line_no ) ;
141
    }
142
    IGNORE fprintf ( stderr, ".\n" ) ;
143
    va_end ( args ) ;
144
    if ( e == ERR_FATAL ) exit ( exit_status ) ;
145
    return ;
146
}
147
 
148
 
149
/*
150
    ALLOCATE A BLOCK OF MEMORY
151
 
152
    This routine allocates a block of memory of size sz and returns
153
    the result.
154
*/
155
 
156
pointer xalloc
157
    PROTO_N ( ( sz ) )
158
    PROTO_T ( int sz )
159
{
160
    pointer p = ( pointer ) malloc ( ( size_t ) sz ) ;
161
    if ( p == null ) error ( ERR_FATAL, "Memory allocation error" ) ;
162
    return ( p ) ;
163
}
164
 
165
 
166
/*
167
    REALLOCATE A BLOCK OF MEMORY
168
 
169
    This routine reallocates the block of memory p to have size sz.
170
    xrealloc ( null, sz ) is equivalent to xalloc ( sz ).
171
 
172
*/
173
 
174
pointer xrealloc
175
    PROTO_N ( ( p, sz ) )
176
    PROTO_T ( pointer p X int sz )
177
{
178
    pointer q ;
179
    if ( p == null ) return ( xalloc ( sz ) ) ;
180
    q = ( pointer ) realloc ( p, ( size_t ) sz ) ;
181
    if ( q == null ) error ( ERR_FATAL, "Memory reallocation error" ) ;
182
    return ( q ) ;
183
}
184
 
185
 
186
/*
187
    ALLOCATE SPACE FOR A STRING
188
 
189
    This routine allocates space for a string of size n.
190
*/
191
 
192
static char *string_alloc
193
    PROTO_N ( ( n ) )
194
    PROTO_T ( int n )
195
{
196
    char *r ;
197
    if ( n >= 1000 ) {
198
	/* Long strings are allocated space by alloc_nof */
199
	r = alloc_nof ( char, n ) ;
200
    } else {
201
	/* Short strings are allocated space from a buffer */
202
	static int no_free = 0 ;
203
	static char *free_chars = null ;
204
	if ( n >= no_free ) {
205
	    no_free = 1000 ;
206
	    free_chars = alloc_nof ( char, no_free ) ;
207
	}
208
	r = free_chars ;
209
	no_free -= n ;
210
	free_chars += n ;
211
    }
212
    return ( r ) ;
213
}
214
 
215
 
216
/*
217
    COPY A STRING
218
 
219
    This routine allocates space for a copy of the string s and copies
220
    the string into this space.  This copy is returned.
221
*/
222
 
223
char *string_copy
224
    PROTO_N ( ( s ) )
225
    PROTO_T ( char *s )
226
{
227
    int n = ( int ) strlen ( s ) ;
228
    char *r = string_alloc ( n + 1 ) ;
229
    IGNORE strcpy ( r, s ) ;
230
    return ( r ) ;
231
}
232
 
233
 
234
/*
235
    CONCATENCATE TWO STRINGS
236
 
237
    This routine allocates space for the concatenation of the strings
238
    s and t.
239
*/
240
 
241
char *string_concat
242
    PROTO_N ( ( s, t ) )
243
    PROTO_T ( char *s X char *t )
244
{
245
    int n = ( int ) strlen ( s ) ;
246
    int m = ( int ) strlen ( t ) ;
247
    char *r = string_alloc ( n + m + 1 ) ;
248
    IGNORE strcpy ( r, s ) ;
249
    IGNORE strcpy ( r + n, t ) ;
250
    return ( r ) ;
251
}
252
 
253
 
254
/*
255
    CONSTRUCT A STRING
256
 
257
    This routine takes a printf string and a list of arguments, and
258
    does a sprintf into a permanent area of memory.
259
*/
260
 
261
char *string_printf
262
    PROTO_V ( ( char *s, ... ) ) /* VARARGS */
263
{
264
    va_list args ;
265
#if FS_STDARG
266
    va_start ( args, s ) ;
267
#else
268
    char *s ;
269
    va_start ( args ) ;
270
    s = va_arg ( args, char * ) ;
271
#endif
272
    IGNORE vsprintf ( buffer, s, args ) ;
273
    va_end ( args ) ;
274
    return ( string_copy ( buffer ) ) ;
275
}
276
 
277
 
278
/*
279
    MODE OF DIRECTORIES CREATED
280
 
281
    The mode of any created directories is determined.  On a truly POSIX
282
    compliant machine, the first branch is taken.
283
*/
284
 
285
#if defined ( S_IRWXU ) && defined ( S_IRWXG ) && defined ( S_IRWXO )
286
#define  DIRMODE	( S_IRWXU | S_IRWXG | S_IRWXO )
287
#else
288
#if defined ( S_IREAD ) && defined ( S_IWRITE ) && defined ( S_IEXEC )
289
#define  DIRMODE	( S_IREAD | S_IWRITE | S_IEXEC )
290
#else
291
#define  DIRMODE	0777
292
#endif
293
#endif
294
 
295
 
296
/*
297
    CREATE A DIRECTORY TO PUT A FILE IN
298
 
299
    This routine recursively creates a directory to contain a file
300
    named nm.
301
*/
302
 
303
void create_dir
304
    PROTO_N ( ( nm ) )
305
    PROTO_T ( char *nm )
306
{
307
    struct stat st ;
308
    char *dir = dirname ( nm ) ;
309
    if ( dir == null ) return ;
310
    if ( stat ( dir, &st ) == 0 ) return ;
311
#ifdef ENOENT
312
    if ( errno != ENOENT ) {
313
	error ( ERR_SERIOUS, "Illegal directory, %s", dir ) ;
314
	return ;
315
    }
316
#endif
317
    create_dir ( dir ) ;
318
    if ( verbose ) error ( ERR_INFO, "Creating directory, %s ...", dir ) ;
319
    if ( mkdir ( dir, ( mode_t ) DIRMODE ) ) {
320
	error ( ERR_SERIOUS, "Can't create directory, %s", dir ) ;
321
	return ;
322
    }
323
    return ;
324
}
325
 
326
 
327
/*
328
    CHECK A FILENAME
329
 
330
    This routine checks the file name nm for excessively long components,
331
    which may cause problems on some machines.
332
*/
333
 
334
void check_name
335
    PROTO_N ( ( nm ) )
336
    PROTO_T ( char *nm )
337
{
338
    char *p ;
339
    int i = 0, n = 0 ;
340
    for ( p = nm ; *p ; p++ ) {
341
	if ( *p == '/' ) {
342
	    if ( i > n ) n = i ;
343
	    i = 0 ;
344
	} else {
345
	    i++ ;
346
	}
347
    }
348
    if ( i > n ) n = i ;
349
    if ( n > 14 ) {
350
	char *err = "The filename %s contains a component of length %d" ;
351
	error ( ERR_WARNING, err, nm, n ) ;
352
    }
353
    return ;
354
}
355
 
356
 
357
/*
358
    FIND THE DATE STAMP ON A FILE
359
 
360
    This routine finds the modification time of the file nm.  Zero is
361
    returned for inaccessible files.
362
*/
363
 
364
time_t date_stamp
365
    PROTO_N ( ( nm ) )
366
    PROTO_T ( char *nm )
367
{
368
    struct stat st ;
369
    if ( nm && stat ( nm, &st ) == 0 ) return ( st.st_mtime ) ;
370
    return ( ( time_t ) 0 ) ;
371
}