1 /* VER 049 TAB P $Id: util.c,v 1.14.2.1 2002/01/29 06:44:48 egil Exp $
2 *
3 * file utilities
4 *
5 * copyright 1996, 1997 Egil Kvaleberg, egil@kvaleberg.no
6 * the GNU General Public License applies
7 *
8 * $Log: util.c,v $
9 * Revision 1.14.2.1 2002/01/29 06:44:48 egil
10 * Changing from xmalloc, xrealloc, xstrcpy to
11 * malloc_perfect, realloc_perfect and strdup_perfect
12 *
13 * Revision 1.14 1999/04/07 08:02:11 src
14 * Implemented --profile
15 *
16 * Revision 1.13 1999/03/24 03:53:02 src
17 * Implemented "newsx" as magic exclude pattern
18 *
19 * Revision 1.12 1999/03/11 07:30:01 src
20 * Implemented check for spool free space
21 *
22 * Revision 1.11 1999/03/07 14:58:19 src
23 * Read newsconfig supported. Storage API supported.
24 *
25 * Revision 1.10 1998/09/14 06:30:25 src
26 * *** empty log message ***
27 *
28 * Revision 1.9 1998/09/14 06:07:19 src
29 * Cleaned up dbz -Wall
30 *
31 * Revision 1.8 1998/09/11 09:17:44 src
32 * Check path consistency (--no-path) and length (--max-path)
33 * GNU style option --help, --version, --dry-run, changed --noxx to --no-xx
34 * Check for putenv and setenv, added xstrcpy
35 *
36 * Revision 1.7 1998/09/09 07:32:15 src
37 * Version 1.1
38 *
39 * Revision 1.6 1998/07/12 09:39:31 src
40 * newsx version 1.0
41 */
42
43 #include "common.h"
44 #include "proto.h"
45 #include "options.h"
46 #include "stat.h"
47
48 /*
49 * append the contents of a file to another file
50 * returns 0 on error, 1 if all OK
51 */
52 int
append_file(FILE * f,char * name,FILE * af)53 append_file(FILE *f,char *name,FILE *af)
54 {
55 int n;
56 char buf[1024];
57
58 if (fseek(f,0L,2) != 0) {
59 log_msg(L_ERRno,"can't seek to end of \"%s\"", name);
60 return 0;
61 }
62
63 while ((n = fread(buf,1,sizeof(buf),af)) > 0) {
64 if (fwrite(buf,1,n,f) != n) {
65 /* append failed */
66 log_msg(L_ERR,"can't append to \"%s\"", name);
67 return 0;
68 }
69 }
70
71 if (fflush(f) != 0) {
72 log_msg(L_ERRno,"can't flush \"%s\"", name);
73 return 0;
74 }
75 if (fseek(f,0L,0) != 0) {
76 log_msg(L_ERRno,"can't seek to start of \"%s\"", name);
77 return 0;
78 }
79 return 1;
80 }
81
82 /*
83 * rename a file
84 * returns 0 on error
85 */
86 int
rename_file(char * from,char * to)87 rename_file(char *from,char *to)
88 {
89 if (rename(from,to) == EOF) {
90 log_msg(L_ERRno,"can't rename \"%s\" to \"%s\"", from,to);
91 return 0;
92 }
93 return 1;
94 }
95
96 /*
97 * check if it is a regular file
98 * as an added bonus, sets file size is desired
99 */
100 int
is_regular(FILE * f,char * name,long * sizep)101 is_regular(FILE *f, char *name, long *sizep)
102 {
103 struct stat st;
104
105 /* verify that it is a regular file */
106 if (fstat(fileno(f),&st) < 0) {
107 log_msg(L_ERRno,"can't fstat \"%s\"", name);
108 return 0;
109 }
110 /* BUG: both of these must be set: S_IRUSR S_IWUSR */
111 if (!S_ISREG(st.st_mode)) {
112 log_msg(L_ERR,"\"%s\" is not a regular file", name);
113 return 0;
114 }
115 if (sizep) *sizep = (long)(st.st_size);
116 return 1;
117 }
118
119 /*
120 * build a file name, with a fixed default choice as well as a
121 * first prioroty alternative
122 * both names may be absolute or relative paths
123 */
124 void
build_alt_filename(char * where,char * home,char * fixed,char * alt)125 build_alt_filename(char *where, char *home, char *fixed, char *alt)
126 {
127 char *name = (alt && alt[0]) ? alt : fixed;
128
129 if (name[0]=='/' || name[0]=='.') {
130 build_filename(where,name,NULL,NULL,NULL);
131 } else {
132 build_filename(where,home,"/",name,NULL);
133 }
134 }
135
136 /*
137 * build a file name, max length PATH_MAX
138 * argument is a list of up to arguments, padded with NULL to make 4
139 * NOTE: a NULL-terminated argument list would have been neater,
140 * but it is simply not worth the effort to make it portable
141 */
142 void
build_filename(char * where,char * arg1,char * arg2,char * arg3,char * arg4)143 build_filename(char *where,char *arg1,char *arg2,char *arg3,char *arg4)
144 {
145 int len = 0;
146 int n;
147 char **argp;
148 char *argv[5];
149
150 argv[0] = arg1;
151 argv[1] = arg2;
152 argv[2] = arg3;
153 argv[3] = arg4;
154 argv[4] = NULL;
155
156 for (argp = argv; *argp; ++argp) {
157 if ((len += (n=strlen(*argp))) >= PATH_MAX) {
158 log_msg(L_ERR,"file name longer than %d chars", PATH_MAX-1);
159 exit_cleanup(1);
160 }
161 strcpy(where+len-n,*argp);
162 }
163 }
164
165 /*
166 * convert time to text string, local time
167 * return static pointer
168 * "Wed Apr 10 11:00:00 1996"
169 */
170 char *
text_time(time_t t)171 text_time(time_t t)
172 {
173 static char buf[50];
174 char *p;
175
176 strcpy(buf,asctime(localtime(&t)));
177 /* remove trailing newline */
178 if ((p=strchr(buf,'\n'))) *p = '\0';
179
180 return buf;
181 }
182
183 /*
184 * skip blanks
185 */
186 char *
skipsp(char * p)187 skipsp(char *p)
188 {
189 while (*p==' ' || *p=='\t') ++p;
190 return p;
191 }
192
193 /*
194 * memory allocation - never fail
195 */
196 void *
malloc_perfect(unsigned int size)197 malloc_perfect(unsigned int size)
198 {
199 void *p;
200
201 if (!(p = malloc(size))) {
202 log_msg(L_ERR,"out of memory");
203 unlock_exit(1);
204 }
205 return p;
206 }
207
208 /*
209 * memory reallocation - never fail
210 */
211 void *
realloc_perfect(void * p,unsigned int size)212 realloc_perfect(void *p,unsigned int size)
213 {
214 if (!(p = realloc(p,size))) {
215 log_msg(L_ERR,"reallocation error, out of memory");
216 unlock_exit(1);
217 }
218 return p;
219 }
220
221 /*
222 * string allocate and copy - never fail
223 */
224 char *
strdup_perfect(const char * str)225 strdup_perfect(const char *str)
226 {
227 return strcpy(malloc_perfect(strlen(str)+1),str);
228 }
229