996
|
1 /*
|
|
2 * uncommon.c -- functions used by ick, convickt, yuk and compiled programs
|
|
3 *
|
|
4 LICENSE TERMS
|
|
5 Copyright (C) 2007 Alex Smith
|
|
6
|
|
7 This program is free software; you can redistribute it and/or modify
|
|
8 it under the terms of the GNU General Public License as published by
|
|
9 the Free Software Foundation; either version 2 of the License, or
|
|
10 (at your option) any later version.
|
|
11
|
|
12 This program is distributed in the hope that it will be useful,
|
|
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
15 GNU General Public License for more details.
|
|
16
|
|
17 You should have received a copy of the GNU General Public License
|
|
18 along with this program; if not, write to the Free Software
|
|
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
20 */
|
|
21
|
|
22 #include <stdio.h>
|
|
23 #include <string.h>
|
|
24 #include <stdarg.h>
|
|
25 #include <ick_lose.h>
|
|
26 #include "uncommon.h"
|
|
27
|
|
28 /* Options that might affect this */
|
|
29 int ick_printfopens=0;
|
|
30
|
|
31 /*@dependent@*/ /*@null@*/ FILE* ick_debfopen(/*@observer@*/ const char* fname,
|
|
32 /*@observer@*/ const char* mode)
|
|
33 {
|
|
34 FILE* t;
|
|
35 if(ick_printfopens) fprintf(stderr,"Trying to open '%s'...\n",fname);
|
|
36 t=fopen(fname,mode);
|
|
37 if(ick_printfopens && t != NULL) fprintf(stderr,"Success!\n");
|
|
38 if(ick_printfopens && t == NULL) fprintf(stderr,"Failed!\n");
|
|
39 return t;
|
|
40 }
|
|
41
|
|
42 /* This function looks for the skeleton and syslib, searching first the
|
|
43 path they should be in, then the current directory, then argv[0]'s
|
|
44 directory (if one was given). This function avoids possible buffer
|
|
45 overflows, instead truncating filenames (and if that manages to find them,
|
|
46 I'll be incredibly surprised). It also tries argv[0]/../lib and
|
|
47 argv[0]/../include (where they are when running without installing). */
|
|
48 /*@dependent@*/ /*@null@*/ FILE* ick_findandfopen(/*@observer@*/ const char* file,
|
|
49 /*@observer@*/ const char* guessdir,
|
|
50 /*@observer@*/ const char* mode,
|
|
51 /*@observer@*/ const char* argv0)
|
|
52 {
|
|
53 static char buf2[BUFSIZ];
|
|
54 /*@observer@*/ static const char *fileiter;
|
|
55 size_t i = 0, j;
|
|
56 FILE* ret;
|
|
57 while(*guessdir != '\0' && i<BUFSIZ-2) buf2[i++] = *guessdir++;
|
|
58 buf2[i++] = '/';
|
|
59 fileiter = file;
|
|
60 while(*fileiter != '\0' && i<BUFSIZ-1) buf2[i++] = *fileiter++;
|
|
61 buf2[i] = '\0';
|
|
62 ret = ick_debfopen(buf2,mode); /* where it ought to be */
|
|
63 if(ret) return ret;
|
|
64 ret = ick_debfopen(file,mode); /* current dir */
|
|
65 if(ret) return ret;
|
|
66 if(!strchr(argv0,'/')&&
|
|
67 !strchr(argv0,'\\')) return NULL; /* argv[0] has no dir specified */
|
|
68 i = j = 0;
|
|
69 while(*argv0 != '\0' && i<BUFSIZ-2)
|
|
70 {
|
|
71 buf2[i++] = *argv0++;
|
|
72 if(*argv0=='/') j = i;
|
|
73 if(*argv0=='\\') j = i;
|
|
74 }
|
|
75 i = j + 1;
|
|
76 fileiter=file;
|
|
77 while(*fileiter != '\0' && i<BUFSIZ-1) buf2[i++] = *fileiter++;
|
|
78 buf2[i] = '\0';
|
|
79 ret = ick_debfopen(buf2,mode); /* argv[0]'s dir */
|
|
80 if(ret) return ret;
|
|
81 i = j + 1;
|
|
82 fileiter="../lib/"; /* correct for POSIX and DJGPP */
|
|
83 while(*fileiter != '\0' && i<BUFSIZ-1) buf2[i++] = *fileiter++;
|
|
84 fileiter=file;
|
|
85 while(*fileiter != '\0' && i<BUFSIZ-1) buf2[i++] = *fileiter++;
|
|
86 buf2[i]='\0';
|
|
87 ret = ick_debfopen(buf2,mode); /* argv[0]/../lib/ */
|
|
88 if(ret) return ret;
|
|
89 i = j + 1;
|
|
90 fileiter="../include/"; /* correct for POSIX and DJGPP */
|
|
91 while(*fileiter != '\0' && i<BUFSIZ-1) buf2[i++] = *fileiter++;
|
|
92 fileiter=file;
|
|
93 while(*fileiter != '\0' && i<BUFSIZ-1) buf2[i++] = *fileiter++;
|
|
94 buf2[i]='\0';
|
|
95 ret = ick_debfopen(buf2,mode); /* argv[0]/../include/ */
|
|
96 if(ret) return ret;
|
|
97 return NULL; /* just return 0 if even this failed */
|
|
98 }
|
|
99
|
|
100 /* AIS: The same, looking for an executable */
|
|
101 /*@observer@*/ /*@null@*/ const char* ick_findandtestopen(/*@observer@*/ const char* file,
|
|
102 /*@observer@*/ const char* guessdir,
|
|
103 /*@observer@*/ const char* mode,
|
|
104 /*@observer@*/ const char* argv0)
|
|
105 {
|
|
106 static char buf2[BUFSIZ];
|
|
107 /*@observer@*/ static const char *fileiter;
|
|
108 size_t i = 0, j;
|
|
109 FILE* ret;
|
|
110 while(*guessdir != '\0' && i<BUFSIZ-2) buf2[i++] = *guessdir++;
|
|
111 buf2[i++] = '/';
|
|
112 fileiter = file;
|
|
113 while(*fileiter != '\0' && i<BUFSIZ-1) buf2[i++] = *fileiter++;
|
|
114 buf2[i] = '\0';
|
|
115 ret = ick_debfopen(buf2,mode); /* where it ought to be */
|
|
116 if(ret) {(void) fclose(ret); return buf2;}
|
|
117 ret = ick_debfopen(file,mode); /* current dir */
|
|
118 if(ret) {(void) fclose(ret); return file;}
|
|
119 if(!strchr(argv0,'/')&&
|
|
120 !strchr(argv0,'\\')) return 0; /* argv[0] has no dir specified */
|
|
121 i = j = 0;
|
|
122 while(*argv0 != '\0' && i<BUFSIZ-2)
|
|
123 {
|
|
124 buf2[i++] = *argv0++;
|
|
125 if(*argv0=='/') j = i;
|
|
126 if(*argv0=='\\') j = i;
|
|
127 }
|
|
128 i = j + 1;
|
|
129 fileiter=file;
|
|
130 while(*fileiter != '\0' && i<BUFSIZ-1) buf2[i++] = *fileiter++;
|
|
131 buf2[i] = '\0';
|
|
132 ret = ick_debfopen(buf2,mode); /* argv[0]'s dir */
|
|
133 if(ret) {(void) fclose(ret); return buf2;}
|
|
134 i = j + 1;
|
|
135 fileiter="../lib/"; /* correct for POSIX and DJGPP */
|
|
136 while(*fileiter != '\0' && i<BUFSIZ-1) buf2[i++] = *fileiter++;
|
|
137 fileiter=file;
|
|
138 while(*fileiter != '\0' && i<BUFSIZ-1) buf2[i++] = *fileiter++;
|
|
139 buf2[i]='\0';
|
|
140 ret = ick_debfopen(buf2,mode); /* argv[0]/../lib/ */
|
|
141 if(ret) {(void) fclose(ret); return buf2;}
|
|
142 i = j + 1;
|
|
143 fileiter="../include/"; /* correct for POSIX and DJGPP */
|
|
144 while(*fileiter != '\0' && i<BUFSIZ-1) buf2[i++] = *fileiter++;
|
|
145 fileiter=file;
|
|
146 while(*fileiter != '\0' && i<BUFSIZ-1) buf2[i++] = *fileiter++;
|
|
147 buf2[i]='\0';
|
|
148 ret = ick_debfopen(buf2,mode); /* argv[0]/../include/ */
|
|
149 if(ret) {(void) fclose(ret); return buf2;}
|
|
150 return 0; /* just return 0 if even this failed */
|
|
151 }
|
|
152
|
|
153 /* AIS: The same thing, but with freopen */
|
|
154 /*@dependent@*/ /*@null@*/ FILE* ick_findandfreopen(/*@observer@*/ const char* file,
|
|
155 /*@observer@*/ const char* guessdir,
|
|
156 /*@observer@*/ const char* mode,
|
|
157 /*@observer@*/ const char* argv0,
|
|
158 FILE* over)
|
|
159 {
|
|
160 const char* s=ick_findandtestopen(file,guessdir,mode,argv0);
|
|
161 if(s != NULL)
|
|
162 return freopen(s,mode,over);
|
|
163 else
|
|
164 return NULL;
|
|
165 }
|
|
166
|
|
167 /**
|
|
168 * Invoke snprintf(), if supported. Otherwise invoke sprintf() and abort
|
|
169 * if we did overflow.
|
|
170 */
|
|
171 int ick_snprintf_or_die(/*@out@*/ char *str, size_t size, /*@observer@*/ const char *format, ...)
|
|
172 {
|
|
173 va_list ap;
|
|
174 int retval;
|
|
175 va_start(ap, format);
|
|
176 #ifdef HAVE_VSNPRINTF
|
|
177 retval = vsnprintf(str, size, format, ap);
|
|
178 #else
|
|
179 retval = vsprintf(str, format, ap);
|
|
180 if (retval >= size)
|
|
181 ick_lose(IE553, 0, (const char*)NULL);
|
|
182 #endif
|
|
183 va_end(ap);
|
|
184 return retval;
|
|
185 }
|