1 /***************************************************************/
2 /*                                                             */
3 /*  UTILS.C                                                    */
4 /*                                                             */
5 /*  Useful utility functions.                                  */
6 /*                                                             */
7 /*  This file is part of REMIND.                               */
8 /*  Copyright (C) 1992-2021 by Dianne Skoll                    */
9 /*                                                             */
10 /***************************************************************/
11 
12 static char const DontEscapeMe[] =
13 "1234567890_-=+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ@.,/";
14 
15 #include "config.h"
16 #include "err.h"
17 
18 #include <string.h>
19 #include <stdio.h>
20 #include <ctype.h>
21 
22 #include <stdlib.h>
23 #include "types.h"
24 #include "globals.h"
25 #include "protos.h"
26 
27 #define UPPER(c) toupper(c)
28 
29 /***************************************************************/
30 /*                                                             */
31 /*  StrnCpy                                                    */
32 /*                                                             */
33 /*  Just like strncpy EXCEPT we ALWAYS copy the trailing 0.    */
34 /*                                                             */
35 /***************************************************************/
StrnCpy(char * dest,char const * source,int n)36 char *StrnCpy(char *dest, char const *source, int n)
37 {
38     char *odest = dest;
39 
40     while (n-- && (*dest++ = *source++)) ;
41     if (*(dest-1)) *dest = 0;
42     return odest;
43 }
44 
45 /***************************************************************/
46 /*                                                             */
47 /*  StrMatch                                                   */
48 /*                                                             */
49 /*  Checks that two strings match (case-insensitive) to at     */
50 /*  least the specified number of characters, or the length    */
51 /*  of the first string, whichever is greater.                 */
52 /*                                                             */
53 /***************************************************************/
StrMatch(char const * s1,char const * s2,int n)54 int StrMatch(char const *s1, char const *s2, int n)
55 {
56     int l;
57     if ((l = strlen(s1)) < n) return 0;
58     return !StrinCmp(s1, s2, l);
59 }
60 
61 /***************************************************************/
62 /*                                                             */
63 /*  StrinCmp - compare strings, case-insensitive               */
64 /*                                                             */
65 /***************************************************************/
StrinCmp(char const * s1,char const * s2,int n)66 int StrinCmp(char const *s1, char const *s2, int n)
67 {
68     register int r;
69     while (n && *s1 && *s2) {
70 	n--;
71 	r = UPPER(*s1) - UPPER(*s2);
72 	if (r) return r;
73 	s1++;
74 	s2++;
75     }
76     if (n) return (UPPER(*s1) - UPPER(*s2)); else return 0;
77 }
78 
79 /***************************************************************/
80 /*                                                             */
81 /*  StrDup                                                     */
82 /*                                                             */
83 /*  Like ANSI strdup                                           */
84 /*                                                             */
85 /***************************************************************/
StrDup(char const * s)86 char *StrDup(char const *s)
87 {
88     char *ret = malloc(strlen(s)+1);
89     if (!ret) return NULL;
90     strcpy(ret, s);
91     return ret;
92 }
93 
94 /***************************************************************/
95 /*                                                             */
96 /*  StrCmpi                                                    */
97 /*                                                             */
98 /*  Compare strings, case insensitive.                         */
99 /*                                                             */
100 /***************************************************************/
StrCmpi(char const * s1,char const * s2)101 int StrCmpi(char const *s1, char const *s2)
102 {
103     int r;
104     while (*s1 && *s2) {
105 	r = UPPER(*s1) - UPPER(*s2);
106 	if (r) return r;
107 	s1++;
108 	s2++;
109     }
110     return UPPER(*s1) - UPPER(*s2);
111 }
112 
113 /***************************************************************/
114 /*                                                             */
115 /*  DateOK                                                     */
116 /*                                                             */
117 /*  Return 1 if the date is OK, 0 otherwise.                   */
118 /*                                                             */
119 /***************************************************************/
DateOK(int y,int m,int d)120 int DateOK(int y, int m, int d)
121 {
122     if (d < 1                 ||
123 	m < 0                 ||
124 	y < BASE              ||
125 	m > 11                ||
126 	y > BASE + YR_RANGE   ||
127 	d > DaysInMonth(m, y) ) return 0;
128     else return 1;
129 }
130 
131 /* Functions designed to defeat gcc optimizer */
132 
_private_div(int a,int b)133 int _private_div(int a, int b) { return a/b; }
_private_add_overflow(int result,int b,int old)134 int _private_add_overflow(int result, int b, int old)
135 {
136     if (b > 0 && result < old) return 1;
137     if (b < 0 && result > old) return 1;
138     return 0;
139 }
_private_sub_overflow(int result,int b,int old)140 int _private_sub_overflow(int result, int b, int old)
141 {
142     if (b < 0 && result < old) return 1;
143     if (b > 0 && result > old) return 1;
144     return 0;
145 }
146 
_private_unminus_overflow(int a,int b)147 int _private_unminus_overflow(int a, int b)
148 {
149     if (a > 0 && b > 0) return 1;
150     if (a < 0 && b < 0) return 1;
151     return 0;
152 }
153 
154 int
ShellEscape(char const * in,DynamicBuffer * out)155 ShellEscape(char const *in, DynamicBuffer *out)
156 {
157     while(*in) {
158         if (!strchr(DontEscapeMe, *in)) {
159             if (DBufPutc(out, '\\') != OK) return E_NO_MEM;
160         }
161         if (DBufPutc(out, *in++) != OK) return E_NO_MEM;
162     }
163     return OK;
164 }
165