Mostly minor fixes up until version 0.8.10.
[irreco.git] / lirc-0.8.4a / tools / irsend.c
blob3c3b772db82afd600bb52e32784a5a301ef49d23
1 /* $Id: irsend.c,v 5.5 2007/09/29 17:13:14 lirc Exp $ */
3 /*
5 irsend - application for sending IR-codes via lirc
7 Copyright (C) 1998 Christoph Bartelmus (lirc@bartelmus.de)
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 #ifdef HAVE_CONFIG_H
26 # include "config.h"
27 #endif
29 #include <netdb.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <unistd.h>
34 #include <fcntl.h>
35 #include <getopt.h>
36 #include <sys/socket.h>
37 #include <sys/types.h>
38 #include <sys/stat.h>
39 #include <sys/un.h>
40 #include <errno.h>
41 #include <signal.h>
42 #include <limits.h>
44 #define PACKET_SIZE 256
45 /* three seconds */
46 #define TIMEOUT 3
48 int timeout=0;
49 char *progname;
51 void sigalrm(int sig)
53 timeout=1;
56 const char *read_string(int fd)
58 static char buffer[PACKET_SIZE+1]="";
59 char *end;
60 static int ptr=0;
61 ssize_t ret;
63 if(ptr>0)
65 memmove(buffer,buffer+ptr,strlen(buffer+ptr)+1);
66 ptr=strlen(buffer);
67 end=strchr(buffer,'\n');
69 else
71 end=NULL;
73 alarm(TIMEOUT);
74 while(end==NULL)
76 if(PACKET_SIZE<=ptr)
78 fprintf(stderr,"%s: bad packet\n",progname);
79 ptr=0;
80 return(NULL);
82 ret=read(fd,buffer+ptr,PACKET_SIZE-ptr);
84 if(ret<=0 || timeout)
86 if(timeout)
88 fprintf(stderr,"%s: timeout\n",progname);
90 else
92 alarm(0);
94 ptr=0;
95 return(NULL);
97 buffer[ptr+ret]=0;
98 ptr=strlen(buffer);
99 end=strchr(buffer,'\n');
101 alarm(0);timeout=0;
103 end[0]=0;
104 ptr=strlen(buffer)+1;
105 # ifdef DEBUG
106 printf("buffer: -%s-\n",buffer);
107 # endif
108 return(buffer);
111 enum packet_state
113 P_BEGIN,
114 P_MESSAGE,
115 P_STATUS,
116 P_DATA,
117 P_N,
118 P_DATA_N,
119 P_END
122 int send_packet(int fd,const char *packet)
124 int done,todo;
125 const char *string,*data;
126 char *endptr;
127 enum packet_state state;
128 int status,n;
129 unsigned long data_n=0;
131 todo=strlen(packet);
132 data=packet;
133 while(todo>0)
135 done=write(fd,(void *) data,todo);
136 if(done<0)
138 fprintf(stderr,"%s: could not send packet\n",
139 progname);
140 perror(progname);
141 return(-1);
143 data+=done;
144 todo-=done;
147 /* get response */
148 status=0;
149 state=P_BEGIN;
150 n=0;
151 while(1)
153 string=read_string(fd);
154 if(string==NULL) return(-1);
155 switch(state)
157 case P_BEGIN:
158 if(strcasecmp(string,"BEGIN")!=0)
160 continue;
162 state=P_MESSAGE;
163 break;
164 case P_MESSAGE:
165 if(strncasecmp(string,packet,strlen(string))!=0 ||
166 strlen(string)+1!=strlen(packet))
168 state=P_BEGIN;
169 continue;
171 state=P_STATUS;
172 break;
173 case P_STATUS:
174 if(strcasecmp(string,"SUCCESS")==0)
176 status=0;
178 else if(strcasecmp(string,"END")==0)
180 status=0;
181 return(status);
183 else if(strcasecmp(string,"ERROR")==0)
185 fprintf(stderr,"%s: command failed: %s",
186 progname,packet);
187 status=-1;
189 else
191 goto bad_packet;
193 state=P_DATA;
194 break;
195 case P_DATA:
196 if(strcasecmp(string,"END")==0)
198 return(status);
200 else if(strcasecmp(string,"DATA")==0)
202 state=P_N;
203 break;
205 goto bad_packet;
206 case P_N:
207 errno=0;
208 data_n=strtoul(string,&endptr,0);
209 if(!*string || *endptr)
211 goto bad_packet;
213 if(data_n==0)
215 state=P_END;
217 else
219 state=P_DATA_N;
221 break;
222 case P_DATA_N:
223 fprintf(stderr,"%s: %s\n",progname,string);
224 n++;
225 if(n==data_n) state=P_END;
226 break;
227 case P_END:
228 if(strcasecmp(string,"END")==0)
230 return(status);
232 goto bad_packet;
233 break;
236 bad_packet:
237 fprintf(stderr,"%s: bad return packet\n",progname);
238 return(-1);
241 int main(int argc,char **argv)
243 char *directive;
244 char *remote;
245 char *code;
246 char *lircd=NULL;
247 char *address=NULL;
248 unsigned short port = LIRC_INET_PORT;
249 unsigned long count=1;
250 struct sockaddr_un addr_un;
251 struct sockaddr_in addr_in;
252 int fd;
253 char buffer[PACKET_SIZE+1];
254 struct sigaction act;
256 progname = "irsend";
258 while(1)
260 int c;
261 static struct option long_options[] =
263 {"help",no_argument,NULL,'h'},
264 {"version",no_argument,NULL,'v'},
265 {"device",required_argument,NULL,'d'},
266 {"address",required_argument,NULL,'a'},
267 {"count",required_argument,NULL,'#'},
268 {0, 0, 0, 0}
270 c = getopt_long(argc,argv,"hvd:a:#:",long_options,NULL);
271 if(c==-1)
272 break;
273 switch (c)
275 case 'h':
276 printf("Usage: %s [options] DIRECTIVE REMOTE CODE [CODE...]\n",progname);
277 printf("\t -h --help\t\t\tdisplay usage summary\n");
278 printf("\t -v --version\t\t\tdisplay version\n");
279 printf("\t -d --device\t\t\tuse given lircd socket [%s]\n", LIRCD);
280 printf("\t -a --address=host[:port]\tconnect to "
281 "lircd at this address\n");
282 printf("\t -# --count=n\t\t\tsend command n times\n");
283 return(EXIT_SUCCESS);
284 case 'v':
285 printf("%s %s\n", progname, VERSION);
286 return(EXIT_SUCCESS);
287 case 'd':
288 lircd = optarg;
289 break;
290 case 'a':
292 char *p;
293 char *end;
294 unsigned long val;
296 address = strdup(optarg);
297 if(!address)
299 fprintf(stderr, "%s: out of memory\n",
300 progname);
301 return(EXIT_FAILURE);
303 p = strchr(address, ':');
304 if(p != NULL)
306 val = strtoul(p+1, &end, 10);
307 if (!(*(p+1)) || *end ||
308 val<1 || val>USHRT_MAX)
310 fprintf(stderr,
311 "%s: invalid port number: "
312 "%s\n", progname, p+1);
313 return(EXIT_FAILURE);
315 port = (unsigned short) val;
316 *p = 0;
318 break;
320 case '#':
322 char *end;
324 count = strtoul(optarg, &end, 10);
325 if(!*optarg || *end)
327 fprintf(stderr, "%s: invalid count value: "
328 "%s\n", progname, optarg);
329 return(EXIT_FAILURE);
331 break;
333 default:
334 return(EXIT_FAILURE);
337 if (optind + 2 > argc)
339 fprintf(stderr,"%s: not enough arguments\n",progname);
340 return(EXIT_FAILURE);
343 if(lircd==NULL)
345 lircd=LIRCD;
347 else
349 if(strlen(lircd)+1 > sizeof(addr_un.sun_path))
351 /* lircd is longer than sockaddr_un.sun_path field */
352 fprintf(stderr, "%s: socket name is too long\n",
353 progname);
354 return(EXIT_FAILURE);
358 act.sa_handler=sigalrm;
359 sigemptyset(&act.sa_mask);
360 act.sa_flags=0; /* we need EINTR */
361 sigaction(SIGALRM,&act,NULL);
363 if (address == NULL) {
364 addr_un.sun_family=AF_UNIX;
365 strcpy(addr_un.sun_path,lircd);
366 fd=socket(AF_UNIX,SOCK_STREAM,0);
368 else
370 struct hostent *hostInfo;
372 hostInfo = gethostbyname(address);
373 if (hostInfo == NULL) {
374 fprintf(stderr,"%s: host %s unknown\n", progname,
375 address);
376 return(EXIT_FAILURE);
378 addr_in.sin_family = hostInfo->h_addrtype;
379 memcpy((char *) &addr_in.sin_addr.s_addr,
380 hostInfo->h_addr_list[0], hostInfo->h_length);
381 addr_in.sin_port = htons(port);
382 fd=socket(AF_INET,SOCK_STREAM,0);
385 if(fd==-1)
387 fprintf(stderr,"%s: could not open socket\n",progname);
388 perror(progname);
389 exit(EXIT_FAILURE);
392 if(connect(fd,
393 address ? (struct sockaddr *) &addr_in :
394 (struct sockaddr *) &addr_un,
395 address ? sizeof(addr_in) : sizeof(addr_un)) == -1)
397 fprintf(stderr,"%s: could not connect to socket\n",progname);
398 perror(progname);
399 exit(EXIT_FAILURE);
402 if(address) free(address);
403 address = NULL;
405 directive=argv[optind++];
407 if(strcasecmp(directive,"set_transmitters")==0)
409 code=argv[optind++];
410 if (strlen(directive)+strlen(code)+2<PACKET_SIZE)
412 sprintf(buffer,"%s %s",directive,code);
414 else
416 fprintf(stderr,"%s: input too long\n",progname);
417 exit(EXIT_FAILURE);
419 while(optind<argc)
421 code=argv[optind++];
422 if (strlen(buffer)+strlen(code)+2<PACKET_SIZE)
424 sprintf(buffer+strlen(buffer)," %s",code);
426 else
428 fprintf(stderr,"%s: input too long\n",progname);
429 exit(EXIT_FAILURE);
432 strcat(buffer,"\n");
433 if(send_packet(fd,buffer)==-1)
435 exit(EXIT_FAILURE);
438 if(strcasecmp(directive,"simulate")==0)
440 code=argv[optind++];
441 if(optind != argc)
443 fprintf(stderr, "%s: invalid argument count\n",
444 progname);
445 exit(EXIT_FAILURE);
447 if(strlen(directive)+strlen(code)+2<PACKET_SIZE)
449 sprintf(buffer,"%s %s\n",directive,code);
451 else
453 fprintf(stderr,"%s: input too long\n",progname);
454 exit(EXIT_FAILURE);
456 if(send_packet(fd,buffer)==-1)
458 exit(EXIT_FAILURE);
461 else
463 remote=argv[optind++];
465 if (optind==argc)
467 fprintf(stderr,"%s: not enough arguments\n",progname);
468 exit(EXIT_FAILURE);
470 while(optind<argc)
472 code=argv[optind++];
474 if(strlen(directive)+strlen(remote)+strlen(code)+3<PACKET_SIZE)
476 if(strcasecmp(directive,"SEND_ONCE")==0 && count>1)
478 sprintf(buffer,"%s %s %s %lu\n",
479 directive,remote,code,count);
481 else
483 sprintf(buffer,"%s %s %s\n",directive,remote,code);
485 if(send_packet(fd,buffer)==-1)
487 exit(EXIT_FAILURE);
490 else
492 fprintf(stderr,"%s: input too long\n",progname);
493 exit(EXIT_FAILURE);
497 close(fd);
498 return(EXIT_SUCCESS);