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