wmail: fixed possible NULL-pointer dereference in config-parser.
[dockapps.git] / wmcalc / wmcalcswitch.c
blob13980f8e79fceae4c2684ff6bc39d47187bbd2ed
1 /****************************************************************
2 * File: wmcalcswitch.c
3 * Version: 0.21
4 * Date: November 1, 2000
5 * Author: Edward H. Flora <ehflora@access1.net>
7 * This file is a part of the wmcalc application. As such, this
8 * file is licensed under the GNU General Public License, version 2.
9 * A copy of this license may be found in the file COPYING that should
10 * have been distributed with this file. If not, please refer to
11 * http://www.gnu.org/copyleft/gpl.html for details.
13 ****************************************************************
14 Description:
15 This file contains system level functions, such as read/write of
16 the config file, character map boundaries, etc.
18 Change History:
19 Date Modification
20 11/1/00 Updated Function headers, cleaned up comments some.
22 ****************************************************************/
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <ctype.h>
28 #include "wmcalc_err.h"
29 #include "wmcalc_c.h"
30 #include "wmcalc_f.h"
32 /****************************************************************
33 * Function: ExecFunc
34 ****************************************************************
35 Description:
36 This function determines which button was pressed, and performs
37 the appropriate function.
39 Change History:
40 Date Modification
41 11/01/00 Function header updated
42 ****************************************************************/
43 void ExecFunc( int val ) {
44 extern int Verbose;
46 if (Verbose) printf("Execute function for button %d\n", val);
48 switch(val) {
49 case 100:
50 clearcalc();
51 break;
52 case 101:
53 sqrtnum();
54 break;
55 case 102:
56 charkey('7');
57 break;
58 case 103:
59 charkey('8');
60 break;
61 case 104:
62 charkey('9');
63 break;
64 case 105:
65 divnums();
66 break;
67 case 106:
68 sqrnum();
69 break;
70 case 107:
71 charkey('4');
72 break;
73 case 108:
74 charkey('5');
75 break;
76 case 109:
77 charkey('6');
78 break;
79 case 110:
80 multnums();
81 break;
82 case 111:
83 /* scinotation(); */
84 startcalc();
85 break;
86 case 112:
87 charkey('1');
88 break;
89 case 113:
90 charkey('2');
91 break;
92 case 114:
93 charkey('3');
94 break;
95 case 115:
96 subtnums();
97 break;
98 case 116:
99 chgsignnum();
100 break;
101 case 117:
102 charkey('0');
103 break;
104 case 118:
105 charkey('.');
106 break;
107 case 119:
108 equalfunc();
109 break;
110 case 120:
111 addnums();
112 break;
113 case 200:
114 clrallmem();
115 break;
116 case 201:
117 sqrtnum();
118 /* userdef201(); */
119 break;
120 case 202:
121 recallmem(7);
122 break;
123 case 203:
124 recallmem(8);
125 break;
126 case 204:
127 recallmem(9);
128 break;
129 case 205:
130 divnums();
131 /* userdef205(); */
132 break;
133 case 206:
134 sqrnum();
135 /* userdef206(); */
136 break;
137 case 207:
138 recallmem(4);
139 break;
140 case 208:
141 recallmem(5);
142 break;
143 case 209:
144 recallmem(6);
145 break;
146 case 210:
147 multnums();
148 /* userdef210(); */
149 break;
150 case 211:
151 startcalc();
152 break;
153 case 212:
154 recallmem(1);
155 break;
156 case 213:
157 recallmem(2);
158 break;
159 case 214:
160 recallmem(3);
161 break;
162 case 215:
163 subtnums();
164 /* userdef215(); */
165 break;
166 case 216:
167 chgsignnum();
168 break;
169 case 217:
170 recallmem(0);
171 break;
172 case 218:
173 /* userdef218(); */
174 break;
175 case 219:
176 equalfunc();
177 break;
178 case 220:
179 addnums();
180 /* userdef220(); */
181 break;
182 case 300:
183 clearnum();
184 break;
185 case 301:
186 sqrtnum();
187 /* userdef301(); */
188 break;
189 case 302:
190 stormem(7);
191 break;
192 case 303:
193 stormem(8);
194 break;
195 case 304:
196 stormem(9);
197 break;
198 case 305:
199 divnums();
200 /* userdef305(); */
201 break;
202 case 306:
203 sqrnum();
204 /* userdef306(); */
205 break;
206 case 307:
207 stormem(4);
208 break;
209 case 308:
210 stormem(5);
211 break;
212 case 309:
213 stormem(6);
214 break;
215 case 310:
216 multnums();
217 /* userdef310(); */
218 break;
219 case 311:
220 startcalc();
221 break;
222 case 312:
223 stormem(1);
224 break;
225 case 313:
226 stormem(2);
227 break;
228 case 314:
229 stormem(3);
230 break;
231 case 315:
232 subtnums();
233 /* userdef315(); */
234 break;
235 case 316:
236 chgsignnum();
237 break;
238 case 317:
239 stormem(0);
240 break;
241 case 318:
242 /* userdef318(); */
243 break;
244 case 319:
245 equalfunc();
246 break;
247 case 320:
248 addnums();
249 /* userdef320(); */
250 break;
251 } /* End of switch statement */
253 } /* End of function ExecFunc() *********************************/
255 /****************************************************************
256 * Function: getboundaries
257 ****************************************************************
258 Description:
259 This function returns the x,y boundaries for each character
260 that is to be displayed on the display.
262 There must be a better way to do this, as by changing the file
263 charmap.xpm, one may have to adjust these constants.
265 Change History:
266 Date Modification
267 11/01/00 Function header updated
268 10/30/00 Added characters for the Memory indicator bar.
269 ****************************************************************/
270 ButtonArea getboundaries(char ch) {
271 ButtonArea xybounds;
273 switch (ch) {
274 case '0':
275 xybounds.x = 1; xybounds.i = 6;
276 xybounds.y = 1; xybounds.j = 8;
277 break;
278 case '1':
279 xybounds.x = 7; xybounds.i = 12;
280 xybounds.y = 1; xybounds.j = 8;
281 break;
282 case '2':
283 xybounds.x = 13; xybounds.i = 18;
284 xybounds.y = 1; xybounds.j = 8;
285 break;
286 case '3':
287 xybounds.x = 19; xybounds.i = 24;
288 xybounds.y = 1; xybounds.j = 8;
289 break;
290 case '4':
291 xybounds.x = 25; xybounds.i = 30;
292 xybounds.y = 1; xybounds.j = 8;
293 break;
294 case '5':
295 xybounds.x = 31; xybounds.i = 36;
296 xybounds.y = 1; xybounds.j = 8;
297 break;
298 case '6':
299 xybounds.x = 37; xybounds.i = 42;
300 xybounds.y = 1; xybounds.j = 8;
301 break;
302 case '7':
303 xybounds.x = 43; xybounds.i = 48;
304 xybounds.y = 1; xybounds.j = 8;
305 break;
306 case '8':
307 xybounds.x = 49; xybounds.i = 54;
308 xybounds.y = 1; xybounds.j = 8;
309 break;
310 case '9':
311 xybounds.x = 55; xybounds.i = 60;
312 xybounds.y = 1; xybounds.j = 8;
313 break;
314 case '+':
315 xybounds.x = 55; xybounds.i = 60;
316 xybounds.y = 28; xybounds.j = 35;
317 break;
318 case '-':
319 xybounds.x = 49; xybounds.i = 54;
320 xybounds.y = 28; xybounds.j = 35;
321 break;
322 case '.':
323 xybounds.x = 7; xybounds.i = 12;
324 xybounds.y = 10; xybounds.j = 17;
325 break;
326 case 'e':
327 xybounds.x = 1; xybounds.i = 6;
328 xybounds.y = 37; xybounds.j = 44;
329 break;
330 case 'i':
331 xybounds.x = 7; xybounds.i = 12;
332 xybounds.y = 37; xybounds.j = 44;
333 break;
334 case 'j':
335 xybounds.x = 13; xybounds.i = 18;
336 xybounds.y = 37; xybounds.j = 44;
337 break;
338 case 'n':
339 xybounds.x = 19; xybounds.i = 24;
340 xybounds.y = 37; xybounds.j = 44;
341 break;
342 case 'a':
343 xybounds.x = 25; xybounds.i = 30;
344 xybounds.y = 37; xybounds.j = 44;
345 break;
346 case 'f':
347 xybounds.x = 31; xybounds.i = 36;
348 xybounds.y = 37; xybounds.j = 44;
349 break;
350 case ' ':
351 xybounds.x = 1; xybounds.i = 6;
352 xybounds.y = 10; xybounds.j = 17;
353 break;
354 case '=':
355 xybounds.x = 55; xybounds.i = 60;
356 xybounds.y = 55; xybounds.j = 56;
357 break;
358 case '#':
359 xybounds.x = 55; xybounds.i = 60;
360 xybounds.y = 57; xybounds.j = 58;
361 break;
362 case '_':
363 xybounds.x = 55; xybounds.i = 60;
364 xybounds.y = 59; xybounds.j = 60;
365 break;
366 default:
367 xybounds.x = 1; xybounds.i = 6;
368 xybounds.y = 10; xybounds.j = 17;
369 break;
370 } /* end of switch statement */
372 return(xybounds);
373 } /***** End of function getboundaries() ************************/
375 /****************************************************************
376 * Function: write_config
377 ****************************************************************
378 Description:
379 This function updates the configuration file as memory locations
380 are updated in the program. It re-writes the entire file, but
381 should ignore all lines that do not start with "Mem".
383 Change History:
384 Date Modification
385 11/01/00 Function Header updated
386 11/05/00 Added Locked Memory Handling
387 ****************************************************************/
388 int write_config(void) {
389 extern int Verbose;
390 extern double MemArray[];
391 extern char configfile[];
392 extern char tempfile[];
393 extern char *CfgVarList[];
394 FILE *fp, *fptmp;
395 char *line = NULL;
396 int mem_ndx = 0;
397 int err_code = OKAY;
398 char movefilecmd[2 * CONFIGFILEMAX + 10]; /* make sure enough room in string */
400 /* Open current Config file */
401 if ((fp = fopen(configfile, "r")) == NULL) { /* Can't find config file */
402 printf("%s: Cannot create configuration file\n", configfile);
403 return(ERR_FILE_NOT_FOUND);
406 /* We cannot write to the global config-file... */
407 if(!strcmp(configfile, CONFIGGLOBAL)) {
408 strcpy(configfile, getenv("HOME")); /* Added to wmbutton by Gordon Fraser, 9/21/01 */
409 strcat(configfile, CONFFILENAME);
412 /* Open Temporary File */
413 if ((fptmp = fopen(tempfile, "w")) == NULL) { /* Can't open file in /tmp */
414 fprintf(stderr, "%s: Temporary File Open Failed\n", tempfile);
415 strcpy(tempfile, getenv("HOME"));
416 strcat(tempfile, "wmcalc.tmp");
417 if ((fptmp = fopen(tempfile, "w")) == NULL) { /* Can't open file in HOME */
418 fprintf(stderr, "%s: Temporary File Open Failed\n", tempfile);
419 return(ERR_TMP_FILE_FAILED);
423 while ((line = readln(fp)) != NULL) { /* Read Lines in config file */
424 if (Verbose) printf("line:%s", line);
426 if ((strncmp(line, CfgVarList[MEM_LABEL_0],
427 strlen(CfgVarList[MEM_LABEL_0]) - 1) == 0)) {
428 /* -1 to generalize to all Mem? strings */
429 /* If we've found a memory entry */
430 mem_ndx = atoi(line+strlen(CfgVarList[MEM_LABEL_0])-1);
431 if ((mem_ndx >= 0) && (mem_ndx <= (NUM_MEM_CELLS - 1))) {
432 fprintf(fptmp, "%s\t%f\n", CfgVarList[mem_ndx],
433 MemArray[mem_ndx]);
436 else {
437 fprintf(fptmp, "%s", line);
439 free(line);
440 } /* End of while loop */
442 /* Close open files */
443 fclose(fp);
444 fclose(fptmp);
446 /* Copy temp file over original */
447 /* Note: If changing command, make sure to adjust size of string above!! */
448 sprintf(movefilecmd, "mv -f %s %s\n", tempfile, configfile);
449 err_code = system(movefilecmd);
451 if(Verbose) printf("New config file written.\n");
453 return(err_code);
454 } /***** End of function write_config() *************************/
457 /****************************************************************
458 * Function: read_config
459 ****************************************************************
460 Description:
461 This function reads the configuration file on program startup,
462 and sets the appropriate configuration options.
463 (By default, this is ~/.wmcalc, or a user set value)
465 Change History:
466 Date Modification
467 11/01/00 Function header updated.
468 11/05/00 Added Lcoked Memory Capabilities
469 ****************************************************************/
470 int read_config(void) {
471 extern int Verbose;
472 extern double MemArray[];
473 extern int MemLock[];
474 extern char *CfgVarList[];
475 extern char ImagChar;
476 extern char configfile[];
477 extern char SysCalcCmd[];
478 FILE *fp;
479 int i = 0;
480 int err_code = OKAY;
481 char *line = NULL;
482 char sep_ch = '\t';
483 char *cfg_var_ptr = NULL;
486 if ((fp = fopen(configfile, "r")) == NULL) { /* Can't find config file */
487 strcpy(configfile, CONFIGGLOBAL); /* ...so try to open global config */
488 if ((fp = fopen(configfile, "r")) == NULL) { /* Can't find global config file */
489 fprintf(stderr, "%s: Configuration File not found\n", configfile);
490 return(ERR_FILE_NOT_FOUND);
491 } else {
492 write_config(); /* if global config opened, save in homedir */
495 else {
496 if (Verbose) printf("%s: Found Configuration File\n", configfile);
499 do { /* Read Lines in config file */
500 line = readln(fp);
501 if (Verbose) printf("Line Read:%s\n", line);
502 if (line == NULL) break; /* if end of file, quit */
503 if ( (line[0] != '#') && (line[0] != '\n')) { /* Ignore comments and
504 blanks */
505 if (strchr(line, sep_ch) != NULL) { /* The line has a tab, so let's
506 see if the variable is
507 understood */
508 i = 0;
509 /* Loop while we haven't found the variable */
510 while (((strncmp(line, CfgVarList[i], strlen(CfgVarList[i]))) != 0)
511 && (i < MAX_LABEL)) {
512 i++;
514 /* If we've found the variable, let's set the appropriate value */
515 if (i <= MAX_LABEL) {
516 if (Verbose) printf("Variable %s found\n", CfgVarList[i]);
518 /* Point to the 'tab' character, to read the value */
519 cfg_var_ptr = strchr(line, sep_ch);
520 cfg_var_ptr++; /* ++ to avoid tab character itself */
522 /* Now set the appropriate variable */
523 switch(i) {
524 case MEM_LABEL_0:
525 case MEM_LABEL_1:
526 case MEM_LABEL_2:
527 case MEM_LABEL_3:
528 case MEM_LABEL_4:
529 case MEM_LABEL_5:
530 case MEM_LABEL_6:
531 case MEM_LABEL_7:
532 case MEM_LABEL_8:
533 case MEM_LABEL_9:
534 /* Set Locked Flag */
535 MemLock[i] = 0;
536 /* Set Memory Element */
537 MemArray[i] = atof(cfg_var_ptr);
538 if (Verbose)
539 printf("Assign Memory Element %d to %f\n", i, MemArray[i]);
540 break;
542 case MEM_LOCK_0:
543 case MEM_LOCK_1:
544 case MEM_LOCK_2:
545 case MEM_LOCK_3:
546 case MEM_LOCK_4:
547 case MEM_LOCK_5:
548 case MEM_LOCK_6:
549 case MEM_LOCK_7:
550 case MEM_LOCK_8:
551 case MEM_LOCK_9:
552 /* Set Locked Flag */
553 MemLock[i - MEM_LOCK_0] = 1;
554 /* Set Memory Element */
555 MemArray[i - MEM_LOCK_0] = atof(cfg_var_ptr);
556 if (Verbose)
557 printf("Assign Memory Element %d to %f\n", i -
558 MEM_LOCK_0, MemArray[i - MEM_LOCK_0]);
559 break;
561 case IMAG_LABEL:
562 /* Get the character that the user wishes to use to
563 represent sqrt(-1) (i or j) */
564 if ((cfg_var_ptr[0] == 'i') || cfg_var_ptr[0] == 'j') {
565 ImagChar = cfg_var_ptr[0];
567 if (Verbose)
568 printf("Use character '%c' to represent sqrt(-1)\n", ImagChar);
569 break;
571 case CALC_LABEL:
572 /* Set external calculator start command */
573 strcpy(SysCalcCmd, cfg_var_ptr);
574 if (Verbose)
575 printf("Assign Calc Command: %s\n", cfg_var_ptr);
576 break;
578 default:
579 if (Verbose) printf("Unknown Config Variable: %s\n", line);
580 break;
584 /* Otherwise, we don't recognize the variable */
585 else {
586 if (Verbose) printf("Unknown Config Variable: %s\n", line);
589 /* Otherwise, we had a poorly formatted line in the config file. */
590 else {
591 if (Verbose) printf("Poorly formatted config file line\n:%s\n", line);
594 free(line);
595 } while (line != NULL);
597 fclose(fp);
601 return(err_code);
602 } /***** End of function read_config **************************/