PageRenderTime 108ms CodeModel.GetById 30ms app.highlight 55ms RepoModel.GetById 15ms app.codeStats 1ms

/client/pub_client.c

https://bitbucket.org/rgingras/mosquitto
C | 698 lines | 633 code | 35 blank | 30 comment | 174 complexity | 8a7782cc461da3fb75a3ec460e31cb8a MD5 | raw file
  1/*
  2Copyright (c) 2009-2012 Roger Light <roger@atchoo.org>
  3All rights reserved.
  4
  5Redistribution and use in source and binary forms, with or without
  6modification, are permitted provided that the following conditions are met:
  7
  81. Redistributions of source code must retain the above copyright notice,
  9   this list of conditions and the following disclaimer.
 102. Redistributions in binary form must reproduce the above copyright
 11   notice, this list of conditions and the following disclaimer in the
 12   documentation and/or other materials provided with the distribution.
 133. Neither the name of mosquitto nor the names of its
 14   contributors may be used to endorse or promote products derived from
 15   this software without specific prior written permission.
 16
 17THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 18AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 19IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 20ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 21LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 22CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 23SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 24INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 25CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 26ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 27POSSIBILITY OF SUCH DAMAGE.
 28*/
 29
 30
 31#include <errno.h>
 32#include <fcntl.h>
 33#include <stdio.h>
 34#include <stdlib.h>
 35#include <string.h>
 36#ifndef WIN32
 37#include <unistd.h>
 38#else
 39#include <process.h>
 40#include <winsock2.h>
 41#define snprintf sprintf_s
 42#endif
 43
 44#include <mosquitto.h>
 45
 46#define MSGMODE_NONE 0
 47#define MSGMODE_CMD 1
 48#define MSGMODE_STDIN_LINE 2
 49#define MSGMODE_STDIN_FILE 3
 50#define MSGMODE_FILE 4
 51#define MSGMODE_NULL 5
 52
 53#define STATUS_CONNECTING 0
 54#define STATUS_CONNACK_RECVD 1
 55#define STATUS_DISCONNECTING 2
 56
 57/* Global variables for use in callbacks. See sub_client.c for an example of
 58 * using a struct to hold variables for use in callbacks. */
 59static char *topic = NULL;
 60static char *message = NULL;
 61static long msglen = 0;
 62static int qos = 0;
 63static int retain = 0;
 64static int mode = MSGMODE_NONE;
 65static int status = STATUS_CONNECTING;
 66static int mid_sent = 0;
 67static bool connected = true;
 68static char *username = NULL;
 69static char *password = NULL;
 70static bool disconnect_sent = false;
 71static bool quiet = false;
 72
 73void my_connect_callback(struct mosquitto *mosq, void *obj, int result)
 74{
 75	int rc = MOSQ_ERR_SUCCESS;
 76
 77	if(!result){
 78		switch(mode){
 79			case MSGMODE_CMD:
 80			case MSGMODE_FILE:
 81			case MSGMODE_STDIN_FILE:
 82				rc = mosquitto_publish(mosq, &mid_sent, topic, msglen, message, qos, retain);
 83				break;
 84			case MSGMODE_NULL:
 85				rc = mosquitto_publish(mosq, &mid_sent, topic, 0, NULL, qos, retain);
 86				break;
 87			case MSGMODE_STDIN_LINE:
 88				status = STATUS_CONNACK_RECVD;
 89				break;
 90		}
 91		if(rc){
 92			if(!quiet){
 93				switch(rc){
 94					case MOSQ_ERR_INVAL:
 95						fprintf(stderr, "Error: Invalid input. Does your topic contain '+' or '#'?\n");
 96						break;
 97					case MOSQ_ERR_NOMEM:
 98						fprintf(stderr, "Error: Out of memory when trying to publish message.\n");
 99						break;
100					case MOSQ_ERR_NO_CONN:
101						fprintf(stderr, "Error: Client not connected when trying to publish.\n");
102						break;
103					case MOSQ_ERR_PROTOCOL:
104						fprintf(stderr, "Error: Protocol error when communicating with broker.\n");
105						break;
106					case MOSQ_ERR_PAYLOAD_SIZE:
107						fprintf(stderr, "Error: Message payload is too large.\n");
108						break;
109				}
110			}
111			mosquitto_disconnect(mosq);
112		}
113	}else{
114		if(result && !quiet){
115			fprintf(stderr, "%s\n", mosquitto_connack_string(result));
116		}
117	}
118}
119
120void my_disconnect_callback(struct mosquitto *mosq, void *obj, int rc)
121{
122	connected = false;
123}
124
125void my_publish_callback(struct mosquitto *mosq, void *obj, int mid)
126{
127	if(mode != MSGMODE_STDIN_LINE && disconnect_sent == false){
128		mosquitto_disconnect(mosq);
129		disconnect_sent = true;
130	}
131}
132
133void my_log_callback(struct mosquitto *mosq, void *obj, int level, const char *str)
134{
135	printf("%s\n", str);
136}
137
138int load_stdin(void)
139{
140	long pos = 0, rlen;
141	char buf[1024];
142
143	mode = MSGMODE_STDIN_FILE;
144
145	while(!feof(stdin)){
146		rlen = fread(buf, 1, 1024, stdin);
147		message = realloc(message, pos+rlen);
148		if(!message){
149			if(!quiet) fprintf(stderr, "Error: Out of memory.\n");
150			return 1;
151		}
152		memcpy(&(message[pos]), buf, rlen);
153		pos += rlen;
154	}
155	msglen = pos;
156
157	if(!msglen){
158		if(!quiet) fprintf(stderr, "Error: Zero length input.\n");
159		return 1;
160	}
161
162	return 0;
163}
164
165int load_file(const char *filename)
166{
167	long pos, rlen;
168	FILE *fptr = NULL;
169
170	fptr = fopen(filename, "rb");
171	if(!fptr){
172		if(!quiet) fprintf(stderr, "Error: Unable to open file \"%s\".\n", filename);
173		return 1;
174	}
175	mode = MSGMODE_FILE;
176	fseek(fptr, 0, SEEK_END);
177	msglen = ftell(fptr);
178	if(msglen > 268435455){
179		fclose(fptr);
180		if(!quiet) fprintf(stderr, "Error: File \"%s\" is too large (>268,435,455 bytes).\n", filename);
181		return 1;
182	}
183	if(msglen == 0){
184		fclose(fptr);
185		if(!quiet) fprintf(stderr, "Error: File \"%s\" is empty.\n", filename);
186		return 1;
187	}
188	fseek(fptr, 0, SEEK_SET);
189	message = malloc(msglen);
190	if(!message){
191		fclose(fptr);
192		if(!quiet) fprintf(stderr, "Error: Out of memory.\n");
193		return 1;
194	}
195	pos = 0;
196	while(pos < msglen){
197		rlen = fread(&(message[pos]), sizeof(char), msglen-pos, fptr);
198		pos += rlen;
199	}
200	fclose(fptr);
201	return 0;
202}
203
204void print_usage(void)
205{
206	printf("mosquitto_pub is a simple mqtt client that will publish a message on a single topic and exit.\n\n");
207	printf("Usage: mosquitto_pub [-h host] [-p port] [-q qos] [-r] {-f file | -l | -n | -m message} -t topic\n");
208	printf("                     [-i id] [-I id_prefix]\n");
209	printf("                     [-d] [--quiet]\n");
210	printf("                     [-u username [-P password]]\n");
211	printf("                     [--will-topic [--will-payload payload] [--will-qos qos] [--will-retain]]\n");
212#ifdef WITH_TLS
213	printf("                     [{--cafile file | --capath dir} [--cert file] [--key file]]\n");
214#ifdef WITH_TLS_PSK
215	printf("                     [--psk hex-key --psk-identity identity]\n");
216#endif
217#endif
218	printf("       mosquitto_pub --help\n\n");
219	printf(" -d : enable debug messages.\n");
220	printf(" -f : send the contents of a file as the message.\n");
221	printf(" -h : mqtt host to connect to. Defaults to localhost.\n");
222	printf(" -i : id to use for this client. Defaults to mosquitto_pub_ appended with the process id.\n");
223	printf(" -I : define the client id as id_prefix appended with the process id. Useful for when the\n");
224	printf("      broker is using the clientid_prefixes option.\n");
225	printf(" -l : read messages from stdin, sending a separate message for each line.\n");
226	printf(" -m : message payload to send.\n");
227	printf(" -n : send a null (zero length) message.\n");
228	printf(" -p : network port to connect to. Defaults to 1883.\n");
229	printf(" -q : quality of service level to use for all messages. Defaults to 0.\n");
230	printf(" -r : message should be retained.\n");
231	printf(" -s : read message from stdin, sending the entire input as a message.\n");
232	printf(" -t : mqtt topic to publish to.\n");
233	printf(" -u : provide a username (requires MQTT 3.1 broker)\n");
234	printf(" -P : provide a password (requires MQTT 3.1 broker)\n");
235	printf(" --help : display this message.\n");
236	printf(" --quiet : don't print error messages.\n");
237	printf(" --will-payload : payload for the client Will, which is sent by the broker in case of\n");
238	printf("                  unexpected disconnection. If not given and will-topic is set, a zero\n");
239	printf("                  length message will be sent.\n");
240	printf(" --will-qos : QoS level for the client Will.\n");
241	printf(" --will-retain : if given, make the client Will retained.\n");
242	printf(" --will-topic : the topic on which to publish the client Will.\n");
243#ifdef WITH_TLS
244	printf(" --cafile : path to a file containing trusted CA certificates to enable encrypted\n");
245	printf("            communication.\n");
246	printf(" --capath : path to a directory containing trusted CA certificates to enable encrypted\n");
247	printf("            communication.\n");
248	printf(" --cert : client certificate for authentication, if required by server.\n");
249	printf(" --key : client private key for authentication, if required by server.\n");
250#ifdef WITH_TLS_PSK
251	printf(" --psk : pre-shared-key in hexadecimal (no leading 0x) to enable TLS-PSK mode.\n");
252	printf(" --psk-identity : client identity string for TLS-PSK mode.\n");
253#endif
254#endif
255	printf("\nSee http://mosquitto.org/ for more information.\n\n");
256}
257
258int main(int argc, char *argv[])
259{
260	char *id = NULL;
261	char *id_prefix = NULL;
262	int i;
263	char *host = "localhost";
264	int port = 1883;
265	int keepalive = 60;
266	char buf[1024];
267	bool debug = false;
268	struct mosquitto *mosq = NULL;
269	int rc;
270	int rc2;
271	char hostname[256];
272	char err[1024];
273	int len;
274
275	char *will_payload = NULL;
276	long will_payloadlen = 0;
277	int will_qos = 0;
278	bool will_retain = false;
279	char *will_topic = NULL;
280
281	char *cafile = NULL;
282	char *capath = NULL;
283	char *certfile = NULL;
284	char *keyfile = NULL;
285
286	char *psk = NULL;
287	char *psk_identity = NULL;
288
289	for(i=1; i<argc; i++){
290		if(!strcmp(argv[i], "-p") || !strcmp(argv[i], "--port")){
291			if(i==argc-1){
292				fprintf(stderr, "Error: -p argument given but no port specified.\n\n");
293				print_usage();
294				return 1;
295			}else{
296				port = atoi(argv[i+1]);
297				if(port<1 || port>65535){
298					fprintf(stderr, "Error: Invalid port given: %d\n", port);
299					print_usage();
300					return 1;
301				}
302			}
303			i++;
304		}else if(!strcmp(argv[i], "--cafile")){
305			if(i==argc-1){
306				fprintf(stderr, "Error: --cafile argument given but no file specified.\n\n");
307				print_usage();
308				return 1;
309			}else{
310				cafile = argv[i+1];
311			}
312			i++;
313		}else if(!strcmp(argv[i], "--capath")){
314			if(i==argc-1){
315				fprintf(stderr, "Error: --capath argument given but no directory specified.\n\n");
316				print_usage();
317				return 1;
318			}else{
319				capath = argv[i+1];
320			}
321			i++;
322		}else if(!strcmp(argv[i], "--cert")){
323			if(i==argc-1){
324				fprintf(stderr, "Error: --cert argument given but no file specified.\n\n");
325				print_usage();
326				return 1;
327			}else{
328				certfile = argv[i+1];
329			}
330			i++;
331		}else if(!strcmp(argv[i], "-d") || !strcmp(argv[i], "--debug")){
332			debug = true;
333		}else if(!strcmp(argv[i], "-f") || !strcmp(argv[i], "--file")){
334			if(mode != MSGMODE_NONE){
335				fprintf(stderr, "Error: Only one type of message can be sent at once.\n\n");
336				print_usage();
337				return 1;
338			}else if(i==argc-1){
339				fprintf(stderr, "Error: -f argument given but no file specified.\n\n");
340				print_usage();
341				return 1;
342			}else{
343				if(load_file(argv[i+1])) return 1;
344			}
345			i++;
346		}else if(!strcmp(argv[i], "--help")){
347			print_usage();
348			return 0;
349		}else if(!strcmp(argv[i], "-h") || !strcmp(argv[i], "--host")){
350			if(i==argc-1){
351				fprintf(stderr, "Error: -h argument given but no host specified.\n\n");
352				print_usage();
353				return 1;
354			}else{
355				host = argv[i+1];
356			}
357			i++;
358		}else if(!strcmp(argv[i], "-i") || !strcmp(argv[i], "--id")){
359			if(id_prefix){
360				fprintf(stderr, "Error: -i and -I argument cannot be used together.\n\n");
361				print_usage();
362				return 1;
363			}
364			if(i==argc-1){
365				fprintf(stderr, "Error: -i argument given but no id specified.\n\n");
366				print_usage();
367				return 1;
368			}else{
369				id = argv[i+1];
370			}
371			i++;
372		}else if(!strcmp(argv[i], "-I") || !strcmp(argv[i], "--id-prefix")){
373			if(id){
374				fprintf(stderr, "Error: -i and -I argument cannot be used together.\n\n");
375				print_usage();
376				return 1;
377			}
378			if(i==argc-1){
379				fprintf(stderr, "Error: -I argument given but no id prefix specified.\n\n");
380				print_usage();
381				return 1;
382			}else{
383				id_prefix = argv[i+1];
384			}
385			i++;
386		}else if(!strcmp(argv[i], "--key")){
387			if(i==argc-1){
388				fprintf(stderr, "Error: --key argument given but no file specified.\n\n");
389				print_usage();
390				return 1;
391			}else{
392				keyfile = argv[i+1];
393			}
394			i++;
395		}else if(!strcmp(argv[i], "-l") || !strcmp(argv[i], "--stdin-line")){
396			if(mode != MSGMODE_NONE){
397				fprintf(stderr, "Error: Only one type of message can be sent at once.\n\n");
398				print_usage();
399				return 1;
400			}else{
401				mode = MSGMODE_STDIN_LINE;
402			}
403		}else if(!strcmp(argv[i], "-m") || !strcmp(argv[i], "--message")){
404			if(mode != MSGMODE_NONE){
405				fprintf(stderr, "Error: Only one type of message can be sent at once.\n\n");
406				print_usage();
407				return 1;
408			}else if(i==argc-1){
409				fprintf(stderr, "Error: -m argument given but no message specified.\n\n");
410				print_usage();
411				return 1;
412			}else{
413				message = argv[i+1];
414				msglen = strlen(message);
415				mode = MSGMODE_CMD;
416			}
417			i++;
418		}else if(!strcmp(argv[i], "-n") || !strcmp(argv[i], "--null-message")){
419			if(mode != MSGMODE_NONE){
420				fprintf(stderr, "Error: Only one type of message can be sent at once.\n\n");
421				print_usage();
422				return 1;
423			}else{
424				mode = MSGMODE_NULL;
425			}
426		}else if(!strcmp(argv[i], "--psk")){
427			if(i==argc-1){
428				fprintf(stderr, "Error: --psk argument given but no key specified.\n\n");
429				print_usage();
430				return 1;
431			}else{
432				psk = argv[i+1];
433			}
434			i++;
435		}else if(!strcmp(argv[i], "--psk-identity")){
436			if(i==argc-1){
437				fprintf(stderr, "Error: --psk-identity argument given but no identity specified.\n\n");
438				print_usage();
439				return 1;
440			}else{
441				psk_identity = argv[i+1];
442			}
443			i++;
444		}else if(!strcmp(argv[i], "-q") || !strcmp(argv[i], "--qos")){
445			if(i==argc-1){
446				fprintf(stderr, "Error: -q argument given but no QoS specified.\n\n");
447				print_usage();
448				return 1;
449			}else{
450				qos = atoi(argv[i+1]);
451				if(qos<0 || qos>2){
452					fprintf(stderr, "Error: Invalid QoS given: %d\n", qos);
453					print_usage();
454					return 1;
455				}
456			}
457			i++;
458		}else if(!strcmp(argv[i], "--quiet")){
459			quiet = true;
460		}else if(!strcmp(argv[i], "-r") || !strcmp(argv[i], "--retain")){
461			retain = 1;
462		}else if(!strcmp(argv[i], "-s") || !strcmp(argv[i], "--stdin-file")){
463			if(mode != MSGMODE_NONE){
464				fprintf(stderr, "Error: Only one type of message can be sent at once.\n\n");
465				print_usage();
466				return 1;
467			}else{
468				if(load_stdin()) return 1;
469			}
470		}else if(!strcmp(argv[i], "-t") || !strcmp(argv[i], "--topic")){
471			if(i==argc-1){
472				fprintf(stderr, "Error: -t argument given but no topic specified.\n\n");
473				print_usage();
474				return 1;
475			}else{
476				topic = argv[i+1];
477			}
478			i++;
479		}else if(!strcmp(argv[i], "-u") || !strcmp(argv[i], "--username")){
480			if(i==argc-1){
481				fprintf(stderr, "Error: -u argument given but no username specified.\n\n");
482				print_usage();
483				return 1;
484			}else{
485				username = argv[i+1];
486			}
487			i++;
488		}else if(!strcmp(argv[i], "-P") || !strcmp(argv[i], "--pw")){
489			if(i==argc-1){
490				fprintf(stderr, "Error: -P argument given but no password specified.\n\n");
491				print_usage();
492				return 1;
493			}else{
494				password = argv[i+1];
495			}
496			i++;
497		}else if(!strcmp(argv[i], "--will-payload")){
498			if(i==argc-1){
499				fprintf(stderr, "Error: --will-payload argument given but no will payload specified.\n\n");
500				print_usage();
501				return 1;
502			}else{
503				will_payload = argv[i+1];
504				will_payloadlen = strlen(will_payload);
505			}
506			i++;
507		}else if(!strcmp(argv[i], "--will-qos")){
508			if(i==argc-1){
509				fprintf(stderr, "Error: --will-qos argument given but no will QoS specified.\n\n");
510				print_usage();
511				return 1;
512			}else{
513				will_qos = atoi(argv[i+1]);
514				if(will_qos < 0 || will_qos > 2){
515					fprintf(stderr, "Error: Invalid will QoS %d.\n\n", will_qos);
516					return 1;
517				}
518			}
519			i++;
520		}else if(!strcmp(argv[i], "--will-retain")){
521			will_retain = true;
522		}else if(!strcmp(argv[i], "--will-topic")){
523			if(i==argc-1){
524				fprintf(stderr, "Error: --will-topic argument given but no will topic specified.\n\n");
525				print_usage();
526				return 1;
527			}else{
528				will_topic = argv[i+1];
529			}
530			i++;
531		}else{
532			fprintf(stderr, "Error: Unknown option '%s'.\n",argv[i]);
533			print_usage();
534			return 1;
535		}
536	}
537
538	if(!topic || mode == MSGMODE_NONE){
539		fprintf(stderr, "Error: Both topic and message must be supplied.\n");
540		print_usage();
541		return 1;
542	}
543
544	if(will_payload && !will_topic){
545		fprintf(stderr, "Error: Will payload given, but no will topic given.\n");
546		print_usage();
547		return 1;
548	}
549	if(will_retain && !will_topic){
550		fprintf(stderr, "Error: Will retain given, but no will topic given.\n");
551		print_usage();
552		return 1;
553	}
554	if(password && !username){
555		if(!quiet) fprintf(stderr, "Warning: Not using password since username not set.\n");
556	}
557	if((certfile && !keyfile) || (keyfile && !certfile)){
558		fprintf(stderr, "Error: Both certfile and keyfile must be provided if one of them is.\n");
559		print_usage();
560		return 1;
561	}
562	if((cafile || capath) && psk){
563		if(!quiet) fprintf(stderr, "Error: Only one of --psk or --cafile/--capath may be used at once.\n");
564		return 1;
565	}
566	if(psk && !psk_identity){
567		if(!quiet) fprintf(stderr, "Error: --psk-identity required if --psk used.\n");
568		return 1;
569	}
570
571	mosquitto_lib_init();
572
573	if(id_prefix){
574		id = malloc(strlen(id_prefix)+10);
575		if(!id){
576			if(!quiet) fprintf(stderr, "Error: Out of memory.\n");
577			mosquitto_lib_cleanup();
578			return 1;
579		}
580		snprintf(id, strlen(id_prefix)+10, "%s%d", id_prefix, getpid());
581	}else if(!id){
582		hostname[0] = '\0';
583		gethostname(hostname, 256);
584		hostname[255] = '\0';
585		len = strlen("mosqpub/-") + 6 + strlen(hostname);
586		id = malloc(len);
587		if(!id){
588			if(!quiet) fprintf(stderr, "Error: Out of memory.\n");
589			mosquitto_lib_cleanup();
590			return 1;
591		}
592		snprintf(id, len, "mosqpub/%d-%s", getpid(), hostname);
593		id[MOSQ_MQTT_ID_MAX_LENGTH] = '\0';
594	}
595
596	mosq = mosquitto_new(id, true, NULL);
597	if(!mosq){
598		switch(errno){
599			case ENOMEM:
600				if(!quiet) fprintf(stderr, "Error: Out of memory.\n");
601				break;
602			case EINVAL:
603				if(!quiet) fprintf(stderr, "Error: Invalid id.\n");
604				break;
605		}
606		mosquitto_lib_cleanup();
607		return 1;
608	}
609	if(debug){
610		mosquitto_log_callback_set(mosq, my_log_callback);
611	}
612	if(will_topic && mosquitto_will_set(mosq, will_topic, will_payloadlen, will_payload, will_qos, will_retain)){
613		if(!quiet) fprintf(stderr, "Error: Problem setting will.\n");
614		mosquitto_lib_cleanup();
615		return 1;
616	}
617	if(username && mosquitto_username_pw_set(mosq, username, password)){
618		if(!quiet) fprintf(stderr, "Error: Problem setting username and password.\n");
619		mosquitto_lib_cleanup();
620		return 1;
621	}
622	if((cafile || capath) && mosquitto_tls_set(mosq, cafile, capath, certfile, keyfile, NULL)){
623		if(!quiet) fprintf(stderr, "Error: Problem setting TLS options.\n");
624		mosquitto_lib_cleanup();
625		return 1;
626	}
627	if(psk && mosquitto_tls_psk_set(mosq, psk, psk_identity, NULL)){
628		if(!quiet) fprintf(stderr, "Error: Problem setting TLS-PSK options.\n");
629		mosquitto_lib_cleanup();
630		return 1;
631	}
632	mosquitto_connect_callback_set(mosq, my_connect_callback);
633	mosquitto_disconnect_callback_set(mosq, my_disconnect_callback);
634	mosquitto_publish_callback_set(mosq, my_publish_callback);
635
636	rc = mosquitto_connect(mosq, host, port, keepalive);
637	if(rc){
638		if(!quiet){
639			if(rc == MOSQ_ERR_ERRNO){
640#ifndef WIN32
641				strerror_r(errno, err, 1024);
642#else
643				FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, errno, 0, (LPTSTR)&err, 1024, NULL);
644#endif
645				fprintf(stderr, "Error: %s\n", err);
646			}else{
647				fprintf(stderr, "Unable to connect (%d).\n", rc);
648			}
649		}
650		mosquitto_lib_cleanup();
651		return rc;
652	}
653
654	if(mode == MSGMODE_STDIN_LINE){
655		mosquitto_loop_start(mosq);
656	}
657
658	do{
659		if(mode == MSGMODE_STDIN_LINE){
660			if(status == STATUS_CONNACK_RECVD){
661				if(fgets(buf, 1024, stdin)){
662					buf[strlen(buf)-1] = '\0';
663					rc2 = mosquitto_publish(mosq, &mid_sent, topic, strlen(buf), buf, qos, retain);
664					if(rc2){
665						if(!quiet) fprintf(stderr, "Error: Publish returned %d, disconnecting.\n", rc2);
666						mosquitto_disconnect(mosq);
667					}
668				}else if(feof(stdin) && disconnect_sent == false){
669					mosquitto_disconnect(mosq);
670					disconnect_sent = true;
671					status = STATUS_DISCONNECTING;
672				}
673			}
674			rc = MOSQ_ERR_SUCCESS;
675		}else{
676			rc = mosquitto_loop(mosq, -1, 1);
677		}
678	}while(rc == MOSQ_ERR_SUCCESS && connected);
679
680	if(mode == MSGMODE_STDIN_LINE){
681		mosquitto_loop_stop(mosq, false);
682	}
683
684	if(message && mode == MSGMODE_FILE){
685		free(message);
686	}
687	mosquitto_destroy(mosq);
688	mosquitto_lib_cleanup();
689
690	if(rc){
691		if(rc == MOSQ_ERR_ERRNO){
692			fprintf(stderr, "Error: %s\n", strerror(errno));
693		}else{
694			fprintf(stderr, "Error: %s\n", mosquitto_strerror(rc));
695		}
696	}
697	return rc;
698}