source: trunk/oscam-simples.c@ 3181

Last change on this file since 3181 was 3181, checked in by dingo35, 10 years ago

Adding threadsafety FIXMEs, feel free to join checking..

File size: 20.5 KB
Line 
1//FIXME Not checked on threadsafety yet; after checking please remove this line
2#include <sys/time.h>
3#include "globals.h"
4
5void aes_set_key(char *key)
6{
7 AES_set_decrypt_key((const unsigned char *)key, 128, &client[cs_idx].aeskey_decrypt);
8 AES_set_encrypt_key((const unsigned char *)key, 128, &client[cs_idx].aeskey);
9}
10
11void aes_decrypt(uchar *buf, int n)
12{
13 int i;
14 for(i=0; i<n; i+=16)
15 AES_decrypt(buf+i, buf+i, &client[cs_idx].aeskey_decrypt);
16}
17
18void aes_encrypt_idx(int idx, uchar *buf, int n)
19{
20 int i;
21 for(i=0; i<n; i+=16)
22 AES_encrypt(buf+i, buf+i, &client[idx].aeskey);
23}
24
25void add_aes_entry(struct s_reader *rdr, ushort caid, uint32 ident, int keyid, uchar *aesKey)
26{
27 AES_ENTRY *new_entry;
28 AES_ENTRY *next,*current;
29
30 // create de AES key entry for the linked list
31 new_entry=malloc(sizeof(AES_ENTRY));
32 if(!new_entry) {
33 cs_log("Error alocation memory for AES key entry");
34 return;
35 }
36
37 new_entry->caid=caid;
38 new_entry->ident=ident;
39 new_entry->keyid=keyid;
40 if(memcmp(aesKey,"\xFF\xFF",2)) {
41 AES_set_decrypt_key((const unsigned char *)aesKey, 128, &(new_entry->key));
42 // cs_log("adding key : %s",cs_hexdump(1,aesKey,16));
43 }
44 else {
45 memset(&new_entry->key,0,sizeof(AES_KEY));
46 // cs_log("adding fake key");
47 }
48 new_entry->next=NULL;
49
50 //if list is empty, new_entry is the new head
51 if(!rdr->aes_list) {
52 rdr->aes_list=new_entry;
53 return;
54 }
55
56 //happend it to the list
57 current=rdr->aes_list;
58 next=current->next;
59 while(next) {
60 current=next;
61 next=current->next;
62 }
63
64 current->next=new_entry;
65
66}
67
68void parse_aes_entry(struct s_reader *rdr,char *value) {
69 ushort caid;
70 ushort dummy;
71 uint32 ident;
72 int len;
73 char *tmp;
74 int nb_keys,key_id;
75 uchar aes_key[16];
76 char *save=NULL;
77
78 tmp=strtok_r(value,"@",&save);
79 caid=a2i(tmp,2);
80 tmp=strtok_r(NULL,":",&save);
81 ident=a2i(tmp,3);
82
83 // now we need to split the key ane add the entry to the reader.
84 nb_keys=0;
85 key_id=0;
86 while((tmp=strtok_r(NULL,",",&save))) {
87 dummy=0;
88 len=strlen(tmp);
89 if(len!=32) {
90 dummy=a2i(tmp,1);
91 // FF means the card will do the AES decrypt
92 // 00 means we don't have the aes.
93 if((dummy!=0xFF && dummy!=0x00) || len>2) {
94 key_id++;
95 cs_log("AES key length error .. not adding");
96 continue;
97 }
98 if(dummy==0x00) {
99 key_id++;
100 continue;
101 }
102 }
103 nb_keys++;
104 if(dummy)
105 memset(aes_key,0xFF,16);
106 else
107 key_atob(tmp,aes_key);
108 // now add the key to the reader... TBD
109 add_aes_entry(rdr,caid,ident,key_id,aes_key);
110 key_id++;
111 }
112
113 cs_log("%d AES key(s) added on reader %s for %04x:%06x", nb_keys, rdr->label, caid, ident);
114}
115
116void parse_aes_keys(struct s_reader *rdr,char *value)
117{
118 // value format is caid1@ident1:key0,key1;caid2@indent2:key0,key1
119 char *entry;
120 char *save=NULL;
121
122 rdr->aes_list=NULL;
123 for (entry=strtok_r(value, ";",&save); entry; entry=strtok_r(NULL, ";",&save)) {
124 parse_aes_entry(rdr,entry);
125 }
126
127 /*
128 AES_ENTRY *current;
129 current=rdr->aes_list;
130 while(current) {
131 cs_log("**************************");
132 cs_log("current = %p",current);
133 cs_log("CAID = %04x",current->caid);
134 cs_log("IDENT = %06x",current->ident);
135 cs_log("keyID = %d",current->keyid);
136 cs_log("next = %p",current->next);
137 cs_log("**************************");
138 current=current->next;
139 }
140 */
141}
142
143int aes_decrypt_from_list(AES_ENTRY *list, ushort caid, uint32 provid,int keyid, uchar *buf, int n)
144{
145 AES_ENTRY *current;
146 AES_KEY dummy;
147 int i;
148 int ok=1;
149 int error=0;
150
151 current=list;
152 while(current) {
153 if(current->caid==caid && current->ident==provid && current->keyid==keyid)
154 break;
155 current=current->next;
156 }
157
158 if(!current) {
159 cs_log("AES Decrypt : key id %d not found for CAID %04X , provider %06x",keyid,caid,provid);
160 return error; // we don't have the key to decode this buffer.
161 }
162 else {
163 // hack for card that do the AES decrypt themsleves
164 memset(&dummy,0,sizeof(AES_KEY));
165 if(!memcmp(&current->key,&dummy,sizeof(AES_KEY))) {
166 return ok;
167 }
168 // decode the key
169 for(i=0; i<n; i+=16)
170 AES_decrypt(buf+i, buf+i, &(current->key));
171 }
172 return ok; // all ok, key decoded.
173}
174
175int aes_present(AES_ENTRY *list, ushort caid, uint32 provid,int keyid)
176{
177 AES_ENTRY *current;
178 int ok=1;
179 int error=0;
180
181 current=list;
182 while(current) {
183 if(current->caid==caid && current->ident==provid && current->keyid==keyid)
184 break;
185 current=current->next;
186 }
187
188 if(!current) {
189 cs_log("AES Decrypt : key id %d not found for CAID %04X , provider %06x",keyid,caid,provid);
190 return error; // we don't have the key to decode this buffer.
191 }
192
193 return ok;
194}
195
196void aes_clear_entries(struct s_reader *rdr)
197{
198
199 AES_ENTRY *current;
200 AES_ENTRY *next;
201
202 current=NULL;
203 next=rdr->aes_list;
204 while(next) {
205 current=next;
206 next=current->next;
207 free(current);
208 }
209 rdr->aes_list=NULL;
210}
211
212char *remote_txt(void)
213{
214 if (client[cs_idx].is_server)
215 return("client");
216 else
217 return("remote server");
218}
219
220char *trim(txt)
221char *txt;
222{
223 register int l;
224 register char *p1, *p2;
225
226 if (*txt==' ')
227 {
228 for (p1=p2=txt;
229 (*p1==' ') || (*p1=='\t') || (*p1=='\n') || (*p1=='\r');
230 p1++);
231 while (*p1)
232 *p2++=*p1++;
233 *p2='\0';
234 }
235 if ((l=strlen(txt))>0)
236 for (p1=txt+l-1;
237 (*p1==' ') || (*p1=='\t') || (*p1=='\n') || (*p1=='\r');
238 *p1--='\0');
239
240 return(txt);
241}
242
243char *strtolower(char *txt)
244{
245 char *p;
246 for (p=txt; *p; p++)
247 if (isupper((uchar)*p)) *p=tolower((uchar)*p);
248 return(txt);
249}
250
251int gethexval(char c)
252{
253 if ((c>='0') && (c<='9')) return(c-'0');
254 if ((c>='A') && (c<='F')) return(c-'A'+10);
255 if ((c>='a') && (c<='f')) return(c-'a'+10);
256 return(-1);
257}
258
259int cs_atob(uchar *buf, char *asc, int n)
260{
261 int i, rc;
262 for (i=0; i<n; i++)
263 {
264 if ((rc=(gethexval(asc[i<<1])<<4)|gethexval(asc[(i<<1)+1]))&0x100)
265 return(-1);
266 buf[i]=rc;
267 }
268 return(n);
269}
270
271ulong cs_atoi(char *asc, int l, int val_on_err)
272{
273 int i, n=0;
274 ulong rc=0;
275 for (i=((l-1)<<1), errno=0; (i>=0) && (n<4); i-=2)
276 {
277 int b;
278 b=(gethexval(asc[i])<<4) | gethexval(asc[i+1]);
279 if (b<0)
280 {
281 errno=EINVAL;
282 rc=(val_on_err) ? 0xFFFFFFFF : 0;
283 break;
284 }
285 rc|=b<<(n<<3);
286 n++;
287 }
288 return(rc);
289}
290
291int byte_atob(char *asc)
292{
293 int rc;
294
295 if (strlen(trim(asc))!=2)
296 rc=(-1);
297 else
298 if ((rc=(gethexval(asc[0])<<4)|gethexval(asc[1]))&0x100)
299 rc=(-1);
300 return(rc);
301}
302
303long word_atob(char *asc)
304{
305 long rc;
306
307 if (strlen(trim(asc))!=4)
308 rc=(-1);
309 else
310 {
311 rc=gethexval(asc[0])<<12 | gethexval(asc[1])<<8 |
312 gethexval(asc[2])<<4 | gethexval(asc[3]);
313 if (rc&0x10000)
314 rc=(-1);
315 }
316 return(rc);
317}
318
319/*
320 * dynamic word_atob
321 * converts an 1-4 digit asc hexstring
322 */
323long dyn_word_atob(char *asc)
324{
325 long rc = (-1);
326 int i, len = strlen(trim(asc));
327
328 if (len <= 4 && len > 0) {
329 for(i = 0, rc = 0; i < len; i++)
330 rc = rc << 4 | gethexval(asc[i]);
331
332 if (rc & 0x10000)
333 rc = (-1);
334 }
335 return(rc);
336}
337
338int key_atob(char *asc, uchar *bin)
339{
340 int i, n1, n2, rc;
341 for (i=rc=0; i<32; i+=2)
342 {
343 if ((n1=gethexval(asc[i ]))<0) rc=(-1);
344 if ((n2=gethexval(asc[i+1]))<0) rc=(-1);
345 bin[i>>1]=(n1<<4)+(n2&0xff);
346 }
347 return(rc);
348}
349
350int key_atob14(char *asc, uchar *bin)
351{
352 int i, n1, n2, rc;
353 for (i=rc=0; i<28; i+=2)
354 {
355 if ((n1=gethexval(asc[i ]))<0) rc=(-1);
356 if ((n2=gethexval(asc[i+1]))<0) rc=(-1);
357 bin[i>>1]=(n1<<4)+(n2&0xff);
358 }
359 return(rc);
360}
361
362int key_atob_l(char *asc, uchar *bin, int l)
363{
364 int i, n1, n2, rc;
365 for (i=rc=0; i<l; i+=2)
366 {
367 if ((n1=gethexval(asc[i ]))<0) rc=(-1);
368 if ((n2=gethexval(asc[i+1]))<0) rc=(-1);
369 bin[i>>1]=(n1<<4)+(n2&0xff);
370 }
371 return(rc);
372}
373
374char *key_btoa(char *asc, uchar *bin)
375{
376 int i;//, n1, n2, rc;
377 static char buf[33];
378 if (!asc)
379 asc=buf;
380 for (i=0; i<16; i++)
381 sprintf(asc+(i<<1), "%02X", bin[i]);
382 return(asc);
383}
384
385char *cs_hexdump(int m, const uchar *buf, int n)
386{
387 int i;
388 static char dump[520];
389
390 dump[i=0]='\0';
391 m=(m)?3:2;
392 if (m*n>=(int)sizeof(dump)) n=(sizeof(dump)/m)-1;
393 while (i<n)
394 sprintf(dump+(m*i++), "%02X%s", *buf++, (m>2)?" ":"");
395 return(dump);
396}
397
398static int inet_byteorder=0;
399in_addr_t cs_inet_order(in_addr_t n)
400{
401 if (!inet_byteorder)
402 inet_byteorder=((inet_addr("1.2.3.4")+1)==inet_addr("1.2.3.5")) ? 1 : 2;
403 switch (inet_byteorder)
404 {
405 case 1:
406 break;
407 case 2:
408 n=((n&0xff000000) >> 24 ) |
409 ((n&0x00ff0000) >> 8 ) |
410 ((n&0x0000ff00) << 8 ) |
411 ((n&0x000000ff) << 24 );
412 break;
413 }
414 return(n);
415}
416
417char *cs_inet_ntoa(in_addr_t n)
418{
419 struct in_addr in;
420 in.s_addr=cs_inet_order(n);
421 return((char *)inet_ntoa(in));
422}
423
424in_addr_t cs_inet_addr(char *txt)
425{
426 if (!inet_byteorder)
427 inet_byteorder=((inet_addr("1.2.3.4")+1)==inet_addr("1.2.3.5")) ? 1 : 2;
428 if (inet_byteorder == 1)
429 return(inet_addr(txt));
430 else
431 return(inet_network(txt));
432}
433
434ulong b2i(int n, uchar *b)
435{
436 switch(n)
437 {
438 case 2:
439 return ((b[0]<<8) | b[1]);
440 case 3:
441 return ((b[0]<<16) | (b[1]<<8) | b[2]);
442 case 4:
443 return (((b[0]<<24) | (b[1]<<16) | (b[2]<<8) | b[3]) & 0xffffffffL);
444 default:
445 cs_log("Error in b2i, n=%i",n);
446 }
447 return 0;
448}
449
450ullong b2ll(int n, uchar *b)
451{
452 int i;
453 ullong k=0;
454 for(i=0; i<n; k+=b[i++])
455 k<<=8;
456 return(k);
457}
458
459uchar *i2b(int n, ulong i)
460{
461 static uchar b[4];
462 switch(n)
463 {
464 case 2:
465 b[0]=(i>> 8) & 0xff;
466 b[1]=(i ) & 0xff;
467 break;
468 case 3:
469 b[0]=(i>>16) & 0xff;
470 b[1]=(i>> 8) & 0xff;
471 b[2]=(i ) & 0xff;
472 case 4:
473 b[0]=(i>>24) & 0xff;
474 b[1]=(i>>16) & 0xff;
475 b[2]=(i>> 8) & 0xff;
476 b[3]=(i ) & 0xff;
477 break;
478 }
479 return(b);
480}
481
482ulong a2i(char *asc, int bytes)
483{
484 int i, n;
485 ulong rc;
486 for (rc=i=0, n=strlen(trim(asc))-1; i<(abs(bytes)<<1); n--, i++)
487 if (n>=0)
488 {
489 int rcl;
490 if ((rcl=gethexval(asc[n]))<0)
491 {
492 errno=EINVAL;
493 return(0x1F1F1F);
494 }
495 rc|=(rcl<<(i<<2));
496 }
497 else
498 if (bytes<0)
499 rc|=(0xf<<(i<<2));
500 errno=0;
501 return(rc);
502}
503
504int boundary(int exp, int n)
505{
506 return((((n-1)>>exp)+1)<<exp);
507}
508
509void cs_ftime(struct timeb *tp)
510{
511#ifdef NO_FTIME
512 struct timeval tv;
513 gettimeofday(&tv, (struct timezone *)0);
514 tp->time=tv.tv_sec;
515 tp->millitm=tv.tv_usec/1000;
516#else
517 ftime(tp);
518#endif
519}
520
521void cs_sleepms(unsigned int msec)
522{
523 //does not interfere with signals like sleep and usleep do
524 struct timespec req_ts;
525 req_ts.tv_sec = msec/1000;
526 req_ts.tv_nsec = (msec % 1000) * 1000000L;
527 nanosleep (&req_ts, NULL);
528}
529
530void cs_sleepus(unsigned int usec)
531{
532 //does not interfere with signals like sleep and usleep do
533 struct timespec req_ts;
534 req_ts.tv_sec = usec/1000000;
535 req_ts.tv_nsec = (usec % 1000000) * 1000L;
536 nanosleep (&req_ts, NULL);
537}
538
539int bytes_available(int fd)
540{
541 fd_set rfds;
542 fd_set erfds;
543 int select_ret;
544 int in_fd;
545
546 in_fd=fd;
547
548 FD_ZERO(&rfds);
549 FD_SET(in_fd, &rfds);
550
551 FD_ZERO(&erfds);
552 FD_SET(in_fd, &erfds);
553
554 select_ret = select(in_fd+1, &rfds, NULL, &erfds, NULL);
555 if (select_ret==-1)
556 {
557 cs_log("ERROR reading from fd %d select_ret=%i, errno=%d",in_fd, select_ret, errno);
558 return 0;
559 }
560
561 if (FD_ISSET(in_fd, &erfds))
562 {
563 cs_log("ERROR reading from fd %d select_ret=%i, errno=%d",in_fd, select_ret, errno);
564 return 0;
565 }
566 if (FD_ISSET(in_fd,&rfds))
567 return 1;
568 else
569 return 0;
570}
571
572
573#ifdef OS_CYGWIN32
574#include <windows.h>
575void cs_setpriority(int prio)
576{
577 HANDLE WinId;
578 ulong wprio;
579 switch((prio+20)/10)
580 {
581 case 0: wprio=REALTIME_PRIORITY_CLASS; break;
582 case 1: wprio=HIGH_PRIORITY_CLASS; break;
583 case 2: wprio=NORMAL_PRIORITY_CLASS; break;
584 default: wprio=IDLE_PRIORITY_CLASS; break;
585 }
586 WinId=GetCurrentProcess();
587 SetPriorityClass(WinId, wprio);
588}
589#else
590void cs_setpriority(int prio)
591{
592#ifdef PRIO_PROCESS
593 setpriority(PRIO_PROCESS, 0, prio); // ignore errors
594#endif
595}
596#endif
597
598#ifdef WEBIF
599/* Helper function for urldecode.*/
600int x2i(int i){
601 i=toupper(i);
602 i = i - '0';
603 if(i > 9) i = i - 'A' + '9' + 1;
604 return i;
605}
606
607/* Decodes values in a http url */
608void urldecode(char *s){
609 int c, c1, n;
610 char *s0,*t;
611 t = s0 = s;
612 n = strlen(s);
613 while(n >0){
614 c = *s++;
615 if(c == '+') c = ' ';
616 else if(c == '%' && n > 2){
617 c = *s++;
618 c1 = c;
619 c = *s++;
620 c = 16*x2i(c1) + x2i(c);
621 n -= 2;
622 }
623 *t++ = c;
624 n--;
625 }
626 *t = 0;
627}
628
629/* Helper function for urlencode.*/
630char to_hex(char code){
631 static const char hex[] = "0123456789abcdef";
632 return hex[(int)code & 15];
633}
634
635/* Encode values in a http url. Note: Be sure to free() the returned string after use */
636char *urlencode(char *str){
637 char *pstr = str, *buf = (char *) malloc((strlen(str) * 3 + 1) * sizeof(char)), *pbuf = buf;
638 while (*pstr) {
639 if (isalnum(*pstr) || *pstr == '-' || *pstr == '_' || *pstr == '.' || *pstr == '~') *pbuf++ = *pstr;
640 else if (*pstr == ' ') *pbuf++ = '+';
641 else {
642 *pbuf++ = '%';
643 *pbuf++ = to_hex(*pstr >> 4);
644 *pbuf++ = to_hex(*pstr & 15);
645 }
646 ++pstr;
647 }
648 *pbuf = '\0';
649 pbuf = (char *) malloc((strlen(buf) + 1) * sizeof(char));
650 strcpy(pbuf, buf);
651 free(buf);
652 return pbuf;
653}
654
655/* Converts a char array to a char array with hex values (needed for example for md5). The hex2ascii
656 array is a lookup table with the corresponding hex string on the array position of the integer representation
657 of the ascii value. Note that you need to "free" the resulting array after usage or you'll get a memory leak!*/
658char *char_to_hex(const unsigned char* p_array, unsigned int p_array_len, char hex2ascii[256][2]) {
659 unsigned char* str = (unsigned char*)malloc(p_array_len*2+1);
660 str[p_array_len*2] = '\0';
661 const unsigned char* p_end = p_array + p_array_len;
662 size_t pos=0;
663 const unsigned char* p;
664 for( p = p_array; p != p_end; p++, pos+=2 ) {
665 str[pos] = hex2ascii[*p][0];
666 str[pos+1] = hex2ascii[*p][1];
667 }
668 return (char*)str;
669}
670
671/* Creates a random string with specified length. Note that dst must be one larger than size to hold the trailing \0*/
672void create_rand_str(char *dst, int size){
673 static const char text[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
674 int i;
675 for (i = 0; i < size; ++i){
676 dst[i] = text[rand() % (sizeof(text) - 1)];
677 }
678 dst[i] = '\0';
679}
680#endif
681
682/* Converts a long value to a char array in bitwise representation.
683 Note that the result array MUST be at least 33 bit large and that
684 this function assumes long values to hold only values up to 32bits and to be positive!
685 the result of e.g. long 7 is 11100000000000000000000000000000 this means the array
686 is reversed */
687void long2bitchar(long value, char *result){
688 int pos;
689 for (pos=0;pos<32;pos++) result[pos]='0';
690 result[pos] = '\0';
691
692 pos=0;
693 while (value > 0 && pos < 32){
694 if(value % 2 == 1) result[pos]='1';
695 else result[pos]='0';
696 value=value / 2;
697 pos++;
698 }
699}
700
701/* Return 1 if the file exists, else 0 */
702int file_exists(const char * filename){
703 FILE *file;
704 if ((file = fopen(filename, "r"))){
705 fclose(file);
706 return 1;
707 }
708 return 0;
709}
710
711/* Clears the s_ip structure provided. The pointer will be set to NULL so everything is cleared.*/
712void clear_sip(struct s_ip **sip){
713 struct s_ip *cip = *sip, *lip;
714 for (*sip = NULL; cip != NULL; cip = lip){
715 lip = cip->next;
716 free(cip);
717 }
718}
719
720/* Clears the s_ftab struct provided by setting nfilts and nprids to zero. */
721void clear_ftab(struct s_ftab *ftab){
722 int i, j;
723 for (i = 0; i < CS_MAXFILTERS; i++) {
724 ftab->filts[i].caid = 0;
725 for (j = 0; j < CS_MAXPROV; j++)
726 ftab->filts[i].prids[j] = 0;
727 ftab->filts[i].nprids = 0;
728 }
729 ftab->nfilts = 0;
730}
731
732/* Clears the s_ptab struct provided by setting nfilts and nprids to zero. */
733void clear_ptab(struct s_ptab *ptab){
734 int i;
735 for (i = 0; i < ptab->nports; i++) {
736 ptab->ports[i].ftab.nfilts = 0;
737 ptab->ports[i].ftab.filts[0].nprids = 0;
738 }
739 ptab->nports = 0;
740}
741
742/* Clears given caidtab */
743void clear_caidtab(struct s_caidtab *ctab){
744 int i;
745 for (i = 0; i < CS_MAXCAIDTAB; i++) {
746 ctab->caid[i] = 0;
747 ctab->mask[i] = 0;
748 ctab->cmap[i] = 0;
749 }
750}
751
752/* Clears given tuntab */
753void clear_tuntab(struct s_tuntab *ttab){
754 int i;
755 for (i = 0; i < CS_MAXTUNTAB; i++) {
756 ttab->bt_caidfrom[i] = 0;
757 ttab->bt_caidto[i] = 0;
758 ttab->bt_srvid[i] = 0;
759 }
760}
761/* Overwrites destfile with tmpfile. If forceBakOverWrite = 0, the bakfile will not be overwritten if it exists, else it will be.*/
762int safe_overwrite_with_bak(char *destfile, char *tmpfile, char *bakfile, int forceBakOverWrite){
763 if (file_exists(destfile)) {
764 if(forceBakOverWrite != 0 && file_exists(bakfile)){
765 if(remove(bakfile) < 0) cs_log("Error removing backup conf file %s (errno=%d)! Will try to proceed nonetheless...", bakfile, errno);
766 }
767 if(file_exists(bakfile)){
768 if(remove(destfile) < 0) {
769 cs_log("Error removing original conf file %s (errno=%d). Will maintain original one!", destfile, errno);
770 if(remove(tmpfile) < 0) cs_log("Error removing temp conf file %s (errno=%d)!", tmpfile, errno);
771 return(1);
772 }
773 } else {
774 if(rename(destfile, bakfile) < 0){
775 cs_log("Error renaming original conf file %s to %s (errno=%d). Will maintain original one!", destfile, bakfile, errno);
776 if(remove(tmpfile) < 0) cs_log("Error removing temp conf file %s (errno=%d)!", tmpfile, errno);
777 return(1);
778 }
779 }
780 if(rename(tmpfile, destfile) < 0){
781 cs_log("Error renaming new conf file %s to %s (errno=%d). The config will be missing upon next startup as this is non-recoverable!", tmpfile, destfile, errno);
782 return(1);
783 }
784 } else {
785 if(rename(tmpfile, destfile) < 0){
786 cs_log("Error renaming new conf file %s to %s (errno=%d). The config will be missing upon next startup as this is non-recoverable!", tmpfile, destfile, errno);
787 return(1);
788 }
789 }
790 return(0);
791}
792
793/* Replacement of fprintf which adds necessary whitespace to fill up the varname to a fixed width.
794 If varname is longer than varnameWidth, no whitespace is added*/
795void fprintf_conf(FILE *f, int varnameWidth, const char *varname, const char *fmtstring, ...){
796 int varlen = strlen(varname);
797 int max = (varlen > varnameWidth) ? varlen : varnameWidth;
798 char varnamebuf[max + 3];
799 char *ptr = varnamebuf + varlen;
800 va_list argptr;
801
802 strcpy(varnamebuf, varname);
803 while(varlen < varnameWidth){
804 ptr[0] = ' ';
805 ++ptr;
806 ++varlen;
807 }
808 strcpy(ptr, "= ");
809 fwrite(varnamebuf, sizeof(char), strlen(varnamebuf), f);
810 if(strlen(fmtstring) > 0){
811 va_start(argptr, fmtstring);
812 vfprintf(f, fmtstring, argptr);
813 va_end(argptr);
814 }
815}
816
817/* Ordinary strncpy does not terminate the string if the source is exactly as long or longer as the specified size. This can raise security issues.
818 This function is a replacement which makes sure that a \0 is always added. num should be the real size of char array (do not subtract -1). */
819void cs_strncpy(char * destination, const char * source, size_t num){
820 uint32 l, size = strlen(source);
821 if(size > num - 1) l = num - 1;
822 else l = size;
823 memcpy(destination, source, l);
824 destination[l] = '\0';
825}
826
827char *get_servicename(int srvid, int caid){
828 int i;
829 struct s_srvid *this = cfg->srvid;
830 static char name[83];
831
832 for (name[0] = 0; this && (!name[0]); this = this->next)
833 if (this->srvid == srvid)
834 for (i=0; i<this->ncaid; i++)
835 if (this->caid[i] == caid)
836 cs_strncpy(name, this->name, 32);
837
838 if (!name[0]) sprintf(name, "%04X:%04X unknown", caid, srvid);
839 if (!srvid) name[0] = '\0';
840 return(name);
841}
842
843char *get_tiername(int tierid, int caid){
844 int i;
845 struct s_tierid *this = cfg->tierid;
846 static char name[83];
847
848 for (name[0] = 0; this && (!name[0]); this = this->next)
849 if (this->tierid == tierid)
850 for (i=0; i<this->ncaid; i++)
851 if (this->caid[i] == caid)
852 cs_strncpy(name, this->name, 32);
853
854 //if (!name[0]) sprintf(name, "%04X:%04X unknown", caid, tierid);
855 if (!tierid) name[0] = '\0';
856 return(name);
857}
858
859char *get_provider(int caid, ulong provid){
860 struct s_provid *this = cfg->provid;
861 static char name[83];
862
863 for (name[0] = 0; this && (!name[0]); this = this->next)
864 if (this->caid == caid && this->provid == provid)
865 snprintf(name, 83, "%s / %s / %s", this->prov, this->sat, this->lang);
866
867 if (!name[0]) snprintf(name, 83, "%04X:%06lX unknown", caid, provid);
868 if (!caid) name[0] = '\0';
869 return(name);
870}
871
872void make_non_blocking(int fd) {
873 int fl;
874 fl=fcntl(fd, F_GETFL);
875 fcntl(fd, F_SETFL, fl | O_NONBLOCK | O_NDELAY);
876}
Note: See TracBrowser for help on using the repository browser.