Subversion Repositories tendra.SVN

Rev

Rev 2 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

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