PageRenderTime 52ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/pud/src/posFile.c

https://bitbucket.org/clauz/olsrd-ccninfo
C | 296 lines | 212 code | 48 blank | 36 comment | 55 complexity | 8d9210e1f6fd8f959cab7941a7ca403b MD5 | raw file
  1. #include "posFile.h"
  2. /* Plugin includes */
  3. #include "pud.h"
  4. #include "configTools.h"
  5. /* OLSR includes */
  6. /* System includes */
  7. #include <stdio.h>
  8. #include <string.h>
  9. #include <regex.h>
  10. #include <sys/stat.h>
  11. /** the maximal length of a line that is read from the file */
  12. #define LINE_LENGTH 256
  13. /** regular expression describing a comment */
  14. static const char * regexCommentString = "^([[:space:]]*|[[:space:]#]+.*)$";
  15. /** regular expression describing a key/value pair */
  16. static const char * regexNameValueString =
  17. "^[[:space:]]*([^[:space:]]+)[[:space:]]*=[[:space:]]*([^[:space:]]+)[[:space:]]*$";
  18. /** the number of matches in regexNameValueString */
  19. static const size_t regexNameValuematchCount = 3;
  20. /** the compiled regular expression describing a comment */
  21. static regex_t regexComment;
  22. /** the compiled regular expression describing a key/value pair */
  23. static regex_t regexNameValue;
  24. /** true when the plugin has been started */
  25. static bool started = false;
  26. /** type to hold the cached stat result */
  27. typedef struct _CachedStat {
  28. time_t timeStamp; /* Time of last modification (second resolution) */
  29. } CachedStat;
  30. /** the cached stat result */
  31. static CachedStat cachedStat;
  32. /**
  33. * Initialises the positionFile reader.
  34. * @return true upon success, false otherwise
  35. */
  36. bool startPositionFile(void) {
  37. if (started) {
  38. return true;
  39. }
  40. if (regcomp(&regexComment, regexCommentString, REG_EXTENDED | REG_ICASE)) {
  41. pudError(false, "Could not compile regex \"%s\"", regexCommentString);
  42. return false;
  43. }
  44. if (regcomp(&regexNameValue, regexNameValueString, REG_EXTENDED | REG_ICASE)) {
  45. pudError(false, "Could not compile regex \"%s\"", regexNameValueString);
  46. regfree(&regexComment);
  47. return false;
  48. }
  49. cachedStat.timeStamp = -1;
  50. started = true;
  51. return true;
  52. }
  53. /**
  54. * Cleans up the positionFile reader.
  55. */
  56. void stopPositionFile(void) {
  57. if (started) {
  58. regfree(&regexNameValue);
  59. regfree(&regexComment);
  60. started = false;
  61. }
  62. }
  63. /**
  64. * Performs a regex match
  65. * @param regex the compiled regex to match against
  66. * @param line the line to match
  67. * @param nmatch the number of matches to produce
  68. * @param pmatch the array with match information
  69. * @return true upon success, false otherwise
  70. */
  71. static bool regexMatch(regex_t * regex, char * line, size_t nmatch, regmatch_t pmatch[]) {
  72. int result = regexec(regex, line, nmatch, pmatch, 0);
  73. if (!result) {
  74. return true;
  75. }
  76. if (result == REG_NOMATCH) {
  77. return false;
  78. }
  79. {
  80. char msgbuf[256];
  81. regerror(result, regex, msgbuf, sizeof(msgbuf));
  82. pudError(false, "Regex match failed: %s", msgbuf);
  83. }
  84. return false;
  85. }
  86. /** the buffer in which to store a line read from the file */
  87. static char line[LINE_LENGTH];
  88. /**
  89. * Read the position file
  90. * @param fileName the filename
  91. * @param nmeaInfo the NMEA data
  92. */
  93. bool readPositionFile(char * fileName, nmeaINFO * nmeaInfo) {
  94. bool retval = false;
  95. struct stat statBuf;
  96. nmeaINFO result;
  97. FILE * fd = NULL;
  98. unsigned int lineNumber = 0;
  99. char * name = NULL;
  100. char * value = NULL;
  101. if (stat(fileName, &statBuf)) {
  102. /* could not access the file */
  103. goto out;
  104. }
  105. if (!memcmp(&cachedStat.timeStamp, &statBuf.st_mtime, sizeof(cachedStat.timeStamp))) {
  106. /* file did not change since last read */
  107. goto out;
  108. }
  109. fd = fopen(fileName, "r");
  110. if (!fd) {
  111. goto out;
  112. }
  113. nmea_zero_INFO(&result);
  114. result.sig = POSFILE_DEFAULT_SIG;
  115. result.fix = POSFILE_DEFAULT_FIX;
  116. result.HDOP = POSFILE_DEFAULT_HDOP;
  117. result.VDOP = POSFILE_CALCULATED_VDOP(result.HDOP);
  118. result.PDOP = POSFILE_CALCULATED_PDOP(result.HDOP);
  119. result.lat = POSFILE_DEFAULT_LAT;
  120. result.lon = POSFILE_DEFAULT_LON;
  121. result.elv = POSFILE_DEFAULT_ELV;
  122. result.speed = POSFILE_DEFAULT_SPEED;
  123. result.track = POSFILE_DEFAULT_TRACK;
  124. result.mtrack = POSFILE_DEFAULT_MTRACK;
  125. result.magvar = POSFILE_DEFAULT_MAGVAR;
  126. memcpy(&cachedStat.timeStamp, &statBuf.st_mtime, sizeof(cachedStat.timeStamp));
  127. while (fgets(line, LINE_LENGTH, fd)) {
  128. regmatch_t pmatch[regexNameValuematchCount];
  129. lineNumber++;
  130. if (regexMatch(&regexComment, line, 0, NULL)) {
  131. continue;
  132. }
  133. if (!regexMatch(&regexNameValue, line, regexNameValuematchCount, pmatch)) {
  134. pudError(false, "Position file \"%s\", line %d uses invalid syntax: %s", fileName, lineNumber, line);
  135. goto out;
  136. }
  137. /* determine name/value */
  138. name = &line[pmatch[1].rm_so];
  139. line[pmatch[1].rm_eo] = '\0';
  140. value = &line[pmatch[2].rm_so];
  141. line[pmatch[2].rm_eo] = '\0';
  142. if (!strncasecmp(POSFILE_NAME_SIG, name, sizeof(line))) {
  143. if (!strncasecmp(POSFILE_VALUE_SIG_BAD, value, sizeof(line))) {
  144. result.sig = NMEA_SIG_BAD;
  145. } else if (!strncasecmp(POSFILE_VALUE_SIG_LOW, value, sizeof(line))) {
  146. result.sig = NMEA_SIG_LOW;
  147. } else if (!strncasecmp(POSFILE_VALUE_SIG_MID, value, sizeof(line))) {
  148. result.sig = NMEA_SIG_MID;
  149. } else if (!strncasecmp(POSFILE_VALUE_SIG_HIGH, value, sizeof(line))) {
  150. result.sig = NMEA_SIG_HIGH;
  151. } else {
  152. pudError(false, "Position file \"%s\", line %d uses an invalid value for \"%s\","
  153. " valid values are [%s|%s\%s|%s]", fileName, lineNumber, POSFILE_NAME_SIG,
  154. POSFILE_VALUE_SIG_BAD, POSFILE_VALUE_SIG_LOW, POSFILE_VALUE_SIG_MID, POSFILE_VALUE_SIG_HIGH);
  155. goto out;
  156. }
  157. nmea_INFO_set_present(&result.present, SIG);
  158. } else if (!strncasecmp(POSFILE_NAME_FIX, name, sizeof(line))) {
  159. if (!strncasecmp(POSFILE_VALUE_FIX_BAD, value, sizeof(line))) {
  160. result.fix = NMEA_FIX_BAD;
  161. } else if (!strncasecmp(POSFILE_VALUE_FIX_2D, value, sizeof(line))) {
  162. result.fix = NMEA_FIX_2D;
  163. } else if (!strncasecmp(POSFILE_VALUE_FIX_3D, value, sizeof(line))) {
  164. result.fix = NMEA_FIX_3D;
  165. } else {
  166. pudError(false, "Position file \"%s\", line %d uses an invalid value for \"%s\","
  167. " valid values are [%s\%s|%s]", fileName, lineNumber, POSFILE_NAME_FIX, POSFILE_VALUE_FIX_BAD,
  168. POSFILE_VALUE_FIX_2D, POSFILE_VALUE_FIX_3D);
  169. goto out;
  170. }
  171. nmea_INFO_set_present(&result.present, FIX);
  172. } else if (!strncasecmp(POSFILE_NAME_HDOP, name, sizeof(line))) {
  173. double val;
  174. if (!readDouble(POSFILE_NAME_HDOP, value, &val)) {
  175. goto out;
  176. }
  177. result.HDOP = val;
  178. result.VDOP = POSFILE_CALCULATED_VDOP(result.HDOP);
  179. result.PDOP = POSFILE_CALCULATED_PDOP(result.HDOP);
  180. nmea_INFO_set_present(&result.present, HDOP);
  181. nmea_INFO_set_present(&result.present, VDOP);
  182. nmea_INFO_set_present(&result.present, PDOP);
  183. } else if (!strncasecmp(POSFILE_NAME_LAT, name, sizeof(line))) {
  184. double val;
  185. if (!readDouble(POSFILE_NAME_LAT, value, &val)) {
  186. goto out;
  187. }
  188. result.lat = val;
  189. nmea_INFO_set_present(&result.present, LAT);
  190. } else if (!strncasecmp(POSFILE_NAME_LON, name, sizeof(line))) {
  191. double val;
  192. if (!readDouble(POSFILE_NAME_LON, value, &val)) {
  193. goto out;
  194. }
  195. result.lon = val;
  196. nmea_INFO_set_present(&result.present, LON);
  197. } else if (!strncasecmp(POSFILE_NAME_ELV, name, sizeof(line))) {
  198. double val;
  199. if (!readDouble(POSFILE_NAME_ELV, value, &val)) {
  200. goto out;
  201. }
  202. result.elv = val;
  203. nmea_INFO_set_present(&result.present, ELV);
  204. } else if (!strncasecmp(POSFILE_NAME_SPEED, name, sizeof(line))) {
  205. double val;
  206. if (!readDouble(POSFILE_NAME_SPEED, value, &val)) {
  207. goto out;
  208. }
  209. result.speed = val;
  210. nmea_INFO_set_present(&result.present, SPEED);
  211. } else if (!strncasecmp(POSFILE_NAME_TRACK, name, sizeof(line))) {
  212. double val;
  213. if (!readDouble(POSFILE_NAME_TRACK, value, &val)) {
  214. goto out;
  215. }
  216. result.track = val;
  217. nmea_INFO_set_present(&result.present, TRACK);
  218. } else if (!strncasecmp(POSFILE_NAME_MTRACK, name, sizeof(line))) {
  219. double val;
  220. if (!readDouble(POSFILE_NAME_MTRACK, value, &val)) {
  221. goto out;
  222. }
  223. result.mtrack = val;
  224. nmea_INFO_set_present(&result.present, MTRACK);
  225. } else if (!strncasecmp(POSFILE_NAME_MAGVAR, name, sizeof(line))) {
  226. double val;
  227. if (!readDouble(POSFILE_NAME_MAGVAR, value, &val)) {
  228. goto out;
  229. }
  230. result.magvar = val;
  231. nmea_INFO_set_present(&result.present, MAGVAR);
  232. } else {
  233. pudError(false, "Position file \"%s\", line %d uses an invalid option \"%s\","
  234. " valid options are [%s|%s|%s|%s|%s|%s|%s|%s|%s|%s]", fileName, lineNumber, name, POSFILE_NAME_SIG,
  235. POSFILE_NAME_FIX, POSFILE_NAME_HDOP, POSFILE_NAME_LAT, POSFILE_NAME_LON, POSFILE_NAME_ELV,
  236. POSFILE_NAME_SPEED, POSFILE_NAME_TRACK, POSFILE_NAME_MTRACK, POSFILE_NAME_MAGVAR);
  237. goto out;
  238. }
  239. }
  240. fclose(fd);
  241. result.smask = POSFILE_DEFAULT_SMASK;
  242. nmea_INFO_set_present(&result.present, SMASK);
  243. nmea_INFO_sanitise(&result);
  244. nmea_INFO_unit_conversion(&result);
  245. memcpy(nmeaInfo, &result, sizeof(result));
  246. retval = true;
  247. out: return retval;
  248. }