1 /*
2  * Changes for use with CM11A copyright 1996, 1997 Daniel B. Suthers,
3  * Pleasanton Ca, 94588 USA
4  * E-mail dbs@tanj.com
5  */
6 /*
7  * Copyright 1986 by Larry Campbell, 73 Concord Street, Maynard MA 01754 USA
8  * (maynard!campbell).
9  *
10  * John Chmielewski (tesla!jlc until 9/1/86, then rogue!jlc) assisted
11  * by doing the System V port and adding some nice features.  Thanks!
12  *
13  */
14 
15 /*
16  *   This program is free software: you can redistribute it and/or modify
17  *   it under the terms of the GNU General Public License as published by
18  *   the Free Software Foundation, either version 3 of the License, or
19  *   (at your option) any later version.
20  *
21  *   This program is distributed in the hope that it will be useful,
22  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
23  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24  *   GNU General Public License for more details.
25  *
26  *   You should have received a copy of the GNU General Public License
27  *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
28  *
29  */
30 
31 #include <stdio.h>
32 #include <sys/stat.h>
33 #include <unistd.h>
34 #include <ctype.h>
35 #include <stdlib.h>
36 #if defined(SYSV) || defined(FREEBSD) || defined(OPENBSD)
37 #include <string.h>
38 #else
39 #include <strings.h>
40 #endif
41 #include <time.h>
42 #include <signal.h>
43 #include "x10.h"
44 #include "version.h"
45 #include <syslog.h>
46 #include "process.h"
47 
48 #ifdef __GLIBC__
49 /* msf - added for glibc/rh 5.0 */
50 #include <sys/types.h>
51 #endif
52 
53 extern int tty;
54 extern int sptty;
55 extern int usage();
56 extern int start_relay(),setup_sp_tty(), xread(), unit2int();
57 extern void error(), quit();
58 extern int lock_for_write();
59 extern int munlock();
60 extern CONFIG config;  /* CWS - Structure with all configuration data */
61 extern CONFIG *configp;
62 
63 int x10_housecode;
64 int verbose;
65 int i_am_relay = 0;	/* flag to differentiate the relay process */
66 int port_locked = 0;	/* flag to show that the tty port is locked */
67 int i_am_monitor = 0;
68 int i_am_state = 0;
69 int i_am_aux = 0;
70 int i_am_rfxmeter = 0;
71 int heyu_parent = D_CMDLINE;
72 
73 FILE *fdsout;
74 FILE *fdserr;
75 FILE *fprfxo;
76 FILE *fprfxe;
77 
78 void init();
79 int check4poll();
80 
81 char heyuprogname[PATH_LEN + 1 + 10];
82 
83 struct opt_st options;
84 struct opt_st *optptr = &options;
85 
86 extern char *wday_name[7];
87 extern char *month_name[12];
88 
89 
90 /* Table for mapping units (1-16) or house codes (a-p) to 4 bit nibbles.
91  * element 0 equates to unit 1 or code a
92  */
93 unsigned char cm11map[]=
94 {  06, 016, 02, 012, 01, 011, 05, 015,
95    07, 017, 03, 013, 0, 010, 04, 014
96 };
97 
98 /* Table for mapping an x10 format bitmap to a unit number.  It's
99  * the reverse of the one above.
100  * Note that the unit numbers are 1-16, but the array is 0-15.
101  */
102 unsigned char map2cm11[]=
103 {
104     13, 5, 3, 11, 15, 7, 1, 9, 14, 6, 4, 12, 16, 8, 2, 10
105 };
106 
107 int timeout = TIMEOUT;
108 
109 
110 extern int
111  c_date(),  c_info(), c_monitor(), c_reset(),  c_setclock(),
112  c_erase(),  c_upload(), c_utility(), c_setclockraw(), c_command(),
113  is_heyu_cmd(), c_qerase(),
114  c_set_status(), c_show1(), c_show2(), c_x10state(), c_ping(), c_busywait(),
115  c_catchup(), c_macro(), c_start_engine(), c_logmsg(), c_readclock(),
116  c_flagstate(), c_cm10a_ident(), c_turn_rts_off(), c_turn_rts_on(),
117  c_trigger(), c_status_state(), c_powerfailtest(),
118  c_show_modem_lines(), c_ri_disable(), c_ri_enable(), c_port_line_test(),
119  c_start_aux(), c_start(), c_restart(), c_stop(), c_script_ctrl(),
120  c_arm(), c_sendarbst(), c_sensorfault(), c_armedstate(), c_settimer(),
121  c_sunstate(), c_restore_groups(), c_rfxcmds(), c_timer_times(), c_webhook(),
122  c_counter(), c_logtail(), c_modlist(), c_dmxcmds(), c_orecmds(), c_ore_emu(),
123  c_launch(), c_rts_pulser(), c_conflist(), c_sec_emu(), c_stateflaglist(),
124  c_masklist();
125 
126 void init ( char * );
127 int read_config( unsigned char );
128 
129 extern void create_alerts ( void );
130 extern int  quick_ports_check ( void );
131 
132 int c_list(), c_version();
133 
134 struct cmdentry {
135     char *cmd_name;
136     int (*cmd_routine) ();
137     int lock_needed;
138     int internal_cmd;
139 } cmdtab[] = {
140     {"___", c_command,1,1},
141     {"date", c_date,1,0} ,
142     {"erase", c_erase,1,0},
143     {"info", c_info,1,1},
144     {"list", c_list,0,1},
145     {"monitor", c_monitor,0,1},
146     {"cmd", c_command,1,1},
147     {"reset", c_reset,1,0},
148     {"setclock", c_setclock,1,0},
149     {"readclock", c_readclock,1,0},
150     {"setclockraw", c_setclockraw, 1,0}, /* undocumented, see source - CWS */
151     {"upload", c_upload, 1, 0},  /* (added by CWS) */
152     {"utility", c_utility, 0, 1}, /* (added by CWS) */
153     {"newbattery", c_set_status, 1, 0},
154     {"purge", c_set_status, 1, 0},
155     {"clear", c_set_status, 1, 0},
156     {"reserved", c_set_status, 1, 0}, /* undocumented, see source - CWS */
157     {"version", c_version,0, 1},
158     {"qerase", c_qerase,1, 0},  /* hidden feature */
159     {"enginestate", c_x10state,1, 1},
160     {"initstate", c_x10state,1, 1},
161     {"initstateold", c_x10state, 1, 1},
162     {"initothers", c_x10state,1, 1},
163     {"fetchstate", c_x10state,1, 1},
164     {"onstate", c_x10state, 1, 1},
165     {"offstate", c_x10state, 1, 1},
166     {"dimstate", c_x10state, 1, 1},
167     {"fullonstate", c_x10state, 1, 1},
168     {"chgstate", c_x10state, 1, 1},
169     {"modchgstate", c_x10state, 1, 1},
170     {"alertstate", c_x10state, 1, 1},
171     {"clearstate", c_x10state, 1, 1},
172     {"auxalertstate", c_x10state, 1, 1},
173     {"auxclearstate", c_x10state, 1, 1},
174     {"addrstate", c_x10state, 1, 1},
175     {"lobatstate", c_x10state, 1, 1},
176     {"inactivestate", c_x10state, 1, 1},
177     {"activestate", c_x10state, 1, 1},
178     {"activechgstate", c_x10state, 1, 1},
179     {"validstate", c_x10state, 1, 1},
180     {"tamperstate", c_x10state, 1, 1},
181     {"dimlevel", c_x10state, 1, 1},
182     {"rawlevel", c_x10state, 1, 1},
183     {"memlevel", c_x10state, 1, 1},
184     {"rcstemp", c_x10state, 1, 1},
185     {"rawmemlevel", c_x10state, 1, 1},
186     {"vident", c_x10state, 1, 1},
187     {"sincelast", c_x10state, 1, 1},
188     {"statestr", c_x10state, 1, 1},
189     {"heyu_state", c_x10state, 1, 1},
190     {"heyu_vflagstate", c_x10state, 1, 1},
191     {"heyu_rawstate", c_x10state, 1, 1},
192     {"verbose_rawstate", c_x10state, 1, 1},
193     {"xtend_state", c_x10state, 1, 1},
194     {"catchup", c_catchup, 1, 0},
195     {"macro", c_macro, 1, 0},
196     {"trigger", c_trigger, 1, 0},
197     {"ping", c_ping, 1, 0},
198     {"show", c_show2, 1, 1},
199     {"engine", c_start_engine, 1, 1},
200     {"logmsg", c_logmsg, 1, 1},
201     {"wait", c_busywait, 1, 0},
202     {"flagstate", c_flagstate, 1, 1},
203     {"statusstate", c_status_state, 1, 1},
204     {"spendstate", c_status_state, 1, 1},
205     {"cm10a_init", c_cm10a_init, 1, 0},
206     {"cm10a_ident", c_cm10a_ident, 1, 0},
207     {"turn_rts_off", c_turn_rts_off, 1, 0},
208     {"turn_rts_on", c_turn_rts_on, 1, 0},
209     {"show_modem_lines", c_show_modem_lines, 1, 0},
210     {"powerfailtest", c_powerfailtest, 1, 1},
211     {"ri_disable", c_ri_disable, 1, 0},
212     {"ri_enable", c_ri_enable, 1, 0},
213     {"port_line_test", c_port_line_test, 1, 0},
214     {"rts_pulser", c_rts_pulser, 1, 1},
215     {"aux", c_start_aux, 1, 1},
216     {"start", c_start, 1, 1},
217     {"restart", c_restart, 1, 1},
218     {"stop", c_stop,0, 1},
219     {"script_ctrl", c_script_ctrl, 1, 1},
220     {"_arm", c_arm, 1, 1},
221     {"_disarm", c_arm, 1, 1},
222     {"sendarbst", c_sendarbst, 1, 0},
223     {"sensorfault", c_sensorfault, 1, 1},
224     {"armedstate", c_armedstate, 1, 1},
225     {"sunstate", c_sunstate, 1, 1},
226     {"nightstate", c_sunstate, 1, 1},
227     {"darkstate", c_sunstate, 1, 1},
228     {"restore_groups", c_restore_groups, 1, 0},
229 #ifdef HASRFXS
230     {"rfxflag_state", c_x10state, 1, 1},
231     {"rfxtemp", c_rfxcmds, 1, 1},
232     {"rfxrh", c_rfxcmds, 1, 1},
233     {"rfxbp", c_rfxcmds, 1, 1},
234     {"rfxvs", c_rfxcmds, 1, 1},
235     {"rfxvad", c_rfxcmds, 1, 1},
236     {"rfxvadi", c_rfxcmds, 1, 1},
237     {"rfxpot", c_rfxcmds, 1, 1},
238     {"rfxtemp2", c_rfxcmds, 1, 1},
239     {"rfxlobat", c_rfxcmds, 1, 1},
240 #endif
241 #ifdef HASRFXM
242     {"rfxflag_state", c_x10state, 1, 1},
243     {"rfxpower", c_rfxcmds, 1, 1},
244     {"rfxwater", c_rfxcmds, 1, 1},
245     {"rfxgas", c_rfxcmds, 1, 1},
246     {"rfxpulse", c_rfxcmds, 1, 1},
247     {"rfxcount", c_rfxcmds, 1, 1},
248     {"rfxpanel", c_rfxcmds, 1, 1},
249 #endif
250 #ifdef HASDMX
251     {"dmxflag_state", c_x10state, 1, 1},
252     {"dmxtemp", c_dmxcmds, 1, 1},
253     {"dmxsetpoint", c_dmxcmds, 1, 1},
254     {"dmxstatus", c_dmxcmds, 1, 1},
255     {"dmxmode", c_dmxcmds, 1, 1},
256 #endif /* HASDMX */
257 #ifdef HASORE
258     {"oreflag_state", c_x10state, 1, 1},
259     {"oretemp", c_orecmds, 1, 1},
260     {"orerh", c_orecmds, 1, 1},
261     {"orebp", c_orecmds, 1, 1},
262     {"orewgt", c_orecmds, 1, 1},
263     {"elscurr", c_orecmds, 1, 1},
264     {"orewindsp", c_orecmds, 1, 1},
265     {"orewindavsp", c_orecmds, 1, 1},
266     {"orewinddir", c_orecmds, 1, 1},
267     {"orerainrate", c_orecmds, 1, 1},
268     {"oreraintot", c_orecmds, 1, 1},
269     {"oreuv", c_orecmds, 1, 1},
270     {"owlpower", c_orecmds, 1, 1},
271     {"owlenergy", c_orecmds, 1, 1},
272     {"ore_emu", c_ore_emu, 1, 1},
273 #endif /* HASORE */
274     {"timer_times", c_timer_times, 1, 1},
275     {"webhook", c_webhook, 1, 1},
276     {"counter", c_counter, 1, 1},
277     {"logtail", c_logtail, 1, 1},
278 //    {"modlist", c_modlist, 0, 1},
279 //    {"conflist", c_conflist, 0, 1},
280     {"launch",  c_launch, 1, 1},
281     {"sec_emu", c_sec_emu, 1, 1},
282     {"", NULL , 0, 0}
283 };
284 
285 char *argptr;
286 
287 /*-------------------------------------------------------------------+
288  |  Main                                                             |
289  +-------------------------------------------------------------------*/
main(int argc,char * argv[])290 int main ( int argc, char *argv[] )
291 {
292     register int i;
293     int (*rtn) ();
294     struct cmdentry *c;
295     int retcode;
296     int ntokens;
297     char writefilename[PATH_LEN + 1];
298     char *cptr;
299     int start_engine_main();
300     int check_for_engine();
301     int check_dir_rw ( char *, char * );
302 
303     configp = &config;
304 
305     strncpy2(heyuprogname, argv[0], sizeof(heyuprogname) - 10);
306 
307     /* Record if heyu was executed downstream of the heyu state engine or relay */
308     heyu_parent = D_CMDLINE;
309     if ( (cptr = getenv("HEYU_PARENT")) != NULL ) {
310        if ( strcmp(cptr, "RELAY") == 0 ) {
311           heyu_parent = D_RELAY;
312           i_am_state = 0;
313        }
314        else if ( strcmp(cptr, "ENGINE") == 0 ) {
315           heyu_parent = D_ENGINE;
316           i_am_state = 0;
317        }
318        else if ( strcmp(cptr, "AUXDEV") == 0 ) {
319           heyu_parent = D_AUXDEV;
320           i_am_state = 0;
321        }
322     }
323 
324     fdsout = fprfxo = stdout;
325     fdserr = fprfxe = stderr;
326 
327     rtn = NULL;
328 
329 
330     /* Check for and store options in options structure */
331     /* Return number of tokens used for options, or -1  */
332     /* if a usage error.                                */
333     ntokens = heyu_getopt(argc, argv, optptr);
334 
335     if ( ntokens < 0 || (argc - ntokens) < 2 ) {
336        fprintf(stderr, "Heyu version %s\n", VERSION );
337        fprintf(stderr, "X10 Automation for Linux, Unix, and Mac OS X\n");
338        fprintf(stderr, "Copyright Charles W. Sullivan and Daniel B. Suthers\n");
339        fprintf(stderr,
340           "Usage: heyu [options] <command>  (Enter 'heyu help' for commands.)\n");
341        return 1;
342     }
343 
344     verbose = optptr->verbose;
345     if( verbose )
346 	printf( "Version:%4s\n", VERSION );
347 
348     /* Remove the tokens used for options from the argument list */
349     for ( i = 1; i < (argc - ntokens); i++ ) {
350        argv[i] = argv[i + ntokens];
351     }
352     argc -= ntokens;
353 
354     if ( strcmp(argv[1], "list") == 0 ) {
355        c_list();
356        return 0;
357     }
358 
359 
360     if ( strcmp(argv[1], "help") == 0 ||
361          strcmp(argv[1], "syn") == 0  ||
362          strcmp(argv[1], "linewidth") == 0  ) {
363        c_command(argc, argv);
364        return 0;
365     }
366 
367     if ( strcmp(argv[1], "utility") == 0 ) {
368           c_utility(argc, argv);
369           return 0;
370     }
371 
372     if ( strcmp(argv[1], "modlist") == 0 ) {
373        return c_modlist(argc, argv);
374     }
375     else if ( strcmp(argv[1], "conflist") == 0 ) {
376        return c_conflist(argc, argv);
377     }
378     else if ( strcmp(argv[1], "stateflaglist") == 0 ) {
379        return c_stateflaglist(argc, argv);
380     }
381     else if ( strcmp(argv[1], "masklist") == 0 ) {
382        return c_masklist(argc, argv);
383     }
384 
385 #if 0
386     if ( strcmp(argv[1], "webhook") == 0 ) {
387        c_webhook(argc, argv);
388        return 0;
389     }
390 #endif
391 
392     if ( strcmp(argv[1], "show") == 0 ) {
393        retcode = c_show1(argc, argv);
394        if ( retcode == 0 ) {
395           free_all_arrays(configp);
396           return 0;
397        }
398     }
399 
400     /* Commands other than those handled above require */
401     /* a configuration file and file locking.          */
402 
403     if ( strcmp(argv[1], "stop") == 0 )
404        read_minimal_config ( CONFIG_INIT, SRC_STOP );
405     else
406        read_config(CONFIG_INIT);
407 
408     if ( is_heyu_cmd(argv[1]) ) {
409          /* This is a direct command */
410          c = cmdtab;
411          rtn = c->cmd_routine;
412     }
413     else {
414         /* This is an administrative or state command */
415         for (c = cmdtab + 1; c->cmd_routine != NULL; c++) {
416 	    if (strcmp(argv[1], c->cmd_name) == 0) {
417                 if ( !(configp->device_type & DEV_DUMMY) || c->internal_cmd ) {
418 	           rtn = c->cmd_routine;
419                    break;
420                 }
421                 else {
422                    fprintf(stderr,
423                       "Command '%s' is not valid for TTY dummy\n", c->cmd_name);
424                    return 1;
425                 }
426 	    }
427         }
428     }
429 
430     if ( rtn == NULL )  {
431        fprintf(stderr,
432           "Usage: heyu [options] <command>  (Enter 'heyu help' for commands.)\n");
433        return 1;
434     }
435 
436 
437     if ( (strcmp("stop", c->cmd_name) == 0 ) ||
438          (strcmp("version", c->cmd_name) == 0) ||
439          (strcmp("help", c->cmd_name) == 0) )     {
440        retcode = (*rtn)();		/* exits */
441        free_all_arrays(configp);
442        return retcode;
443     }
444 
445     /* Check read/write permissions for spoolfile directory */
446     if ( check_dir_rw(SPOOLDIR, "SPOOL") != 0 ) {
447        fprintf(stderr, "%s\n", error_message());
448        return 1;
449     }
450 
451     if ( quick_ports_check() != 0 ) {
452        fprintf(stderr, "Serial port %s is in use by another program.\n", configp->ttyaux);
453        return 1;
454     }
455 
456     if ( c->lock_needed == 1 ) {
457        if ( lock_for_write() < 0 )
458           error("Program exiting.\n");
459        port_locked = 1;
460     }
461 
462     argptr = argv[0];
463 
464     /* Setup alert command arrays */
465     create_alerts();
466 
467     /* Check for and start relay if not already running */
468     start_relay(configp->tty);
469     if ( ! i_am_relay ) {
470       setup_sp_tty();
471     }
472 
473     if ( strcmp("start", c->cmd_name) == 0 &&
474        check_for_engine() != 0 &&
475        configp->start_engine == AUTOMATIC )  {
476        if ( heyu_parent == D_CMDLINE )
477           printf("starting heyu_engine\n");
478        init("engine");
479        c_start_engine(argc, argv);
480     }
481 
482     if ( strcmp("start", c->cmd_name) == 0 &&
483        check_for_aux() != 0 &&
484        configp->ttyaux[0] != '\0' ) {
485           if ( heyu_parent == D_CMDLINE )
486              printf("starting heyu_aux\n");
487           init("aux");
488           c_start_aux(argc, argv);
489     }
490 
491 
492 #ifdef MINIEXCH
493     mxconnect(MINIXPORT);
494 #endif
495 
496     init(c->cmd_name);
497 
498     retcode = (*rtn) (argc, argv);
499     if ( port_locked == 1 ) {
500        sprintf(writefilename, "%s%s", WRITEFILE, configp->suffix);
501        munlock(writefilename);
502     }
503     free_all_arrays(configp);
504     return retcode;
505 }
506 
507 /*-------------------------------------------------------------------+
508  |  Init                                                             |
509  +-------------------------------------------------------------------*/
510 
init(char * cmd_name)511 void init ( char *cmd_name )
512 {
513 
514     timeout = TIMEOUT;
515     if( strcmp(cmd_name, "monitor") == 0 )
516     {
517 	check4poll(1, 2);
518     }
519     else if ( strcmp(cmd_name, "engine") == 0 )
520         check4poll(0, 0);
521     else if ( strcmp(cmd_name, "info") == 0 )
522         check4poll(0, 0) ;
523     else
524 	check4poll(0, 0);
525 
526     /* Now check the status of the interface. */
527     /* if( get_status() < 1)
528         error("could not get the interface status");
529     */
530 }
531 
532 
533 
534 /*
535  * Convert X10-style day of week (bit map, bit 0=monday, 6=sunday)
536  * to UNIX localtime(3) style day of week (integer, 0=sunday)
537  */
538 /* DBS  NOTE:  This is valid for CP290, not for CM11A.
539  * The CM11A uses unix style.
540  */
541 
542 
dowX2U(b)543 int dowX2U(b)
544 register char b;
545 {
546     register int n;
547 
548     for (n = 1; (!(b & 1)) && n < 8; n++, b = b >> 1)
549     	;
550     if (n == 7)
551 	n = 0;
552     if (n == 8)
553 	n = 7;
554     return (n);
555 }
556 
557 
558 
dowU2X(d)559 int dowU2X(d)
560 int d;
561 {
562     if (d == 0)
563 	d = 7;
564     return (1 << (d - 1));
565 }
566 
567 
568 
read_config(unsigned char mode)569 int read_config( unsigned char mode )
570 {
571    int retcode;
572 
573    /* Read the user's Heyu configuration file and store in */
574    /* global CONFIG structure 'config'.  Transfer some of  */
575    /* the data into existing variables.                    */
576 
577    retcode = get_configuration(mode);
578 
579    x10_housecode = hc2code(configp->housecode);
580 
581    return retcode;
582 }
583 
584 
585 /* Takes the bits in CM11A format (as used in the reply to a status)
586  * and returns a day string.
587  * The b parameter is for bitmap */
bits2day(b)588 char *bits2day(b)
589 int b;
590 {
591 
592    switch(b)
593    {
594        case 1:
595 	   return("Sun");
596        case 2:
597 	   return("Mon");
598        case 4:
599 	   return("Tue");
600        case 8:
601 	   return("Wed");
602        case 16:
603 	   return("Thu");
604        case 32:
605 	   return("Fri");
606        case 64:
607 	   return("Sat");
608     }
609     return("Error");
610 }
611 
c_version()612 int c_version()
613 {
614     printf( "Version:%4s\n", VERSION );
615     return(0);
616 }
617 
display(RCCS)618 void display(RCCS)
619 char *RCCS;
620 {
621 
622     /* This is not used much so far */
623     if( verbose > 1)
624         printf( "%s\n", RCCS);
625 }
626 
627 
628 /* List the variables as built into the program at compile time */
c_list()629 int c_list ()
630 {
631    if ( verbose ) {
632       printf( "Version: %s\n", VERSION );
633       printf( "The SPOOLDIR is %s\n", SPOOLDIR);
634       printf( "The LOCKDIR is %s\n", LOCKDIR);
635       printf( "The SYSBASEDIR is %s\n", SYSBASEDIR);
636       printf( "Number of Flags = %d\n", (32 * NUM_FLAG_BANKS));
637       printf( "Number of Counters = %d\n", (32 * NUM_COUNTER_BANKS));
638       printf( "Number of Timers = %d\n", (32 * NUM_TIMER_BANKS));
639    }
640    else {
641       printf( "Version=%s\n", VERSION );
642       printf( "SPOOLDIR=%s\n", SPOOLDIR);
643       printf( "LOCKDIR=%s\n", LOCKDIR);
644       printf( "SYSBASEDIR=%s\n", SYSBASEDIR);
645       printf( "Flags=%d\n", (32 * NUM_FLAG_BANKS));
646       printf( "Counters=%d\n", (32 * NUM_COUNTER_BANKS));
647       printf( "Timers=%d\n", (32 * NUM_TIMER_BANKS));
648    }
649 
650    return 0;
651 }
652 
653 /* Start command does nothing by itself */
654 /* but allows daemons to start.         */
c_start(int argc,char * argv[])655 int c_start( int argc, char *argv[] )
656 {
657    return 0;
658 }
659 
660 /* Reread configuration file */
reread_config(void)661 int reread_config ( void )
662 {
663    config.read_flag = 0;
664 
665    /* Null out the option pointers so a restart will use */
666    /* the config file defined by env variable X10CONFIG  */
667    if ( i_am_state || i_am_relay || i_am_aux || i_am_monitor ) {
668       optptr->configp = NULL;
669       optptr->subp = NULL;
670    }
671 
672    return read_config(CONFIG_RESTART);
673 
674 }
675 
676 /* Check existance and read/write ability of a directory */
check_dir_rw(char * pathspec,char * label)677 int check_dir_rw ( char *pathspec, char *label )
678 {
679    struct stat statb;
680    gid_t       grps[100];
681    int         ngrps, j;
682    char        errmsg[256];
683    int         msgl = sizeof(errmsg) - 1;
684 
685    clear_error_message();
686 
687    if ( stat(pathspec, &statb) != 0 ) {
688       snprintf(errmsg, msgl, "%s directory %s does not exist", label, pathspec);
689       store_error_message(errmsg);
690       return 1;
691    }
692 
693 #ifdef POSIX
694    if ( S_ISDIR(statb.st_mode) == 0 ) {
695 #else
696    if ( (statb.st_mode & S_IFDIR) != S_IFDIR ) {
697 #endif
698       snprintf(errmsg, msgl, "%s %s is not a directory", label, pathspec);
699       store_error_message(errmsg);
700       return 1;
701    }
702 
703    if ( getuid() == 0 )
704       return 0;
705 
706    if ( (statb.st_mode & S_IRWXU) == S_IRWXU &&
707         (statb.st_uid == getuid() || statb.st_uid == geteuid()) ) {
708       return 0;
709    }
710 
711    if ( (statb.st_mode & S_IRWXG) == S_IRWXG ) {
712       if ( (ngrps = getgroups((sizeof(grps)/sizeof(gid_t)) - 1, grps)) < 0 ) {
713          snprintf(errmsg, msgl, "Internal error - getgroups()");
714          store_error_message(errmsg);
715          return 1;
716       }
717       grps[ngrps++] = getegid();
718       for ( j = 0; j < ngrps; j++ ) {
719          if ( statb.st_gid == grps[j] )
720             return 0;
721       }
722    }
723 
724    if ( ((statb.st_mode & S_IRWXO) == S_IRWXO) )
725       return 0;
726 
727    snprintf(errmsg, msgl, "Insufficient r/w permission for %s directory %s", label, pathspec);
728    store_error_message(errmsg);
729    return 1;
730 }
731 
732