|
1 // Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca> |
|
2 // |
|
3 // This program is free software; you can redistribute it and/or modify |
|
4 // it under the terms of the GNU General Public License as published by |
|
5 // the Free Software Foundation; either version 2 of the License, or |
|
6 // (at your option) any later version. |
|
7 // |
|
8 // This program is distributed in the hope that it will be useful, |
|
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
11 // GNU General Public License for more details. |
|
12 // |
|
13 // You should have received a copy of the GNU General Public License |
|
14 // along with this program; if not, write to the Free Software |
|
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|
16 |
|
17 #include <config.h> |
|
18 #include "server.h" |
|
19 #include <stdlib.h> |
|
20 #include <unistd.h> |
|
21 #include "un.h" |
|
22 #include "debug.h" |
|
23 |
|
24 server_call::~server_call() |
|
25 { |
|
26 trace("server_call::~server_call"); |
|
27 disconnect(); |
|
28 delete[] args; |
|
29 } |
|
30 |
|
31 static unsigned char* encode_string(unsigned char* ptr, mystring str) |
|
32 { |
|
33 unsigned length = str.length(); |
|
34 *ptr++ = length >> 8; |
|
35 *ptr++ = length & 0xff; |
|
36 memcpy(ptr, str.c_str(), length); |
|
37 return ptr+length; |
|
38 } |
|
39 |
|
40 mystring server_call::build_msg() const |
|
41 { |
|
42 if(argc >= 1<<8) |
|
43 return ""; |
|
44 unsigned msglen = 3 + cmd.length(); |
|
45 for(unsigned i = 0; i < argc; i++) { |
|
46 if(args[i].length() >= 1<<16) |
|
47 return ""; |
|
48 msglen += 2 + args[i].length(); |
|
49 } |
|
50 char buf[msglen+3]; |
|
51 unsigned char* ptr = (unsigned char*)buf; |
|
52 *ptr++ = 2; // protocol ID |
|
53 *ptr++ = msglen >> 8; |
|
54 *ptr++ = msglen & 0xff; |
|
55 *ptr++ = argc; |
|
56 ptr = encode_string(ptr, cmd); |
|
57 for(unsigned i = 0; i < argc; i++) |
|
58 ptr = encode_string(ptr, args[i]); |
|
59 return mystring(buf, msglen+3); |
|
60 } |
|
61 |
|
62 static bool send(int fd, mystring msg) |
|
63 { |
|
64 ssize_t written = 0; |
|
65 while(written < (ssize_t)msg.length()) { |
|
66 ssize_t w = write(fd, msg.c_str()+written, msg.length()-written); |
|
67 if(w == 0 || w == -1) |
|
68 break; |
|
69 written += w; |
|
70 } |
|
71 return written == (ssize_t)msg.length(); |
|
72 } |
|
73 |
|
74 int server_call::connect(const mystring& socket_file) const |
|
75 { |
|
76 int s = ::socket(AF_UNIX, SOCK_STREAM, 0); |
|
77 if(s == -1) |
|
78 return -1; |
|
79 size_t size = sizeof(sockaddr_un) + socket_file.length()+1; |
|
80 sockaddr_un* saddr = (sockaddr_un*)malloc(size); |
|
81 saddr->sun_family = AF_UNIX; |
|
82 strcpy(saddr->sun_path, socket_file.c_str()); |
|
83 if(::connect(s, (sockaddr*)saddr, SUN_LEN(saddr)) == -1) |
|
84 return -1; |
|
85 free(saddr); |
|
86 return s; |
|
87 } |
|
88 |
|
89 void server_call::disconnect() |
|
90 { |
|
91 if(fd >= 0) |
|
92 close(fd); |
|
93 } |
|
94 |
|
95 response server_call::call(const mystring& socket_file) |
|
96 { |
|
97 trace("server_call::call"); |
|
98 mystring msg = build_msg(); |
|
99 if(!msg) |
|
100 RETURN(bad, "Invalid command data"); |
|
101 fd = connect(socket_file); |
|
102 if(fd == -1) |
|
103 RETURN(econn, "Unable to connect to the server"); |
|
104 if(!send(fd, msg)) |
|
105 RETURN(econn, "Server aborted the connection"); |
|
106 return response::read(fd); |
|
107 } |