1 /******************************************************************************
2     (c) 2000-2008 Christine Caulfield                 christine.caulfield@googlemail.com
3     (c) 2003 Dmitri Popov
4 
5     This program is free software; you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation; either version 2 of the License, or
8     any later version.
9 
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14 ******************************************************************************/
15 
16 // LAT Control Program (latcp)
17 
18 
19 #include <sys/types.h>
20 #include <sys/uio.h>
21 #include <sys/socket.h>
22 #include <sys/un.h>
23 #include <sys/ioctl.h>
24 #include <sys/wait.h>
25 #include <sys/stat.h>
26 #include <sys/time.h>
27 #include <sys/utsname.h>
28 #include <stdio.h>
29 #include <errno.h>
30 #include <unistd.h>
31 #include <signal.h>
32 #include <string.h>
33 #include <fcntl.h>
34 #include <syslog.h>
35 #include <ctype.h>
36 #include <regex.h>
37 #include <stdlib.h>
38 // #include <utmp.h>
39 #include <pwd.h>
40 #include <signal.h>
41 #include <limits.h>
42 #include <assert.h>
43 
44 #include <list>
45 #include <queue>
46 #include <map>
47 #include <string>
48 #include <algorithm>
49 #include <iterator>
50 #include <string>
51 #include <sstream>
52 #include <iostream>
53 
54 #include "lat.h"
55 #include "latcp.h"
56 #include "utils.h"
57 #include "dn_endian.h"
58 
59 static int latcp_socket;
60 
61 static void make_upper(char *str);
62 
63 int  read_reply(int fd, int &cmd, unsigned char *&cmdbuf, int &len);
64 bool send_msg(int fd, int cmd, char *buf, int len);
65 bool open_socket(bool);
66 
67 // Command processing routines
68 void display(int argc, char *argv[]);
69 void add_service(int argc, char *argv[]);
70 void del_service(int argc, char *argv[]);
71 void set_multicast(int);
72 void set_retransmit(int);
73 void set_keepalive(int);
74 void set_responder(int onoff);
75 void shutdown();
76 void purge_services();
77 void start_latd(int argc, char *argv[]);
78 void set_rating(int argc, char *argv[]);
79 void set_ident(int argc, char *argv[]);
80 void set_server_groups(int argc, char *argv[]);
81 void set_user_groups(int argc, char *argv[]);
82 void set_node (char *);
83 
84 
85 // Misc utility routines
86 static void make_bitmap(char *bitmap, char *cmdline);
87 
88 
usage(char * cmd)89 int usage(char *cmd)
90 {
91     printf ("Usage: latcp      {option}\n");
92     printf ("     where option is one of the following:\n");
93     printf ("       -s [<latd args>]\n");
94     printf ("       -h\n");
95     printf ("       -A -a service [-i description] [-r rating] [-s] [-C command] [-u user] [-m max conn]\n");
96     printf ("       -A -p tty -V learned_service [-R rem_port] [-H rem_node] [-Q] [-8]\n");
97     printf ("       -D {-a service | -p tty}\n");
98     printf ("       -C service command}\n");
99     printf ("       -i description -a service\n");
100     printf ("       -g list\n");
101     printf ("       -G list\n");
102     printf ("       -u list\n");
103     printf ("       -U list\n");
104     printf ("       -j\n");
105     printf ("       -J\n");
106     printf ("       -Y\n");
107     printf ("       -x rating [-s] -a service\n");
108     printf ("       -n node\n");
109     printf ("       -r retransmit limit\n");
110     printf ("       -m multicast timer (100ths/sec)\n");
111     printf ("       -k keepalive timer (seconds)\n");
112     printf ("       -d [ [-l [-v] [-n] ] ]\n");
113     printf ("       -z \n");
114 
115     return 2;
116 }
117 
main(int argc,char * argv[])118 int main(int argc, char *argv[])
119 {
120 
121 // Parse the command.
122 // because the args vary so much for each command I just check argv[1]
123 // for the command switch and the command processors call getopt themselves
124 
125     if (argc == 1)
126     {
127 	exit(usage(argv[0]));
128     }
129 
130     if (argv[1][0] != '-')
131     {
132 	exit(usage(argv[0]));
133     }
134 
135     switch (argv[1][1])
136     {
137     case 'A':
138 	add_service(argc-1, &argv[1]);
139 	break;
140     case 'D':
141 	del_service(argc-1, &argv[1]);
142 	break;
143     case 'j':
144 	set_responder(1);
145 	break;
146     case 'J':
147 	set_responder(0);
148 	break;
149     case 'Y':
150 	purge_services();
151 	break;
152     case 'n':
153 	set_node(argv[2]);
154 	break;
155     case 'm':
156 	if (argv[2])
157 	    set_multicast(atoi(argv[2]));
158 	else
159 	    exit(usage(argv[0]));
160 	break;
161     case 'r':
162         if (argv[2])
163             set_retransmit(atoi(argv[2]));
164         else
165             exit(usage(argv[0]));
166         break;
167     case 'k':
168         if (argv[2])
169             set_keepalive(atoi(argv[2]));
170         else
171             exit(usage(argv[0]));
172         break;
173     case 'd':
174 	display(argc-1, &argv[1]);
175 	break;
176     case 'h':
177 	shutdown();
178 	break;
179     case 's':
180 	start_latd(argc, argv);
181 	break;
182     case 'x':
183 	set_rating(argc, argv);
184 	break;
185     case 'i':
186 	set_ident(argc, argv);
187 	break;
188     case 'z':
189 	printf("counters not yet done\n");
190 	break;
191     case 'U':
192 	set_user_groups(argc, argv);
193 	break;
194     case 'u':
195 	set_user_groups(argc, argv);
196 	break;
197     case 'g':
198 	set_server_groups(argc, argv);
199 	break;
200     case 'G':
201 	set_server_groups(argc, argv);
202 	break;
203     default:
204 	exit(usage(argv[0]));
205 	break;
206     }
207 }
208 
209 
210 // Display latd characteristics or learned services
display(int argc,char * argv[])211 void display(int argc, char *argv[])
212 {
213     char verboseflag[1] = {'\0'};
214     signed char opt;
215     bool show_services = false;
216     bool show_nodes = false;
217 
218     if (!open_socket(false)) return;
219 
220     while ((opt=getopt(argc,argv,"lvn")) != EOF)
221     {
222 	switch(opt)
223 	{
224 	case 'l':
225 	    show_services=true;
226 	    break;
227 
228 	case 'v':
229 	    verboseflag[0] = 1;
230 	    break;
231 
232 	case 'n':
233 	    show_nodes = true;
234 	    break;
235 
236 	default:
237 	    fprintf(stderr, "only -v, -n or -l valid with -d flag\n");
238 	    exit(2);
239 	}
240     }
241 
242      if (show_nodes)
243      {
244      	send_msg(latcp_socket, LATCP_SHOWNODES, verboseflag, 1);
245          unsigned char *result;
246          int len;
247          int cmd;
248          if (!read_reply(latcp_socket, cmd, result, len))
249 	 {
250 		 std::cout << result;
251 
252 		 delete[] result;
253 	 }
254          return;
255      }
256 
257     if (show_services)
258     {
259 	send_msg(latcp_socket, LATCP_SHOWSERVICE, verboseflag, 1);
260     }
261     else
262     {
263 	send_msg(latcp_socket, LATCP_SHOWCHAR, verboseflag, 1);
264     }
265 
266     unsigned char *result = NULL;
267     int len;
268     int cmd;
269 
270     if (!read_reply(latcp_socket, cmd, result, len))
271     {
272 	    std::cout << result;
273 
274 	    delete[] result;
275     }
276 }
277 
278 
279 // Change the rating of a service
set_rating(int argc,char * argv[])280 void set_rating(int argc, char *argv[])
281 {
282     int new_rating = 0;
283     bool static_rating = false;
284     char service[256];
285     signed char opt;
286 
287     if (!open_socket(false)) return;
288 
289     while ((opt=getopt(argc,argv,"x:sa:")) != EOF)
290     {
291 	switch(opt)
292 	{
293 	case 'x':
294 	    new_rating = atoi(optarg);
295 	    break;
296 
297 	case 's':
298 	    static_rating = true;
299 	    break;
300 
301 	case 'a':
302 	    strcpy(service, optarg);
303 	    make_upper(service);
304 	    break;
305 
306 	default:
307 	    fprintf(stderr, "only valid with -a and -x flags\n");
308 	    exit(2);
309 	}
310     }
311 
312     if (!new_rating)
313     {
314 	fprintf(stderr, "Invalid rating\n");
315 	exit(2);
316     }
317 
318     make_upper(service);
319 
320     char message[520];
321     int ptr = 2;
322     message[0] = (int)static_rating;
323     message[1] = new_rating;
324     add_string((unsigned char*)message, &ptr, (unsigned char*)service);
325     send_msg(latcp_socket, LATCP_SETRATING, message, ptr);
326 
327     // Wait for ACK or error
328     unsigned char *result = NULL;
329     int len;
330     int cmd;
331 
332     exit (read_reply(latcp_socket, cmd, result, len));
333 
334 }
335 
336 
337 // Change the ident of a service
set_ident(int argc,char * argv[])338 void set_ident(int argc, char *argv[])
339 {
340     char service[256];
341     char ident[256];
342     signed char opt;
343 
344     if (!open_socket(false)) return;
345 
346     while ((opt=getopt(argc,argv,"i:a:")) != EOF)
347     {
348 	switch(opt)
349 	{
350 	case 'a':
351 	    strcpy(service, optarg);
352 	    make_upper(service);
353 	    break;
354 	case 'i':
355 	    strcpy(ident, optarg);
356 	    break;
357 
358 	default:
359 	    fprintf(stderr, "must have both -i and -a flags\n");
360 	    exit(2);
361 	}
362     }
363 
364     make_upper(service);
365 
366     char message[1024];
367     int ptr = 0;
368     add_string((unsigned char*)message, &ptr, (unsigned char*)service);
369     add_string((unsigned char*)message, &ptr, (unsigned char*)ident);
370     send_msg(latcp_socket, LATCP_SETIDENT, message, ptr);
371 
372     // Wait for ACK or error
373     unsigned char *result = NULL;
374     int len;
375     int cmd;
376     exit(read_reply(latcp_socket, cmd, result, len));
377 }
378 
379 
set_server_groups(int argc,char * argv[])380 void set_server_groups(int argc, char *argv[])
381 {
382     signed char opt;
383     int  cmd;
384     char groups[256];
385 
386     while ((opt=getopt(argc,argv,"G:g:")) != EOF)
387     {
388 	switch(opt)
389 	{
390 	case 'G':
391 	    cmd = LATCP_SETSERVERGROUPS;
392 	    strcpy(groups, optarg);
393 	    break;
394 
395 	case 'g':
396 	    cmd = LATCP_UNSETSERVERGROUPS;
397 	    strcpy(groups, optarg);
398 	    break;
399 
400 	default:
401 	    fprintf(stderr, "Just G or g please\n");
402 	    exit(2);
403 	}
404     }
405 
406     if (!open_socket(false)) return;
407 
408     char bitmap[32]; // 256 bits
409     make_bitmap(bitmap, groups);
410 
411     send_msg(latcp_socket, cmd, bitmap, 32);
412 
413     // Wait for ACK or error
414     unsigned char *result = NULL;
415     int len;
416     exit(read_reply(latcp_socket, cmd, result, len));
417 
418 }
419 
set_user_groups(int argc,char * argv[])420 void set_user_groups(int argc, char *argv[])
421 {
422     signed char opt;
423     int  cmd;
424     char groups[256];
425 
426     while ((opt=getopt(argc,argv,"u:U:")) != EOF)
427     {
428 	switch(opt)
429 	{
430 	case 'U':
431 	    cmd = LATCP_SETUSERGROUPS;
432 	    strcpy(groups, optarg);
433 	    break;
434 
435 	case 'u':
436 	    cmd = LATCP_UNSETUSERGROUPS;
437 	    strcpy(groups, optarg);
438 	    break;
439 
440 	default:
441 	    fprintf(stderr, "Just U or u please\n");
442 	    exit(2);
443 	}
444     }
445 
446     if (!open_socket(false)) return;
447 
448     char bitmap[32]; // 256 bits
449     make_bitmap(bitmap, groups);
450 
451     send_msg(latcp_socket, cmd, bitmap, 32);
452 
453     // Wait for ACK or error
454     unsigned char *result = NULL;
455     int len;
456     exit(read_reply(latcp_socket, cmd, result, len));
457 
458 }
459 
460 // Enable/Disable the service responder
set_responder(int onoff)461 void set_responder(int onoff)
462 {
463     if (!open_socket(false)) return;
464 
465     char flag[1];
466     flag[0] = onoff;
467     send_msg(latcp_socket, LATCP_SETRESPONDER, flag, 1);
468 }
469 
470 // Shutdown latd
shutdown()471 void shutdown()
472 {
473     if (!open_socket(false)) return;
474 
475     char dummy[1];
476     send_msg(latcp_socket, LATCP_SHUTDOWN, dummy, 0);
477 }
478 
479 // Purge learned services
purge_services()480 void purge_services()
481 {
482     if (!open_socket(false)) return;
483 
484     char dummy[1];
485     send_msg(latcp_socket, LATCP_PURGE, dummy, 0);
486 }
487 
set_multicast(int newtime)488 void set_multicast(int newtime)
489 {
490     if (newtime < 10 || newtime > 180)
491     {
492 	fprintf(stderr, "invalid multicast time\n");
493 	return;
494     }
495     if (!open_socket(false)) return;
496 
497     send_msg(latcp_socket, LATCP_SETMULTICAST, (char *)&newtime, sizeof(int));
498 }
499 
set_retransmit(int newlim)500 void set_retransmit(int newlim)
501 {
502     if (newlim < 4 || newlim > 120)
503     {
504         fprintf(stderr, "invalid retransmit limit\n");
505         return;
506     }
507     if (!open_socket(false)) return;
508 
509     send_msg(latcp_socket, LATCP_SETRETRANS, (char *)&newlim, sizeof(int));
510 }
511 
set_keepalive(int newtime)512 void set_keepalive(int newtime)
513 {
514     if (newtime < 10 || newtime > 180)
515     {
516 	fprintf(stderr, "invalid keepalive timer\n");
517 	return;
518     }
519     if (!open_socket(false)) return;
520 
521     send_msg(latcp_socket, LATCP_SETKEEPALIVE, (char *)&newtime, sizeof(int));
522 }
523 
set_node(char * name)524 void set_node(char *name)
525 {
526     if (!open_socket(false)) return;
527 
528     make_upper(name);
529 
530     char message[520];
531     int ptr = 0;
532     add_string((unsigned char*)message, &ptr, (unsigned char*)name);
533 
534     send_msg(latcp_socket, LATCP_SETNODENAME, message, ptr);
535     return;
536 }
537 
add_service(int argc,char * argv[])538 void add_service(int argc, char *argv[])
539 {
540     char name[255] = {'\0'};
541     char ident[255] = {'\0'};
542     char remport[255] = {'\0'};
543     char localport[255] = {'\0'};
544     char remnode[255] = {'\0'};
545     char remservice[255] = {'\0'};
546     char password[255] = {'\0'};
547     char command[1024] = {'\0'};
548     signed char opt;
549     bool got_service=false;
550     bool got_port=false;
551     bool static_rating=false;
552     int  rating = 0;
553     int  queued = 0;
554     int  clean = 0;
555     int  max_connections = 0;
556     uid_t target_uid = 0;
557     gid_t target_gid = 0;
558     struct passwd *target_user;
559 
560     opterr = 0;
561     while ((opt=getopt(argc,argv,"a:i:p:H:R:V:r:w:sQ8C:m:u:")) != EOF)
562     {
563 	switch(opt)
564 	{
565 	case 'a':
566 	    got_service=true;
567 	    strcpy(name, optarg);
568 	    make_upper(name);
569 	    break;
570 
571 	case 'i':
572 	    got_service=true;
573 	    strcpy(ident, optarg);
574 	    break;
575 
576 	case 'w':
577 	    strcpy(password, optarg);
578 	    break;
579 
580 	case 'p':
581 	    got_port=true;
582 	    strcpy(localport, optarg);
583 	    if (strncmp(localport, LAT_DIRECTORY, strlen(LAT_DIRECTORY)) != 0)
584 	    {
585 		fprintf(stderr, "Local port name must start " LAT_DIRECTORY "\n");
586 		return;
587 	    }
588 	    break;
589 
590 	case 'H':
591 	    got_port=true;
592 	    strcpy(remnode, optarg);
593 	    make_upper(remnode);
594 	    break;
595 
596 	case 'R':
597 	    got_port=true;
598 	    strcpy(remport, optarg);
599 	    make_upper(remport);
600 	    break;
601 
602 	case 'V':
603 	    got_port=true;
604 	    strcpy(remservice, optarg);
605 	    make_upper(remservice);
606 	    break;
607 
608 	case 'Q':
609 	    got_port=true;
610 	    queued = 1;
611 	    break;
612 
613 	case 's':
614 	    static_rating = true;
615 	    break;
616 
617 	case '8':
618 	    clean = true;
619 	    break;
620 
621 	case 'C':
622 	    strcpy(command, optarg);
623 	    break;
624 
625 	case 'u':
626 	    target_user = getpwnam(optarg);
627 	    if (target_user == NULL)
628 	    {
629 		fprintf(stderr, "Unknown username '%s'\n", optarg);
630 		exit(99);
631 	    }
632 	    target_uid = target_user->pw_uid;
633 	    target_gid = target_user->pw_gid;
634 	    break;
635 
636 	case 'm':
637 	    max_connections = atoi(optarg);
638 	    break;
639 
640 	case 'r':
641 	    rating = atoi(optarg);
642 	    break;
643 
644 	default:
645 	    fprintf(stderr, "No more service switches defined yet\n");
646 	    exit(2);
647 	}
648     }
649 
650     if (!open_socket(false)) return;
651 
652     // Variables for ACK message
653     unsigned char *result = NULL;
654     int len;
655     int cmd;
656 
657     if (got_service)
658     {
659 	if (name[0] == '\0')
660 	{
661 	    fprintf(stderr, "No name for new service\n");
662 	    exit(2);
663 	}
664 
665 	char message[520];
666 	int ptr = 2;
667 	message[0] = (int)static_rating;
668 	message[1] = rating;
669 	add_string((unsigned char*)message, &ptr, (unsigned char*)name);
670 	add_string((unsigned char*)message, &ptr, (unsigned char*)ident);
671 	message[ptr++] = max_connections;
672 	memcpy(message+ptr, &target_uid, sizeof(uid_t)); ptr += sizeof(uid_t);
673 	memcpy(message+ptr, &target_gid, sizeof(uid_t)); ptr += sizeof(gid_t);
674 	add_string((unsigned char*)message, &ptr, (unsigned char*)command);
675 
676 	send_msg(latcp_socket, LATCP_ADDSERVICE, message, ptr);
677 
678 	// Wait for ACK or error
679 	exit(read_reply(latcp_socket, cmd, result, len));
680     }
681 
682     if (got_port)
683     {
684 	char message[520];
685 	int ptr = 0;
686 	add_string((unsigned char*)message, &ptr, (unsigned char*)remservice);
687 	add_string((unsigned char*)message, &ptr, (unsigned char*)remport);
688 	add_string((unsigned char*)message, &ptr, (unsigned char*)localport);
689 	add_string((unsigned char*)message, &ptr, (unsigned char*)remnode);
690 	message[ptr++] = queued;
691 	message[ptr++] = clean;
692 	add_string((unsigned char*)message, &ptr, (unsigned char*)password);
693 	send_msg(latcp_socket, LATCP_ADDPORT, message, ptr);
694 
695 	// Wait for ACK or error
696 	exit(read_reply(latcp_socket, cmd, result, len));
697     }
698 
699     fprintf(stderr, "Sorry, did you want me to do something??\n");
700 }
701 
del_service(int argc,char * argv[])702 void del_service(int argc, char *argv[])
703 {
704     char name[255] = {'\0'};
705     signed char opt;
706     bool got_service = false;
707     bool got_port = false;
708     opterr = 0;
709 
710     while ((opt=getopt(argc,argv,"a:p:")) != EOF)
711     {
712 	switch(opt)
713 	{
714 	case 'a':
715 	    got_service = true;
716 	    strcpy(name, optarg);
717 	    make_upper(name);
718 	    break;
719 
720 	case 'p':
721 	    got_port = true;
722 	    strcpy(name, optarg);
723 	    break;
724 
725 	default:
726 	    fprintf(stderr, "No more service switches defined yet\n");
727 	    exit(2);
728 	}
729     }
730 
731     if ((got_port && got_service) ||
732 	(!got_port && !got_service))
733     {
734 	fprintf(stderr, "Either -a or -p can be specified but not both\n");
735 	return;
736     }
737 
738 
739     if (!open_socket(false)) return;
740 
741     char message[520];
742     int ptr = 0;
743     add_string((unsigned char*)message, &ptr, (unsigned char*)name);
744     if (got_service)
745 	send_msg(latcp_socket, LATCP_REMSERVICE, message, ptr);
746     else
747 	send_msg(latcp_socket, LATCP_REMPORT, message, ptr);
748 
749     unsigned char *result = NULL;
750     int len;
751     int cmd;
752     exit(read_reply(latcp_socket, cmd, result, len));
753 }
754 
755 // Start latd & run startup script.
start_latd(int argc,char * argv[])756 void start_latd(int argc, char *argv[])
757 {
758     if (getuid() != 0)
759     {
760 	fprintf(stderr, "You must be root to start latd\n");
761 	return;
762     }
763 
764     // If we can connect to LATD than it's already running
765     if (open_socket(true))
766     {
767 	fprintf(stderr, "LAT is already running\n");
768 	return;
769     }
770 
771     // Look for latd in well-known places
772     struct stat st;
773     char *latd_bin = NULL;
774     char *latd_path = NULL;
775 
776     // Look for latd in the same place as latcp
777     char *name = (char *)malloc(strlen(argv[0])+1);
778     char *path = (char *)malloc(strlen(argv[0])+1);
779     strcpy(name, argv[0]);
780 
781     char *slash = rindex(name, '/');
782     if (slash)
783     {
784 	*slash='\0';
785 	strcpy(path, name);
786 	strcat(name, "/latd");
787 	if (!stat(name, &st))
788 	{
789 	    latd_bin = name;
790 	    latd_path = path;
791 	}
792     }
793     // Otherwise look in some well-known places
794     else if (!stat("/usr/sbin/latd", &st))
795     {
796 	    latd_bin = (char *)"/usr/sbin/latd";
797 	    latd_path = (char *)"/usr/sbin";
798     }
799     else if (!stat("/usr/local/sbin/latd", &st))
800     {
801 	    latd_bin = (char *)"/usr/local/sbin/latd";
802 	    latd_path = (char *)"/usr/local/sbin";
803     }
804 
805     // Did we find it?
806     if (latd_bin)
807     {
808         char *newargv[argc+1];
809 	char *newenv[4];
810 	int   i;
811 	char  latcp_bin[PATH_MAX];
812 	char  latcp_env[PATH_MAX+7];
813 
814 // This is VERY Linux specific and needs /proc mounted.
815 // we get the full path of the current executable by doing a readlink.
816 // /proc/<pid>/exe
817 
818 #ifdef __linux__
819 	char  latcp_proc[PATH_MAX];
820 
821 	sprintf(latcp_proc, "/proc/%d/exe", getpid());
822 	if ( (i=readlink(latcp_proc, latcp_bin, sizeof(latcp_bin))) == -1)
823 	{
824 	    fprintf(stderr, "readlink in /proc failed. Make sure the the proc filesystem is mounted on /proc\n");
825 	    exit(2);
826 	}
827 #endif
828 	sprintf(latcp_env, "LATCP=%s", latcp_bin);
829 
830 	newargv[0] = latd_bin;
831 	newargv[1] = NULL;
832 	newenv[0] = (char *)"PATH=/bin:/usr/bin:/sbin:/usr/sbin";
833 	newenv[1] = (char*)"LATCP_STARTED=true"; // Tell latd it was started by us.
834 	newenv[2] = latcp_env;
835 	newenv[3] = NULL;
836 
837 	switch(fork())
838 	{
839 	case 1: //Error
840 	    perror("fork failed");
841 	    return;
842 	case 0: // Child
843 	    // Start latd with our args (after the "-s")
844 	    for (i=2; i<argc; i++)
845 		newargv[i-1] = argv[i];
846 	    newargv[i-1] = NULL;
847 
848 	    execve(latd_bin, newargv, newenv);
849 	    perror("exec of latd failed");
850 	    break;
851 
852 	default: //Parent
853 	    {
854 		// Wait for latd to start up
855 		int count = 0;
856 		while (!open_socket(true) && count < 10)
857 		{
858 		    sleep(1);
859 		    count++;
860 		}
861 		if (count >= 10)
862 		{
863 		    fprintf(stderr, "latd did not start\n");
864 		    exit(2);
865 		}
866 
867 
868 		// Run startup script if there is one.
869 		if (!stat("/etc/latd.conf", &st))
870 		{
871 		    pid_t shell_pid;
872 		    switch ( (shell_pid=fork()) )
873 		    {
874 		    case 0: // Child
875 			newargv[0] = (char *)"/bin/sh";
876 			newargv[1] = (char *)"/etc/latd.conf";
877 			newargv[2] = NULL;
878 			execve("/bin/sh", newargv, newenv);
879 			perror("exec of /bin/sh failed");
880 			exit(0);
881 
882 		    case -1:
883 			perror("Fork failed");
884 			exit(0);
885 
886 		    default: // Parent. Wait for child to finish
887 			waitpid(shell_pid, NULL, 0);
888 		    }
889 		}
890 		// OK, latd has started and we have run the startup script.
891 		// Now "unlock" latd. ie tell it we have finished initialisation
892 		char dummy[1];
893 		send_msg(latcp_socket, LATCP_UNLOCK, dummy, 0);
894 	    }
895 	    break;
896 	}
897     }
898     else
899     {
900 	fprintf(stderr, "cannot find latd\n");
901 	return;
902     }
903 }
904 
905 
send_msg(int fd,int cmd,char * buf,int len)906 bool send_msg(int fd, int cmd, char *buf, int len)
907 {
908     unsigned char outhead[3];
909 
910     outhead[0] = cmd;
911     outhead[1] = len/256;
912     outhead[2] = len%256;
913     if (write(fd, outhead, 3) != 3) return false;
914     if (write(fd, buf, len) != len) return false;
915 
916     return true;
917 }
918 
919 
920 // Return 0 for success and -1 for failure
read_reply(int fd,int & cmd,unsigned char * & cmdbuf,int & len)921 int read_reply(int fd, int &cmd, unsigned char *&cmdbuf, int &len)
922 {
923     unsigned char head[3];
924 
925     // Get the message header (cmd & length)
926     if (read(fd, head, sizeof(head)) != 3)
927 	return -1; // Bad header
928 
929     len = head[1] * 256 + head[2];
930     cmd = head[0];
931     cmdbuf = new unsigned char[len];
932     if (cmdbuf == NULL)
933 	return -1;
934 
935     // Read the message buffer
936     if (read(fd, cmdbuf, len) != len)
937     {
938 	return -1; // Bad message
939     }
940 
941     if (cmd == LATCP_ERRORMSG)
942     {
943 	fprintf(stderr, "%s\n", cmdbuf);
944 	return -1;
945     }
946 
947     return 0;
948 }
949 
open_socket(bool quiet)950 bool open_socket(bool quiet)
951 {
952     struct sockaddr_un sockaddr;
953 
954     latcp_socket = socket(PF_UNIX, SOCK_STREAM, 0);
955     if (latcp_socket == -1)
956     {
957 	if (!quiet) perror("Can't create socket");
958 	return false; /* arggh ! */
959     }
960 
961     strcpy(sockaddr.sun_path, LATCP_SOCKNAME);
962     sockaddr.sun_family = AF_UNIX;
963     if (connect(latcp_socket, (struct sockaddr *)&sockaddr, sizeof(sockaddr)))
964     {
965 	if (!quiet) perror("Can't connect to latd");
966 	close(latcp_socket);
967 	return false;
968     }
969 
970     unsigned char *result = NULL;
971     int len;
972     int cmd;
973 
974     // Send our version
975     send_msg(latcp_socket, LATCP_VERSION, (char*)VERSION, strlen(VERSION)+1);
976 
977     if (!read_reply(latcp_socket, cmd, result, len)) // Read version number back
978 	delete[] result;
979 
980     return true;
981 }
982 
make_upper(char * str)983 static void make_upper(char *str)
984 {
985     unsigned int i;
986 
987     for (i=0; i<strlen(str); i++)
988     {
989 	str[i] = toupper(str[i]);
990     }
991 }
992 
set_in_bitmap(char * bits,int entry)993 static inline void set_in_bitmap(char *bits, int entry)
994 {
995 
996     if (entry < 256)
997     {
998 	unsigned int  intnum;
999 	unsigned int  bitnum;
1000 
1001 	intnum = entry / 8;
1002 	bitnum = entry % 8;
1003 	bits[intnum] |= 1<<bitnum;
1004     }
1005 }
1006 
make_bitmap(char * bitmap,char * cmdline)1007 static void make_bitmap(char *bitmap, char *cmdline)
1008 {
1009     int   firstnum;
1010     int   secondnum;
1011     int   i;
1012     bool  finished = false;
1013     char  delimchar;
1014     char* delimiter;
1015 
1016     memset(bitmap, 0, 32);
1017     delimiter = strpbrk(cmdline, ",-");
1018 
1019     do
1020     {
1021 	if (delimiter == NULL)
1022 	{
1023 	    delimchar = ',';
1024 	}
1025 	else
1026 	{
1027 	    delimchar = delimiter[0];
1028 	    delimiter[0] = '\0';
1029 	}
1030 	firstnum = atoi(cmdline);
1031 	if (delimiter != NULL) delimiter[0] = delimchar;
1032 
1033 	/* Found a comma -- mark the number preceding it as read */
1034 	if ((delimchar == ',') || (delimiter == NULL))
1035 	{
1036 	    set_in_bitmap(bitmap, firstnum);
1037 	}
1038 
1039 	/* Found a hyphen -- mark the range as read */
1040 	if (delimchar == '-')
1041 	{
1042 	    cmdline = delimiter+1;
1043 	    delimiter = strpbrk(cmdline, ",");
1044 
1045 	    if (delimiter != NULL)
1046 	    {
1047 		delimchar = delimiter[0];
1048 		delimiter[0] = '\0';
1049 	    }
1050 	    secondnum = atoi(cmdline);
1051 	    if (delimiter != NULL) delimiter[0] = delimchar;
1052 
1053 	    for (i=firstnum; i<=secondnum; i++)
1054 	    {
1055 		set_in_bitmap(bitmap, i);
1056 	    }
1057 	}
1058 	if (delimiter == NULL) finished = true;
1059 
1060 	cmdline = delimiter+1;
1061 	if (delimiter != NULL) delimiter = strpbrk(cmdline, ",-");
1062     } while (!finished);
1063 }
1064