|
|
1.1 root 1: /* misc.cpp */
2:
3: /* Synchronet miscellaneous utility-type routines (exported) */
4:
5: /* $Id: misc.c,v 1.9 2000/11/14 01:58:37 rswindell Exp $ */
6:
7: /****************************************************************************
8: * @format.tab-size 4 (Plain Text/Source Code File Header) *
9: * @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) *
10: * *
11: * Copyright 2000 Rob Swindell - http://www.synchro.net/copyright.html *
12: * *
13: * This program is free software; you can redistribute it and/or *
14: * modify it under the terms of the GNU General Public License *
15: * as published by the Free Software Foundation; either version 2 *
16: * of the License, or (at your option) any later version. *
17: * See the GNU General Public License for more details: gpl.txt or *
18: * http://www.fsf.org/copyleft/gpl.html *
19: * *
20: * Anonymous FTP access to the most recent released source is available at *
21: * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net *
22: * *
23: * Anonymous CVS access to the development source and modification history *
24: * is available at cvs.synchro.net:/cvsroot/sbbs, example: *
25: * cvs -d :pserver:[email protected]:/cvsroot/sbbs login *
26: * (just hit return, no password is necessary) *
27: * cvs -d :pserver:[email protected]:/cvsroot/sbbs checkout src *
28: * *
29: * For Synchronet coding style and modification guidelines, see *
30: * http://www.synchro.net/source.html *
31: * *
32: * You are encouraged to submit any modifications (preferably in Unix diff *
33: * format) via e-mail to [email protected] *
34: * *
35: * Note: If this box doesn't appear square, then you need to fix your tabs. *
36: ****************************************************************************/
37:
38: #include "sbbs.h"
39: #include "crc32.h"
40:
41: /****************************************************************************/
42: /* Network open function. Opens all files DENYALL and retries LOOP_NOPEN */
43: /* number of times if the attempted file is already open or denying access */
44: /* for some other reason. All files are opened in BINARY mode. */
45: /****************************************************************************/
46: int nopen(char *str, int access)
47: {
48: int file,share,count=0;
49:
50: if(access&O_DENYNONE) {
51: share=SH_DENYNO;
52: access&=~O_DENYNONE; }
53: else if(access==O_RDONLY) share=SH_DENYWR;
54: else share=SH_DENYRW;
55: while(((file=sopen(str,O_BINARY|access,share))==-1)
56: && errno==EACCES && count++<LOOP_NOPEN)
57: if(count>10)
58: mswait(55);
59: return(file);
60: }
61: /****************************************************************************/
62: /* This function performs an nopen, but returns a file stream with a buffer */
63: /* allocated. */
64: /****************************************************************************/
65: FILE * fnopen(int *fd, char *str, int access)
66: {
67: char mode[128];
68: int file;
69: FILE * stream;
70:
71: if((file=nopen(str,access))==-1)
72: return(NULL);
73:
74: if(fd!=NULL)
75: *fd=file;
76:
77: if(access&O_APPEND) {
78: if(access&O_RDONLY)
79: strcpy(mode,"a+");
80: else
81: strcpy(mode,"a");
82: } else if(access&O_CREAT) {
83: if(access&O_TRUNC)
84: strcpy(mode,"w");
85: else
86: strcpy(mode,"w+");
87: } else {
88: if(access&O_WRONLY || (access&O_RDWR)==O_RDWR)
89: strcpy(mode,"r+");
90: else
91: strcpy(mode,"r");
92: }
93: stream=fdopen(file,mode);
94: if(stream==NULL) {
95: close(file);
96: return(NULL);
97: }
98: setvbuf(stream,NULL,_IOFBF,FNOPEN_BUF_SIZE);
99: return(stream);
100: }
101:
102: /****************************************************************************/
103: /* Returns the number of characters in 'str' not counting ctrl-ax codes */
104: /* or the null terminator */
105: /****************************************************************************/
106: int bstrlen(char *str)
107: {
108: int i=0;
109:
110: while(*str) {
111: if(*str==1) /* ctrl-a */
112: str++;
113: else
114: i++;
115: if(!(*str)) break;
116: str++; }
117: return(i);
118: }
119:
120: void strip_ctrl(char *str)
121: {
122: char tmp[1024];
123: int i,j,k;
124:
125: k=strlen(str);
126: for(i=j=0;i<k;i++)
127: if(str[i]==1) /* Ctrl-a */
128: i++;
129: else if(j && str[i]<=SP && tmp[j-1]==SP)
130: continue;
131: else if(i && !isalnum(str[i]) && str[i]==str[i-1])
132: continue;
133: else if((uchar)str[i]>=SP)
134: tmp[j++]=str[i];
135: else if(str[i]==TAB || (str[i]==CR && str[i+1]==LF))
136: tmp[j++]=SP;
137: tmp[j]=0;
138: strcpy(str,tmp);
139: }
140:
141: void strip_exascii(char *str)
142: {
143: char tmp[1024];
144: int i,j,k;
145:
146: k=strlen(str);
147: for(i=j=0;i<k;i++)
148: if(!(str[i]&0x80))
149: tmp[j++]=str[i];
150: tmp[j]=0;
151: strcpy(str,tmp);
152: }
153:
154: /****************************************************************************/
155: /* Returns in 'string' a character representation of the number in l with */
156: /* commas. */
157: /****************************************************************************/
158: char *ultoac(ulong l, char *string)
159: {
160: char str[256];
161: char i,j,k;
162:
163: ultoa(l,str,10);
164: i=strlen(str)-1;
165: j=i/3+1+i;
166: string[j--]=0;
167: for(k=1;i>-1;k++) {
168: string[j--]=str[i--];
169: if(j>0 && !(k%3))
170: string[j--]=','; }
171: return(string);
172: }
173:
174: /****************************************************************************/
175: /* Truncates white-space chars off end of 'str' */
176: /****************************************************************************/
177: void truncsp(char *str)
178: {
179: uint c;
180:
181: #if 0 /* no longer terminates at first tab OCT-09-2000 rswindell */
182: str[strcspn(str,"\t")]=0;
183: #endif
184: c=strlen(str);
185: while(c && (uchar)str[c-1]<=SP) c--;
186: str[c]=0;
187: }
188:
189: /****************************************************************************/
190: /* Puts a backslash on path strings */
191: /****************************************************************************/
192: void backslash(char *str)
193: {
194: int i;
195:
196: i=strlen(str);
197: if(i && str[i-1]!='\\' && str[i-1]!='/') {
198: str[i]=BACKSLASH;
199: str[i+1]=0;
200: }
201: }
202:
203: /****************************************************************************/
204: /* Puts a backslash on path strings if not just a drive letter and colon */
205: /****************************************************************************/
206: void backslashcolon(char *str)
207: {
208: int i;
209:
210: i=strlen(str);
211: if(i && str[i-1]!='\\' && str[i-1]!='/' && str[i-1]!=':') {
212: str[i]=BACKSLASH;
213: str[i+1]=0;
214: }
215: }
216:
217: /****************************************************************************/
218: /* Updates 16-bit "rcrc" with character 'ch' */
219: /****************************************************************************/
220: void ucrc16(uchar ch, ushort *rcrc)
221: {
222: ushort i, cy;
223: uchar nch=ch;
224:
225: for (i=0; i<8; i++) {
226: cy=*rcrc & 0x8000;
227: *rcrc<<=1;
228: if (nch & 0x80) *rcrc |= 1;
229: nch<<=1;
230: if (cy) *rcrc ^= 0x1021; }
231: }
232:
233: /****************************************************************************/
234: /* Returns CRC-16 of string (not including terminating NULL) */
235: /****************************************************************************/
236: ushort DLLCALL crc16(char *str)
237: {
238: int i=0;
239: ushort crc=0;
240:
241: ucrc16(0,&crc);
242: while(str[i])
243: ucrc16(str[i++],&crc);
244: ucrc16(0,&crc);
245: ucrc16(0,&crc);
246: return(crc);
247: }
248:
249: /****************************************************************************/
250: /* Returns CRC-32 of string (not including terminating NULL) */
251: /****************************************************************************/
252: ulong crc32(char *buf, ulong len)
253: {
254: ulong l,crc=0xffffffff;
255:
256: for(l=0;l<len;l++)
257: crc=ucrc32(buf[l],crc);
258: return(~crc);
259: }
260:
261: /****************************************************************************/
262: /* Compares pointers to pointers to char. Used in conjuction with qsort() */
263: /****************************************************************************/
264: int pstrcmp(char **str1, char **str2)
265: {
266: return(strcmp(*str1,*str2));
267: }
268:
269: /****************************************************************************/
270: /* Returns the number of characters that are the same between str1 and str2 */
271: /****************************************************************************/
272: int strsame(char *str1, char *str2)
273: {
274: int i,j=0;
275:
276: for(i=0;str1[i];i++)
277: if(str1[i]==str2[i]) j++;
278: return(j);
279: }
280:
281: #define MV_BUFLEN 4096
282:
283: /****************************************************************************/
284: /* Converts when_t.zone into ASCII format */
285: /****************************************************************************/
286: char* DLLCALL zonestr(short zone)
287: {
288: static char str[32];
289:
290: switch((ushort)zone) {
291: case 0: return("UT");
292: case AST: return("AST");
293: case EST: return("EST");
294: case CST: return("CST");
295: case MST: return("MST");
296: case PST: return("PST");
297: case YST: return("YST");
298: case HST: return("HST");
299: case BST: return("BST");
300: case ADT: return("ADT");
301: case EDT: return("EDT");
302: case CDT: return("CDT");
303: case MDT: return("MDT");
304: case PDT: return("PDT");
305: case YDT: return("YDT");
306: case HDT: return("HDT");
307: case BDT: return("BDT");
308: case MID: return("MID");
309: case VAN: return("VAN");
310: case EDM: return("EDM");
311: case WIN: return("WIN");
312: case BOG: return("BOG");
313: case CAR: return("CAR");
314: case RIO: return("RIO");
315: case FER: return("FER");
316: case AZO: return("AZO");
317: case LON: return("LON");
318: case BER: return("BER");
319: case ATH: return("ATH");
320: case MOS: return("MOS");
321: case DUB: return("DUB");
322: case KAB: return("KAB");
323: case KAR: return("KAR");
324: case BOM: return("BOM");
325: case KAT: return("KAT");
326: case DHA: return("DHA");
327: case BAN: return("BAN");
328: case HON: return("HON");
329: case TOK: return("TOK");
330: case SYD: return("SYD");
331: case NOU: return("NOU");
332: case WEL: return("WEL");
333: }
334:
335: sprintf(str,"%02d:%02u",zone/60,zone<0 ? (-zone)%60 : zone%60);
336: return(str);
337: }
338:
339:
340: /****************************************************************************/
341: /* Returns an ASCII string for FidoNet address 'addr' */
342: /****************************************************************************/
343: char *faddrtoa(faddr_t addr)
344: {
345: static char str[25];
346: char point[25];
347:
348: sprintf(str,"%u:%u/%u",addr.zone,addr.net,addr.node);
349: if(addr.point) {
350: sprintf(point,".%u",addr.point);
351: strcat(str,point); }
352: return(str);
353: }
354:
355: /****************************************************************************/
356: /* Returns string for 2 digit hex+ numbers up to 575 */
357: /****************************************************************************/
358: char *hexplus(uint num, char *str)
359: {
360: sprintf(str,"%03x",num);
361: str[0]=num/0x100 ? 'f'+(num/0x10)-0xf : str[1];
362: str[1]=str[2];
363: str[2]=0;
364: return(str);
365: }
366:
367: uint hptoi(char *str)
368: {
369: char tmp[128];
370: uint i;
371:
372: if(!str[1] || toupper(str[0])<='F')
373: return(ahtoul(str));
374: strcpy(tmp,str);
375: tmp[0]='F';
376: i=ahtoul(tmp)+((toupper(str[0])-'F')*0x10);
377: return(i);
378: }
379:
380: /****************************************************************************/
381: /* Converts an ASCII Hex string into an ulong */
382: /****************************************************************************/
383: ulong ahtoul(char *str)
384: {
385: ulong l,val=0;
386:
387: while((l=(*str++)|0x20)!=0x20)
388: val=(l&0xf)+(l>>6&1)*9+val*16;
389: return(val);
390: }
391:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.