thermferm/rdconfig.c

changeset 80
81bf78a7618e
parent 78
c49ab5179bf3
child 82
d48299405980
equal deleted inserted replaced
79:eb9dd60aa791 80:81bf78a7618e
71 71
72 72
73 void killconfig(void) 73 void killconfig(void)
74 { 74 {
75 w1_therm *tmp1, *old1; 75 w1_therm *tmp1, *old1;
76 units_list *tmp2;
76 77
77 if (Config.name) 78 if (Config.name)
78 free(Config.name); 79 free(Config.name);
79 Config.name = NULL; 80 Config.name = NULL;
80 81
88 free(tmp1->alias); 89 free(tmp1->alias);
89 free(tmp1); 90 free(tmp1);
90 } 91 }
91 Config.w1therms = NULL; 92 Config.w1therms = NULL;
92 Config.my_port = 6554; 93 Config.my_port = 6554;
94 Config.tempFormat = 'C';
95
96 for (tmp2 = Config.units; tmp2; tmp2 = tmp2->next) {
97 if (tmp2->uuid)
98 free(tmp2->uuid);
99 if (tmp2->name)
100 free(tmp2->name);
101 if (tmp2->air_address)
102 free(tmp2->air_address);
103 if (tmp2->beer_address)
104 free(tmp2->beer_address);
105 if (tmp2->io1_address)
106 free(tmp2->io1_address);
107 if (tmp2->io2_address)
108 free(tmp2->io2_address);
109 if (tmp2->profile)
110 free(tmp2->profile);
111 free(tmp2);
112 }
113 Config.units = NULL;
93 114
94 #ifdef HAVE_WIRINGPI_H 115 #ifdef HAVE_WIRINGPI_H
95 Config.lcd_cols = 16; 116 Config.lcd_cols = 16;
96 Config.lcd_rows = 2; 117 Config.lcd_rows = 2;
97 #endif 118 #endif
345 } 366 }
346 if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "UUID", "%s", tmp3->uuid)) < 0) { 367 if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "UUID", "%s", tmp3->uuid)) < 0) {
347 syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement"); 368 syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement");
348 return 1; 369 return 1;
349 } 370 }
350 if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "NAME", "%s", MBSE_SS(tmp3->name))) < 0) { 371 if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "NAME", "%s", tmp3->name)) < 0) {
351 syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement"); 372 syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement");
352 return 1; 373 return 1;
353 } 374 }
354 if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "VOLUME", "%.1f", tmp3->volume)) < 0) { 375 if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "VOLUME", "%.1f", tmp3->volume)) < 0) {
355 syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement"); 376 syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement");
356 return 1; 377 return 1;
357 } 378 }
358 if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "AIR_ADDRESS", "%s", MBSE_SS(tmp3->air_address))) < 0) { 379 if (tmp3->air_address && ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "AIR_ADDRESS", "%s", tmp3->air_address)) < 0)) {
359 syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement"); 380 syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement");
360 return 1; 381 return 1;
361 } 382 }
362 if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "BEER_ADDRESS", "%s", MBSE_SS(tmp3->beer_address))) < 0) { 383 if (tmp3->beer_address && ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "BEER_ADDRESS", "%s", tmp3->beer_address)) < 0)) {
363 syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement"); 384 syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement");
364 return 1; 385 return 1;
365 } 386 }
366 if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "IO1_ADDRESS", "%s", MBSE_SS(tmp3->io1_address))) < 0) { 387 if (tmp3->io1_address && ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "IO1_ADDRESS", "%s", tmp3->io1_address)) < 0)) {
367 syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement"); 388 syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement");
368 return 1; 389 return 1;
369 } 390 }
370 if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "IO2_ADDRESS", "%s", MBSE_SS(tmp3->io2_address))) < 0) { 391 if (tmp3->io2_address && ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "IO2_ADDRESS", "%s", tmp3->io2_address)) < 0)) {
371 syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement"); 392 syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement");
372 return 1; 393 return 1;
373 } 394 }
374 if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "HEATER", "%s", tmp3->heater_available ? "YES":"NO")) < 0) { 395 if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "HEATER", "%s", tmp3->heater_available ? "YES":"NO")) < 0) {
375 syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement"); 396 syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement");
467 return rc; 488 return rc;
468 } 489 }
469 490
470 491
471 492
493 /*
494 * Parse one LCD display
495 */
496 #ifdef HAVE_WIRINGPI_H
497 int parseLCD(xmlDocPtr doc, xmlNodePtr cur)
498 {
499 xmlChar *key;
500 int ival;
501
502 cur = cur->xmlChildrenNode;
503 while (cur != NULL) {
504 if ((!xmlStrcmp(cur->name, (const xmlChar *)"COLUMNS"))) {
505 key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
506 if (sscanf((const char *)key, "%d", &ival) == 1)
507 Config.lcd_cols = ival;
508 xmlFree(key);
509 }
510 if ((!xmlStrcmp(cur->name, (const xmlChar *)"ROWS"))) {
511 key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
512 if (sscanf((const char *)key, "%d", &ival) == 1)
513 Config.lcd_rows = ival;
514 xmlFree(key);
515 }
516 if ((!xmlStrcmp(cur->name, (const xmlChar *)"ADDRESS"))) {
517 key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
518 if (sscanf((const char *)key, "%x", &ival) == 1)
519 Config.lcd_address = ival;
520 xmlFree(key);
521 }
522 cur = cur->next;
523 }
524
525 return 0;
526 }
527
528
529
530 int parseLCDs(xmlDocPtr doc, xmlNodePtr cur)
531 {
532 cur = cur->xmlChildrenNode;
533 while (cur != NULL) {
534 if ((!xmlStrcmp(cur->name, (const xmlChar *)"LCD"))) {
535 parseLCD(doc, cur);
536 }
537 cur = cur->next;
538 }
539 return 0;
540 }
541 #endif
542
543
544
545 int parseW1therm(xmlDocPtr doc, xmlNodePtr cur)
546 {
547 xmlChar *key;
548 int ival;
549 w1_therm *w1therm, *tmp;
550
551 w1therm = (w1_therm *)malloc(sizeof(w1_therm));
552 w1therm->next = NULL;
553 w1therm->master = w1therm->name = w1therm->alias = NULL;
554 w1therm->bus = w1therm->present = w1therm->lastval = w1therm->update = 0;
555
556 cur = cur->xmlChildrenNode;
557 while (cur != NULL) {
558 if ((!xmlStrcmp(cur->name, (const xmlChar *)"VERSION"))) {
559 key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
560 if (xmlStrcmp(key, (const xmlChar *)"1")) {
561 xmlFree(key);
562 return 1;
563 }
564 xmlFree(key);
565 }
566 if ((!xmlStrcmp(cur->name, (const xmlChar *)"MASTER"))) {
567 w1therm->master = (char *)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
568 }
569 if ((!xmlStrcmp(cur->name, (const xmlChar *)"BUS"))) {
570 key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
571 if (sscanf((const char *)key, "%d", &ival) == 1)
572 w1therm->bus = ival;
573 xmlFree(key);
574 }
575 if ((!xmlStrcmp(cur->name, (const xmlChar *)"NAME"))) {
576 w1therm->name = (char *)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
577 }
578 if ((!xmlStrcmp(cur->name, (const xmlChar *)"ALIAS"))) {
579 w1therm->alias = (char *)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
580 }
581 cur = cur->next;
582 }
583
584 if (Config.w1therms == NULL) {
585 Config.w1therms = w1therm;
586 } else {
587 for (tmp = Config.w1therms; tmp; tmp = tmp->next) {
588 if (tmp->next == NULL) {
589 tmp->next = w1therm;
590 break;
591 }
592 }
593 }
594
595 return 0;
596 }
597
598
599
600 int parseW1therms(xmlDocPtr doc, xmlNodePtr cur)
601 {
602 cur = cur->xmlChildrenNode;
603 while (cur != NULL) {
604 if ((!xmlStrcmp(cur->name, (const xmlChar *)"W1TERM"))) {
605 parseW1therm(doc, cur);
606 }
607 cur = cur->next;
608 }
609 return 0;
610 }
611
612
613
614 /*
615 * Parse a fermenter unit
616 */
617 int parseUnit(xmlDocPtr doc, xmlNodePtr cur)
618 {
619 xmlChar *key;
620 int i, ival;
621 float val;
622 units_list *unit, *tmp;
623
624 unit = (units_list *)malloc(sizeof(units_list));
625 unit->next = NULL;
626 unit->uuid = unit->name = unit->air_address = unit->beer_address = unit->io1_address = unit->io2_address = unit->profile = NULL;
627 unit->volume = 0.0;
628 unit->heater_available = unit->cooler_available = unit->fan_available = FALSE;
629 unit->air_temp = unit->beer_temp = unit->beer_set = unit->fridge_set = 20.0;
630 unit->heater_state = unit->cooler_state = unit->fan_state = unit->door_state = unit->mode = 0;
631 unit->temp_set_min = 1.0;
632 unit->temp_set_max = 30.0;
633 unit->idle_rangeH = 1.0;
634 unit->idle_rangeL = -1.0;
635 unit->prof_started = (time_t)0;
636
637 cur = cur->xmlChildrenNode;
638 while (cur != NULL) {
639 if ((!xmlStrcmp(cur->name, (const xmlChar *)"VERSION"))) {
640 key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
641 if (xmlStrcmp(key, (const xmlChar *)"1")) {
642 xmlFree(key);
643 return 1;
644 }
645 xmlFree(key);
646 }
647 if ((!xmlStrcmp(cur->name, (const xmlChar *)"UUID"))) {
648 unit->uuid = (char *)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
649 }
650 if ((!xmlStrcmp(cur->name, (const xmlChar *)"NAME"))) {
651 unit->name = (char *)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
652 }
653 if ((!xmlStrcmp(cur->name, (const xmlChar *)"VOLUME"))) {
654 key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
655 if (sscanf((const char *)key, "%f", &val) == 1)
656 unit->volume = val;
657 xmlFree(key);
658 }
659 if ((!xmlStrcmp(cur->name, (const xmlChar *)"AIR_ADDRESS"))) {
660 unit->air_address = (char *)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
661 }
662 if ((!xmlStrcmp(cur->name, (const xmlChar *)"BEER_ADDRESS"))) {
663 unit->beer_address = (char *)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
664 }
665 if ((!xmlStrcmp(cur->name, (const xmlChar *)"IO1_ADDRESS"))) {
666 unit->io1_address = (char *)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
667 }
668 if ((!xmlStrcmp(cur->name, (const xmlChar *)"IO2_ADDRESS"))) {
669 unit->io2_address = (char *)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
670 }
671 if ((!xmlStrcmp(cur->name, (const xmlChar *)"HEATER"))) {
672 key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
673 if (! xmlStrcmp(key, (const xmlChar *)"TRUE"))
674 unit->heater_available = TRUE;
675 xmlFree(key);
676 }
677 if ((!xmlStrcmp(cur->name, (const xmlChar *)"COOLER"))) {
678 key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
679 if (! xmlStrcmp(key, (const xmlChar *)"TRUE"))
680 unit->cooler_available = TRUE;
681 xmlFree(key);
682 }
683 if ((!xmlStrcmp(cur->name, (const xmlChar *)"FAN"))) {
684 key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
685 if (! xmlStrcmp(key, (const xmlChar *)"TRUE"))
686 unit->fan_available = TRUE;
687 xmlFree(key);
688 }
689 if ((!xmlStrcmp(cur->name, (const xmlChar *)"MODE"))) {
690 key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
691 for (i = 0; i < 5; i++) {
692 if (! xmlStrcmp(key, (const xmlChar *)UNITMODE[i])) {
693 unit->mode = i;
694 break;
695 }
696 }
697 xmlFree(key);
698 }
699 if ((!xmlStrcmp(cur->name, (const xmlChar *)"BEER_SET"))) {
700 key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
701 if (sscanf((const char *)key, "%f", &val) == 1)
702 unit->beer_set = val;
703 xmlFree(key);
704 }
705 if ((!xmlStrcmp(cur->name, (const xmlChar *)"FRIDGE_SET"))) {
706 key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
707 if (sscanf((const char *)key, "%f", &val) == 1)
708 unit->fridge_set = val;
709 xmlFree(key);
710 }
711 if ((!xmlStrcmp(cur->name, (const xmlChar *)"TEMP_SET_MIN"))) {
712 key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
713 if (sscanf((const char *)key, "%f", &val) == 1)
714 unit->temp_set_min = val;
715 xmlFree(key);
716 }
717 if ((!xmlStrcmp(cur->name, (const xmlChar *)"TEMP_SET_MAX"))) {
718 key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
719 if (sscanf((const char *)key, "%f", &val) == 1)
720 unit->temp_set_max = val;
721 xmlFree(key);
722 }
723 if ((!xmlStrcmp(cur->name, (const xmlChar *)"IDLE_RANGE_L"))) {
724 key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
725 if (sscanf((const char *)key, "%f", &val) == 1)
726 unit->idle_rangeL = val;
727 xmlFree(key);
728 }
729 if ((!xmlStrcmp(cur->name, (const xmlChar *)"IDLE_RANGE_H"))) {
730 key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
731 if (sscanf((const char *)key, "%f", &val) == 1)
732 unit->idle_rangeH = val;
733 xmlFree(key);
734 }
735 if ((!xmlStrcmp(cur->name, (const xmlChar *)"PROFILE"))) {
736 unit->profile = (char *)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
737 }
738 if ((!xmlStrcmp(cur->name, (const xmlChar *)"PROF_STARTED"))) {
739 key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
740 if (sscanf((const char *)key, "%d", &ival) == 1)
741 unit->prof_started = ival;
742 xmlFree(key);
743 }
744 cur = cur->next;
745 }
746
747 if (Config.units == NULL) {
748 Config.units = unit;
749 } else {
750 for (tmp = Config.units; tmp; tmp = tmp->next) {
751 if (tmp->next == NULL) {
752 tmp->next = unit;
753 break;
754 }
755 }
756 }
757
758 return 0;
759 }
760
761
762
763 int parseFermenters(xmlDocPtr doc, xmlNodePtr cur)
764 {
765 cur = cur->xmlChildrenNode;
766 while (cur != NULL) {
767 if ((!xmlStrcmp(cur->name, (const xmlChar *)"UNIT"))) {
768 parseUnit(doc, cur);
769 }
770 cur = cur->next;
771 }
772 return 0;
773 }
774
775
776
472 int rdconfig(char *config) 777 int rdconfig(char *config)
473 { 778 {
474 char buf[256], *p; 779 // char buf[256], *p;
475 FILE *fp; 780 // FILE *fp;
476 int i, rc = 0; 781 // int i, rc = 0;
782 int rc = 0, ival;
783 xmlDocPtr doc;
784 xmlNodePtr cur;
785 xmlChar *key;
477 786
478 killconfig(); 787 killconfig();
479 788
480 syslog(LOG_NOTICE, "HOME='%s' USER='%s' LOGNAME='%s'", MBSE_SS(getenv((char *)"HOME")), MBSE_SS(getenv((char *)"USER")), MBSE_SS(getenv((char *)"LOGNAME"))); 789 syslog(LOG_NOTICE, "HOME='%s' USER='%s' LOGNAME='%s'", MBSE_SS(getenv((char *)"HOME")), MBSE_SS(getenv((char *)"USER")), MBSE_SS(getenv((char *)"LOGNAME")));
481 790
487 } else { 796 } else {
488 mypath = xstrcpy(getenv((char *)"HOME")); 797 mypath = xstrcpy(getenv((char *)"HOME"));
489 } 798 }
490 mypath = xstrcat(mypath, (char *)"/mbsepi-apps/"); 799 mypath = xstrcat(mypath, (char *)"/mbsepi-apps/");
491 mypath = xstrcat(mypath, config); 800 mypath = xstrcat(mypath, config);
492 if ((fp = fopen(mypath, "r")) == NULL) { 801 if ((doc = xmlParseFile(mypath)) == NULL) {
802 //if ((fp = fopen(mypath, "r")) == NULL) {
493 /* 803 /*
494 * Not in the users home directory 804 * Not in the users home directory
495 */ 805 */
496 free(mypath); 806 free(mypath);
497 mypath = xstrcpy((char *)"/etc/mbsepi-apps/"); 807 mypath = xstrcpy((char *)"/etc/mbsepi-apps/");
498 mypath = xstrcat(mypath, config); 808 mypath = xstrcat(mypath, config);
499 if ((fp = fopen(mypath, "r")) == NULL) { 809 if ((doc = xmlParseFile(mypath)) == NULL) {
810 //if ((fp = fopen(mypath, "r")) == NULL) {
500 /* 811 /*
501 * Try /usr/local/etc 812 * Try /usr/local/etc
502 */ 813 */
503 free(mypath); 814 free(mypath);
504 mypath = xstrcpy((char *)"/usr/local/etc/mbsepi-apps/"); 815 mypath = xstrcpy((char *)"/usr/local/etc/mbsepi-apps/");
505 mypath = xstrcat(mypath, config); 816 mypath = xstrcat(mypath, config);
506 if ((fp = fopen(mypath, "r")) == NULL) { 817 if ((doc = xmlParseFile(mypath)) == NULL) {
507 syslog(LOG_NOTICE, "rdconfig: could find %s", config); 818 //if ((fp = fopen(mypath, "r")) == NULL) {
819 syslog(LOG_NOTICE, "rdconfig: could not parse %s", config);
508 return 1; 820 return 1;
509 } 821 }
510 } 822 }
511 } 823 }
512 syslog(LOG_NOTICE, "rdconfig: using %s", mypath); 824 syslog(LOG_NOTICE, "rdconfig: using %s", mypath);
513 825
826 if ((cur = xmlDocGetRootElement(doc)) == NULL) {
827 syslog(LOG_NOTICE, "XML file %s empty.", mypath);
828 xmlFreeDoc(doc);
829 return 1;
830 }
831 if (xmlStrcmp(cur->name, (const xmlChar*)"THERMFERM")) {
832 syslog(LOG_NOTICE, "XML file %s is not a valid configuration file.\n", mypath);
833 xmlFreeDoc(doc);
834 return 1;
835 }
836
837 /*
838 * Parse configuration
839 */
840 cur = cur->xmlChildrenNode;
841 while (cur != NULL) {
842 // VERSION LISTEN_PORT TEMPFORMAT LCDS FERMENTERS
843 // if ((!xmlStrcmp(cur->name, (const xmlChar *)"VERSION"))) {
844 // recipe->name = (char *)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
845 // }
846 if ((!xmlStrcmp(cur->name, (const xmlChar *)"LISTEN_PORT"))) {
847 key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
848 if (sscanf((const char *)key, "%d", &ival) == 1)
849 Config.my_port = ival;
850 xmlFree(key);
851 }
852 if ((!xmlStrcmp(cur->name, (const xmlChar *)"TEMPFORMAT"))) {
853 key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
854 Config.tempFormat = key[0];
855 xmlFree(key);
856 }
857 #ifdef HAVE_WIRINGPI_H
858 if ((!xmlStrcmp(cur->name, (const xmlChar *)"LCDS"))) {
859 parseLCDs(doc, cur);
860 }
861 #endif
862 if ((!xmlStrcmp(cur->name, (const xmlChar *)"W1TERMS"))) {
863 parseW1therms(doc, cur);
864 }
865 if ((!xmlStrcmp(cur->name, (const xmlChar *)"FERMENTERS"))) {
866 parseFermenters(doc, cur);
867 }
868 cur = cur->next;
869 }
870 xmlFreeDoc(doc);
871
872 /*
514 linecnt = 0; 873 linecnt = 0;
515 while (fgets(buf, sizeof(buf) -1, fp)) { 874 while (fgets(buf, sizeof(buf) -1, fp)) {
516 linecnt++; 875 linecnt++;
517 if (*(p = buf + strlen(buf) -1) != '\n') { 876 if (*(p = buf + strlen(buf) -1) != '\n') {
518 syslog(LOG_NOTICE, "rdconfig: %s(%d): \"%s\" - line too long", mypath, linecnt, buf); 877 syslog(LOG_NOTICE, "rdconfig: %s(%d): \"%s\" - line too long", mypath, linecnt, buf);
550 break; 909 break;
551 } 910 }
552 911
553 } 912 }
554 fclose(fp); 913 fclose(fp);
914 */
555 915
556 free(mypath); 916 free(mypath);
557 mypath = NULL; 917 mypath = NULL;
558 918
559 return rc; 919 return rc;

mercurial