multipathd: set return code for multipathd commands
[multipath-tools/.git] / multipathd / uxclnt.c
1 /*
2  * Original author : tridge@samba.org, January 2002
3  *
4  * Copyright (c) 2005 Christophe Varoqui
5  * Copyright (c) 2005 Benjamin Marzinski, Redhat
6  */
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <unistd.h>
10 #include <stdarg.h>
11 #include <fcntl.h>
12 #include <errno.h>
13 #include <sys/ioctl.h>
14 #include <sys/types.h>
15 #include <sys/socket.h>
16 #include <sys/un.h>
17 #include <poll.h>
18 #include <readline/readline.h>
19 #include <readline/history.h>
20
21 #include "mpath_cmd.h"
22 #include "uxsock.h"
23 #include "memory.h"
24 #include "defaults.h"
25
26 #include "vector.h"
27 #include "cli.h"
28 #include "uxclnt.h"
29
30 static void print_reply(char *s)
31 {
32         if (!s)
33                 return;
34
35         if (isatty(1)) {
36                 printf("%s", s);
37                 return;
38         }
39         /* strip ANSI color markers */
40         while (*s != '\0') {
41                 if ((*s == 0x1b) && (*(s+1) == '['))
42                         while ((*s++ != 'm') && (*s != '\0')) {};
43                 putchar(*s++);
44         }
45 }
46
47 static int need_quit(char *str, size_t len)
48 {
49         char *ptr, *start;
50         size_t trimed_len = len;
51
52         for (ptr = str; trimed_len && isspace(*ptr);
53              trimed_len--, ptr++)
54                 ;
55
56         start = ptr;
57
58         for (ptr = str + len - 1; trimed_len && isspace(*ptr);
59              trimed_len--, ptr--)
60                 ;
61
62         if ((trimed_len == 4 && !strncmp(start, "exit", 4)) ||
63             (trimed_len == 4 && !strncmp(start, "quit", 4)))
64                 return 1;
65
66         return 0;
67 }
68
69 /*
70  * process the client
71  */
72 static void process(int fd, unsigned int timeout)
73 {
74         char *line;
75         char *reply;
76         int ret;
77
78         cli_init();
79         rl_readline_name = "multipathd";
80         rl_completion_entry_function = key_generator;
81         while ((line = readline("multipathd> "))) {
82                 size_t llen = strlen(line);
83
84                 if (!llen) {
85                         free(line);
86                         continue;
87                 }
88
89                 if (need_quit(line, llen))
90                         break;
91
92                 if (send_packet(fd, line) != 0) break;
93                 ret = recv_packet(fd, &reply, timeout);
94                 if (ret != 0) break;
95
96                 print_reply(reply);
97
98                 if (line && *line)
99                         add_history(line);
100
101                 free(line);
102                 FREE(reply);
103         }
104 }
105
106 static int process_req(int fd, char * inbuf, unsigned int timeout)
107 {
108         char *reply;
109         int ret;
110
111         if (send_packet(fd, inbuf) != 0) {
112                 printf("cannot send packet\n");
113                 return 1;
114         }
115         ret = recv_packet(fd, &reply, timeout);
116         if (ret < 0) {
117                 if (ret == -ETIMEDOUT)
118                         printf("timeout receiving packet\n");
119                 else
120                         printf("error %d receiving packet\n", ret);
121                 return 1;
122         } else {
123                 printf("%s", reply);
124                 ret = (strcmp(reply, "fail\n") == 0);
125                 FREE(reply);
126                 return ret;
127         }
128 }
129
130 /*
131  * entry point
132  */
133 int uxclnt(char * inbuf, unsigned int timeout)
134 {
135         int fd, ret = 0;
136
137         fd = mpath_connect();
138         if (fd == -1)
139                 exit(1);
140
141         if (inbuf)
142                 ret = process_req(fd, inbuf, timeout);
143         else
144                 process(fd, timeout);
145         mpath_disconnect(fd);
146         return ret;
147 }