1 /*
2 * Author: William Chia-Wei Cheng (bill.cheng@acm.org)
3 *
4 * Copyright (C) 2001-2009, William Chia-Wei Cheng.
5 *
6 * This file may be distributed under the terms of the Q Public License
7 * as defined by Trolltech AS of Norway and appearing in the file
8 * LICENSE.QPL included in the packaging of this file.
9 *
10 * THIS FILE IS PROVIDED AS IS WITH NO WARRANTY OF ANY KIND, INCLUDING
11 * THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
12 * PURPOSE. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
13 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
14 * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
15 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
16 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 *
18 * @(#)$Header: /mm2/home/cvs/bc-src/tgif/util.c,v 1.13 2011/05/16 16:22:00 william Exp $
19 */
20
21 #define _INCLUDE_FROM_UTIL_C_
22
23 #include "tgifdefs.h"
24
25 #include "dialog.e"
26 #include "file.e"
27 #include "remote.e"
28 #include "strtbl.e"
29 #include "util.e"
30
UtilFree(pszStr)31 void UtilFree(pszStr)
32 char *pszStr;
33 {
34 if (pszStr != NULL) free(pszStr);
35 }
36
UtilFreeStringArray(ppsz,nItems)37 char *UtilFreeStringArray(ppsz, nItems)
38 char **ppsz;
39 int nItems;
40 /* ppsz is also freed */
41 {
42 if (ppsz != NULL) {
43 int i;
44
45 for (i=0; i < nItems; i++) UtilFree(ppsz[i]);
46 free(ppsz);
47 }
48 return NULL;
49 }
50
UtilStrDup(pszStr)51 char *UtilStrDup(pszStr)
52 char *pszStr;
53 /* must eventually free the returned string with free() */
54 {
55 int len=(pszStr == NULL ? 0 : strlen(pszStr));
56 char *c_ptr=(char*)malloc((len+1)*sizeof(char));
57
58 if (c_ptr == NULL) return NULL;
59 strcpy(c_ptr, (pszStr == NULL ? "" : pszStr));
60 return c_ptr;
61 }
62
UtilStrCpyN(pszDest,nMaxDestSz,pszSrc)63 int UtilStrCpyN(pszDest, nMaxDestSz, pszSrc)
64 char *pszDest, *pszSrc;
65 int nMaxDestSz;
66 {
67 int len=0;
68
69 if (pszDest != NULL && nMaxDestSz > 0) *pszDest = '\0';
70 if (pszDest == NULL || pszSrc == NULL || nMaxDestSz <= 0) return 0;
71
72 len = strlen(pszSrc);
73 if (len > nMaxDestSz-1) len = nMaxDestSz-1;
74 strncpy(pszDest, pszSrc, len);
75 pszDest[len] = '\0';
76 return len;
77 }
78
UtilStrCpy(pszDest,pszSrc)79 int UtilStrCpy(pszDest, pszSrc)
80 char *pszDest, *pszSrc;
81 /* safe copy byte by byte from pszSrc to pszDest */
82 {
83 int len=0;
84
85 if (pszDest == NULL || pszSrc == NULL) return 0;
86
87 while (((*pszDest++)=(*pszSrc++)) != '\0') {
88 len++;
89 }
90 return len;
91 }
92
UtilLeftTrim(pszStr)93 void UtilLeftTrim(pszStr)
94 char *pszStr;
95 /* pszStr must be terminated by '\0' */
96 {
97 register char *c_ptr;
98
99 for (c_ptr=pszStr; *c_ptr != '\0'; c_ptr++) {
100 char ch=(*c_ptr);
101
102 if (!(ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r')) {
103 break;
104 }
105 }
106 if (*c_ptr != '\0' && c_ptr != pszStr) {
107 while ((*pszStr++ = *c_ptr++) != '\0') ;
108 }
109 }
110
UtilRightTrim(pszStr)111 void UtilRightTrim(pszStr)
112 char *pszStr;
113 /* pszStr must be terminated by '\0' */
114 {
115 register int len;
116
117 for (len=strlen(pszStr)-1; len >= 0; len--) {
118 char ch=pszStr[len];
119
120 if (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r') {
121 pszStr[len] = '\0';
122 } else {
123 break;
124 }
125 }
126 }
127
UtilTrimBlanks(pszStr)128 void UtilTrimBlanks(pszStr)
129 char *pszStr;
130 /* pszStr must be terminated by '\0' */
131 {
132 register int len;
133 register char *c_ptr;
134
135 for (len=strlen(pszStr)-1; len >= 0; len--) {
136 char ch=pszStr[len];
137
138 if (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r') {
139 pszStr[len] = '\0';
140 } else {
141 break;
142 }
143 }
144 for (c_ptr=pszStr; *c_ptr != '\0'; c_ptr++) {
145 char ch=(*c_ptr);
146
147 if (!(ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r')) {
148 break;
149 }
150 }
151 if (*c_ptr != '\0' && c_ptr != pszStr) {
152 while ((*pszStr++ = *c_ptr++) != '\0') ;
153 }
154 }
155
UtilStrUpper(psz)156 void UtilStrUpper(psz)
157 char *psz;
158 {
159 for ( ; *psz != '\0'; psz++) {
160 if (*psz >= 'a' && *psz <= 'z') {
161 *psz = *psz-'a'+'A';
162 }
163 }
164 }
165
UtilStrLower(psz)166 void UtilStrLower(psz)
167 char *psz;
168 {
169 for ( ; *psz != '\0'; psz++) {
170 if (*psz >= 'A' && *psz <= 'Z') {
171 *psz = *psz-'A'+'a';
172 }
173 }
174 }
175
UtilStrNCaseCmp(pszStr1,pszStr2,nCount)176 int UtilStrNCaseCmp(pszStr1, pszStr2, nCount)
177 char *pszStr1, *pszStr2;
178 int nCount;
179 {
180 char *c_ptr1, *c_ptr2, ch1, ch2;
181 int i=0;
182
183 for (c_ptr1=pszStr1, c_ptr2=pszStr2; i < nCount && (*c_ptr1 != '\0' ||
184 *c_ptr2 != '\0'); c_ptr1++, c_ptr2++, i++) {
185 ch1 = *c_ptr1;
186 ch2 = *c_ptr2;
187 if (ch1 >= 'A' && ch1 <= 'Z') ch1 = ch1-'A'+'a';
188 if (ch2 >= 'A' && ch2 <= 'Z') ch2 = ch2-'A'+'a';
189 if (ch1 != ch2) break;
190 }
191 if (i == nCount) return 0;
192 return ((*c_ptr1)-(*c_ptr2));
193 }
194
UtilStrICmp(pszStr1,pszStr2)195 int UtilStrICmp(pszStr1, pszStr2)
196 char *pszStr1, *pszStr2;
197 {
198 int diff=FALSE;
199 char *c_ptr1, *c_ptr2, ch1, ch2;
200
201 for (c_ptr1=pszStr1, c_ptr2=pszStr2; *c_ptr1 != '\0' || *c_ptr2 != '\0';
202 c_ptr1++, c_ptr2++) {
203 ch1 = *c_ptr1;
204 ch2 = *c_ptr2;
205 if (ch1 >= 'A' && ch1 <= 'Z') ch1 = ch1-'A'+'a';
206 if (ch2 >= 'A' && ch2 <= 'Z') ch2 = ch2-'A'+'a';
207 if (ch1 != ch2) {
208 diff = TRUE;
209 break;
210 }
211 }
212 return (diff ? ((*c_ptr1)-(*c_ptr2)) : 0);
213 }
214
UtilStrRChr(pszStr,int_ch)215 char *UtilStrRChr(pszStr, int_ch)
216 char *pszStr;
217 int int_ch;
218 {
219 int len=strlen(pszStr);
220 char ch=(char)int_ch;
221
222 for (len--; len >= 0; len--) {
223 if (pszStr[len] == ch) {
224 return (&pszStr[len]);
225 }
226 }
227 return NULL;
228 }
229
UtilStrTok(pszStr,pszDelim,ppszState)230 char *UtilStrTok(pszStr, pszDelim, ppszState)
231 char *pszStr, *pszDelim, **ppszState;
232 {
233 char *psz=NULL, *psz_start=NULL;
234
235 if (pszStr != NULL) {
236 *ppszState = NULL;
237 psz_start = pszStr;
238 while (*psz_start != '\0' && strchr(pszDelim, *psz_start) != NULL) {
239 psz_start++;
240 }
241 if (*psz_start == '\0') return NULL;
242
243 for (psz=psz_start; *psz != '\0'; psz++) {
244 if (strchr(pszDelim, *psz) != NULL) {
245 *psz = '\0';
246 *ppszState = psz;
247
248 return psz_start;
249 }
250 }
251 if (*psz == '\0' && psz_start != psz) {
252 return psz_start;
253 }
254 } else {
255 if (*ppszState == NULL) return NULL;
256
257 psz_start = &(*ppszState)[1];
258 *ppszState = NULL;
259 while (*psz_start != '\0' && strchr(pszDelim, *psz_start) != NULL) {
260 psz_start++;
261 }
262 if (*psz_start == '\0') return NULL;
263
264 for (psz=psz_start; *psz != '\0'; psz++) {
265 if (strchr(pszDelim, *psz) != NULL) {
266 *psz = '\0';
267 *ppszState = psz;
268
269 return psz_start;
270 }
271 }
272 if (*psz == '\0' && psz_start != psz) {
273 return psz_start;
274 }
275 }
276 return NULL;
277 }
278
279 #ifdef NO_STRSTR
strstr(pszStr,pszSubStr)280 char *strstr (pszStr, pszSubStr)
281 char *pszStr, *pszSubStr;
282 {
283 int len;
284
285 for (len=strlen(pszSubStr); *pszStr != '\0'; pszStr++) {
286 if (strncmp(pszStr, pszSubStr, len) == 0) {
287 return(pszStr);
288 }
289 }
290 return NULL;
291 }
292 #endif /* NO_STRSTR */
293
UtilShrinkName(pszFile)294 int UtilShrinkName(pszFile)
295 char *pszFile;
296 {
297 char *c_ptr=NULL, *real_ptr=NULL, *real_name=NULL;
298
299 if (pszFile[0] == '.' && pszFile[1] == DIR_SEP) return TRUE;
300 if (*pszFile != DIR_SEP) return FALSE;
301
302 real_name = UtilStrDup(pszFile);
303 if (real_name == NULL) return FALSE;
304 real_ptr = real_name;
305 c_ptr = &real_name[1];
306
307 while (*c_ptr != '\0') {
308 if (*c_ptr == '.') {
309 if (c_ptr[1] == '.') {
310 if (c_ptr[2] == DIR_SEP) {
311 /* "../" */
312 if (real_ptr != real_name) {
313 while (*(--real_ptr) != DIR_SEP) ;
314 }
315 c_ptr = (&c_ptr[3]);
316 } else {
317 while (*c_ptr != '\0' && *c_ptr != DIR_SEP) {
318 *(++real_ptr) = *c_ptr++;
319 }
320 if (*c_ptr == DIR_SEP) {
321 c_ptr++;
322 *(++real_ptr) = DIR_SEP;
323 }
324 }
325 } else if (c_ptr[1] == DIR_SEP) {
326 /* "./" */
327 c_ptr = (&c_ptr[2]);
328 } else {
329 while (*c_ptr != '\0' && *c_ptr != DIR_SEP) {
330 *(++real_ptr) = *c_ptr++;
331 }
332 if (*c_ptr == DIR_SEP) {
333 c_ptr++;
334 *(++real_ptr) = DIR_SEP;
335 }
336 }
337 #ifndef apollo
338 } else if (*c_ptr == DIR_SEP) {
339 c_ptr++;
340 #endif
341 } else {
342 while (*c_ptr != '\0' && *c_ptr != DIR_SEP) {
343 *(++real_ptr) = *c_ptr++;
344 }
345 if (*c_ptr == DIR_SEP) {
346 c_ptr++;
347 *(++real_ptr) = DIR_SEP;
348 }
349 }
350 }
351 *(++real_ptr) = '\0';
352 strcpy(pszFile, real_name);
353 free(real_name);
354 return TRUE;
355 }
356
UtilRemoveQuotes(pszStr)357 void UtilRemoveQuotes(pszStr)
358 char *pszStr;
359 {
360 int nStart=0, nEnd=strlen(pszStr)-1, still_going=TRUE;
361
362 while (still_going) {
363 if (nStart >= nEnd) break;
364 switch (pszStr[nStart]) {
365 case '"': if (pszStr[nEnd] != '"') still_going = FALSE; break;
366 case '\'': if (pszStr[nEnd] != '\'') still_going = FALSE; break;
367 default: still_going = FALSE; break;
368 }
369 if (still_going) {
370 nStart++;
371 pszStr[nEnd--] = '\0';
372 }
373 }
374 if (nStart != 0) {
375 char *c_ptr=&pszStr[nStart];
376
377 while (*pszStr != '\0') *pszStr++ = (*c_ptr++);
378 }
379 }
380
381 static char gszMsg[512];
382
UtilGetALine(pFile)383 char *UtilGetALine(pFile)
384 FILE *pFile;
385 {
386 unsigned long len;
387
388 if (fgets(gszMsg, sizeof(gszMsg), pFile) == NULL) return NULL;
389
390 len = strlen(gszMsg);
391 if (len == sizeof(gszMsg)-1 && gszMsg[len-1] != '\n') {
392 char *buf=UtilStrDup(gszMsg);
393 unsigned long cur_len;
394 int still_going=TRUE;
395
396 if (buf == NULL) return NULL;
397
398 cur_len = strlen(buf);
399 while (still_going && fgets(gszMsg, sizeof(gszMsg), pFile) != NULL) {
400 len = strlen(gszMsg);
401 if (len != sizeof(gszMsg)-1) {
402 still_going = FALSE;
403 } else if (gszMsg[len-1] == '\n') {
404 gszMsg[--len] = '\0';
405 still_going = FALSE;
406 }
407 if (buf != NULL) {
408 char *new_buf=(char*)realloc(buf, (size_t)(cur_len+len+1));
409
410 if (new_buf == NULL) {
411 free(buf);
412 return NULL;
413 }
414 buf = new_buf;
415 strcat(&buf[cur_len], gszMsg);
416 cur_len += len;
417 }
418 }
419 return buf;
420 } else {
421 if (gszMsg[len-1] == '\n') gszMsg[--len] = '\0';
422 return UtilStrDup(gszMsg);
423 }
424 }
425
UtilGetAContinuedLine(pFile)426 char *UtilGetAContinuedLine(pFile)
427 FILE *pFile;
428 {
429 unsigned long len;
430 char *buf;
431
432 if ((buf=UtilGetALine(pFile)) == NULL) return NULL;
433
434 len = strlen(buf);
435 while (len > 0 && buf[len-1] == '\\') {
436 char *tmp_buf;
437 int tmp_len;
438
439 buf[--len] = '\0';
440 tmp_buf = UtilGetALine(pFile);
441 if (tmp_buf == NULL) return buf;
442 tmp_len = strlen(tmp_buf);
443 if (tmp_len == 0) {
444 free(tmp_buf);
445 return buf;
446 } else if ((buf=(char*)realloc(buf, len+tmp_len+1)) == NULL) {
447 free(tmp_buf);
448 return NULL;
449 }
450 strcpy(&buf[len], tmp_buf);
451 len += tmp_len;
452 free(tmp_buf);
453 }
454 return buf;
455 }
456
UtilCopyFile(pszFromFile,pszToFile)457 int UtilCopyFile(pszFromFile, pszToFile)
458 char *pszFromFile, *pszToFile;
459 {
460 char buf[0x1000];
461 int bytes_read=0;
462 int fd1=(-1), fd2=(-1);
463 mode_t mode=((tmpFileMode == 0) ? 0700 : tmpFileMode);
464
465 if ((fd1=open(pszFromFile, O_RDONLY)) == (-1)) return TG_REMOTE_STATUS_READ;
466 if (UtilPathExists(pszToFile)) {
467 if ((fd2=open(pszToFile, O_WRONLY|O_TRUNC)) == (-1)) {
468 close(fd1);
469 return TG_REMOTE_STATUS_WRITE;
470 }
471 } else {
472 if ((fd2=open(pszToFile, O_WRONLY|O_CREAT|O_TRUNC, mode)) == (-1)) {
473 close(fd1);
474 return TG_REMOTE_STATUS_WRITE;
475 }
476 }
477 while ((bytes_read=read(fd1, buf, sizeof(buf))) > 0) {
478 if (write(fd2, buf, bytes_read) <= 0) {
479 close(fd1);
480 close(fd2);
481 return TG_REMOTE_STATUS_FILE;
482 }
483 }
484 close(fd1);
485 close(fd2);
486 if (tmpFileMode != 0 && chmod(pszToFile, tmpFileMode)) {
487 char msg[MAXSTRING<<1];
488
489 sprintf(msg, TgLoadString(STID_CANNOT_CHMOD), pszToFile, tmpFileMode);
490 MsgBox(msg, TOOL_NAME, INFO_MB);
491 }
492 return TG_REMOTE_STATUS_OK;
493 }
494
UtilConcatFile(pszFromFile1,pszFromFile2,pszToFile)495 int UtilConcatFile(pszFromFile1, pszFromFile2, pszToFile)
496 char *pszFromFile1, *pszFromFile2, *pszToFile;
497 {
498 char buf[0x1000];
499 int bytes_read=0;
500 int fd1=(-1), fd2=(-1), fd3=(-1);
501 mode_t mode=((tmpFileMode == 0) ? 0700 : tmpFileMode);
502
503 if ((fd1=open(pszFromFile1, O_RDONLY)) == (-1)) return TG_REMOTE_STATUS_READ;
504 if ((fd2=open(pszFromFile2, O_RDONLY)) == (-1)) {
505 close(fd1);
506 return TG_REMOTE_STATUS_READ;
507 }
508 if (UtilPathExists(pszToFile)) {
509 if ((fd3=open(pszToFile, O_WRONLY|O_TRUNC)) == (-1)) {
510 close(fd1);
511 close(fd2);
512 return TG_REMOTE_STATUS_WRITE;
513 }
514 } else {
515 if ((fd3=open(pszToFile, O_WRONLY|O_CREAT|O_TRUNC, mode)) == (-1)) {
516 close(fd1);
517 close(fd2);
518 return TG_REMOTE_STATUS_WRITE;
519 }
520 }
521 while ((bytes_read=read(fd1, buf, sizeof(buf))) > 0) {
522 if (write(fd3, buf, bytes_read) <= 0) {
523 close(fd1);
524 close(fd2);
525 close(fd3);
526 return TG_REMOTE_STATUS_FILE;
527 }
528 }
529 close(fd1);
530 while ((bytes_read=read(fd2, buf, sizeof(buf))) > 0) {
531 if (write(fd3, buf, bytes_read) <= 0) {
532 close(fd2);
533 close(fd3);
534 return TG_REMOTE_STATUS_FILE;
535 }
536 }
537 close(fd2);
538 close(fd3);
539 if (tmpFileMode != 0 && chmod(pszToFile, tmpFileMode)) {
540 char msg[MAXSTRING<<1];
541
542 sprintf(msg, TgLoadString(STID_CANNOT_CHMOD), pszToFile, tmpFileMode);
543 MsgBox(msg, TOOL_NAME, INFO_MB);
544 }
545 return TG_REMOTE_STATUS_OK;
546 }
547
UtilPathExists(pszPath)548 int UtilPathExists(pszPath)
549 char *pszPath;
550 {
551 struct stat stat_buf;
552
553 return (stat(pszPath, &stat_buf) == 0);
554 }
555
UtilPathIsLink(pszPath)556 int UtilPathIsLink(pszPath)
557 char *pszPath;
558 /*
559 * if pszPath is not valid, return FALSE
560 * if pszPath is valid but not a link, return FALSE
561 * if pszPath is valid and is a link, return TRUE
562 */
563 {
564 #ifndef _NO_LSTAT
565 struct stat stat_buf;
566
567 if (lstat(pszPath, &stat_buf) == 0 &&
568 ((stat_buf.st_mode & S_IFLNK) == S_IFLNK)) {
569 return TRUE;
570 }
571 #endif /* _NO_LSTAT */
572 return FALSE;
573 }
574
UtilIsDirectory(pszPath)575 int UtilIsDirectory(pszPath)
576 char *pszPath;
577 {
578 struct stat stat_buf;
579
580 return (stat(pszPath, &stat_buf) == 0 &&
581 (stat_buf.st_mode & S_IFDIR) == S_IFDIR);
582 }
583
UtilCreateDirHier(pszDir)584 int UtilCreateDirHier(pszDir)
585 char *pszDir;
586 {
587 char *psz=NULL;
588 int ok=TRUE;
589
590 if (*pszDir == '\0') return FALSE;
591
592 if (UtilPathExists(pszDir)) {
593 if (UtilPathIsLink(pszDir)) {
594 return TRUE;
595 }
596 if (UtilIsDirectory(pszDir)) {
597 return TRUE;
598 }
599 return FALSE;
600 }
601 if (*pszDir == DIR_SEP && pszDir[1] == '\0') {
602 return FALSE;
603 }
604 if ((psz=strrchr(pszDir, DIR_SEP)) == NULL) {
605 return FALSE;
606 }
607 *psz = '\0';
608 if (!UtilCreateDirHier(pszDir)) {
609 ok = FALSE;
610 }
611 *psz = DIR_SEP;
612
613 if (ok) {
614 if (mkdir(pszDir, 0755) != 0) {
615 return FALSE;
616 }
617 }
618 return ok;
619 }
620
621 #ifndef _NO_GETTIMEOFDAY
622 static
ms_time(tv)623 long ms_time(tv)
624 struct timeval *tv;
625 {
626 return ((long)(tv->tv_usec / 1000.0)) + ((long)(tv->tv_sec * 1000));
627 }
628 #endif /* ~_NO_GETTIMEOFDAY */
629
UtilGetMilliSecTime(pl_sec,pl_msec)630 long UtilGetMilliSecTime(pl_sec, pl_msec)
631 long *pl_sec, *pl_msec;
632 {
633 #ifdef _NO_GETTIMEOFDAY
634 struct timeb start;
635 #else /* ~_NO_GETTIMEOFDAY */
636 struct timeval start;
637 struct timezone zone;
638 #endif /* _NO_GETTIMEOFDAY */
639 long ms_start_time=0L;
640
641 #ifdef _NO_GETTIMEOFDAY
642 ftime(&start);
643 ms_start_time = ((long)start.time * 1000) + ((long)start.millitm);
644 if (pl_sec != NULL) *pl_sec = ((long)(start.time));
645 if (pl_msec != NULL) *pl_msec = ((long)(start.millitm));
646 #else /* ~_NO_GETTIMEOFDAY */
647 gettimeofday(&start, &zone);
648 ms_start_time = ms_time(&start);
649 if (pl_sec != NULL) *pl_sec = ((long)(start.tv_sec));
650 if (pl_msec != NULL) *pl_msec = ((long)(start.tv_usec/1000));
651 #endif /* _NO_GETTIMEOFDAY */
652
653 return ms_start_time;
654 }
655
656