Subversion Repositories HomeAutomation

Rev

Rev 1987 | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | SVN | RSS feed

Rev 1987 Rev 1989
1
/*
1
/*
2
 *
2
 *
3
 *  Copyright (C) 2010  Mattias Runge
3
 *  Copyright (C) 2010  Mattias Runge
4
 *
4
 *
5
 *  This program is free software; you can redistribute it and/or modify
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
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
7
 *  the Free Software Foundation; either version 2 of the License, or
8
 *  (at your option) any later version.
8
 *  (at your option) any later version.
9
 *
9
 *
10
 *  This program is distributed in the hope that it will be useful,
10
 *  This program is distributed in the hope that it will be useful,
11
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 *  GNU General Public License for more details.
13
 *  GNU General Public License for more details.
14
 *
14
 *
15
 *  You should have received a copy of the GNU General Public License along
15
 *  You should have received a copy of the GNU General Public License along
16
 *  with this program; if not, write to the Free Software Foundation, Inc.,
16
 *  with this program; if not, write to the Free Software Foundation, Inc.,
17
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18
 *
18
 *
19
 */
19
 */
20
 
20
 
21
#include <string>
21
#include <string>
22
#include <vector>
22
#include <vector>
23
#include <iostream>
23
#include <iostream>
24
 
24
 
25
#include <signal.h>
25
#include <signal.h>
26
#include <stdio.h>
26
#include <stdio.h>
27
#include <stdlib.h>
27
#include <stdlib.h>
28
#include <pwd.h>
28
#include <pwd.h>
29
 
29
 
30
#include <boost/lexical_cast.hpp>
30
#include <boost/lexical_cast.hpp>
31
#include <boost/thread/mutex.hpp>
31
#include <boost/thread/mutex.hpp>
32
#include <boost/thread/condition.hpp>
32
#include <boost/thread/condition.hpp>
33
#include <boost/thread/locks.hpp>
33
#include <boost/thread/locks.hpp>
34
#include <boost/algorithm/string.hpp>
34
#include <boost/algorithm/string.hpp>
35
#include <boost/program_options.hpp>
35
#include <boost/program_options.hpp>
36
 
36
 
37
#include "config.h"
37
#include "config.h"
38
 
38
 
39
#include "net/Manager.h"
39
#include "net/Manager.h"
40
#include "net/Subscriber.h"
40
#include "net/Subscriber.h"
41
#include "net/types.h"
41
#include "net/types.h"
42
 
42
 
43
#include "common/common.h"
43
#include "common/common.h"
44
#include "common/log.h"
44
#include "common/log.h"
45
 
45
 
46
#include <readline/readline.h>
46
#include <readline/readline.h>
47
#include <readline/history.h>
47
#include <readline/history.h>
48
 
48
 
49
using namespace atom;
49
using namespace atom;
50
 
50
 
51
bool finish = false;
51
bool finish = false;
52
common::StringList autocomplete_list;
52
common::StringList autocomplete_list;
53
char* buffer = NULL;
53
char* buffer = NULL;
54
boost::condition on_message_condition;
54
boost::condition on_message_condition;
55
struct termios original_flags;
55
struct termios original_flags;
56
std::string history_filename;
56
std::string history_filename;
57
 
57
 
58
void Handler(int status);
58
void Handler(int status);
59
void CleanUp();
59
void CleanUp();
60
 
60
 
61
char* AutoCompleteGet(const char* text, int state);
61
char* AutoCompleteGet(const char* text, int state);
62
static char** AutoComplete(const char* text, int start, int end);
62
static char** AutoComplete(const char* text, int start, int end);
63
 
63
 
64
std::string GetUserHomeDirectory()
64
std::string GetUserHomeDirectory()
65
{
65
{
66
    return std::string(getpwuid(getuid())->pw_dir);
66
    return std::string(getpwuid(getuid())->pw_dir);
67
}
67
}
68
 
68
 
69
class ConsoleClient : public net::Subscriber
69
class ConsoleClient : public net::Subscriber
70
{
70
{
71
public:
71
public:
72
    typedef boost::shared_ptr<ConsoleClient> Pointer;
72
    typedef boost::shared_ptr<ConsoleClient> Pointer;
73
   
73
   
74
    ConsoleClient(std::string address, unsigned int port)
74
    ConsoleClient(std::string address, unsigned int port)
75
    {
75
    {
76
        this->client_id_ = net::Manager::Instance()->Connect(net::PROTOCOL_TCP, address, port);
76
        this->client_id_ = net::Manager::Instance()->Connect(net::TRANSPORT_PROTOCOL_TCP, address, port);
77
    }
77
    }
78
   
78
   
79
    virtual ~ConsoleClient()
79
    virtual ~ConsoleClient()
80
    {
80
    {
81
        net::Manager::Instance()->Disconnect(this->client_id_);
81
        net::Manager::Instance()->Disconnect(this->client_id_);
82
 
82
 
83
        this->io_service_.stop();
83
        this->io_service_.stop();
84
    }
84
    }
85
   
85
   
86
    std::string GetPrompt()
86
    std::string GetPrompt()
87
    {
87
    {
88
        return this->prompt_;
88
        return this->prompt_;
89
    }
89
    }
90
   
90
   
91
    void SendResponse(std::string payload)
91
    void SendResponse(std::string payload)
92
    {
92
    {
93
        std::string packet = "RESP";
93
        std::string packet = "RESP";
94
        packet += common::PadNumber(payload.length() + 1, 4);
94
        packet += common::PadNumber(payload.length() + 1, 4);
95
        packet += payload;
95
        packet += payload;
96
       
96
       
97
        net::Manager::Instance()->SendTo(this->client_id_, common::Byteset(packet.begin(), packet.end()));
97
        net::Manager::Instance()->SendTo(this->client_id_, common::Byteset(packet.begin(), packet.end()));
98
    }
98
    }
99
   
99
   
100
    void AutoCompleteRequest(unsigned int arg_index, std::string commandline)
100
    void AutoCompleteRequest(unsigned int arg_index, std::string commandline)
101
    {
101
    {
102
        std::string payload = common::PadNumber(arg_index, 4);
102
        std::string payload = common::PadNumber(arg_index, 4);
103
        payload += commandline;
103
        payload += commandline;
104
       
104
       
105
        std::string packet = "COMP";
105
        std::string packet = "COMP";
106
        packet += common::PadNumber(payload.length() + 1, 4);
106
        packet += common::PadNumber(payload.length() + 1, 4);
107
        packet += payload;
107
        packet += payload;
108
       
108
       
109
        net::Manager::Instance()->SendTo(this->client_id_, common::Byteset(packet.begin(), packet.end()));
109
        net::Manager::Instance()->SendTo(this->client_id_, common::Byteset(packet.begin(), packet.end()));
110
    }
110
    }
111
   
111
   
112
private:
112
private:
113
    net::SocketId client_id_;
113
    net::SocketId client_id_;
114
    std::string prompt_;
114
    std::string prompt_;
115
    std::vector<unsigned char> buffer_;
115
    std::vector<unsigned char> buffer_;
116
   
116
   
117
    void SlotOnNewStateHandler(net::SocketId client_id, net::ClientState client_state)
117
    void SlotOnNewStateHandler(net::SocketId client_id, net::ClientState client_state)
118
    {
118
    {
119
        if (client_state != net::CLIENT_STATE_CONNECTED)
119
        if (client_state != net::CLIENT_STATE_CONNECTED)
120
        {
120
        {
121
            std::cout << "Disconnected from server." << std::endl;
121
            std::cout << "Disconnected from server." << std::endl;
122
           
122
           
123
            this->client_id_ = 0;
123
            this->client_id_ = 0;
124
            finish = true;
124
            finish = true;
125
            on_message_condition.notify_all();
125
            on_message_condition.notify_all();
126
        }
126
        }
127
    }
127
    }
128
   
128
   
129
    void SlotOnNewClientHandler(net::SocketId id, net::SocketId server_id)
129
    void SlotOnNewClientHandler(net::SocketId id, net::SocketId server_id)
130
    {
130
    {
131
    }
131
    }
132
   
132
   
133
    void SlotOnNewDataHandler(net::SocketId client_id, common::Byteset data)
133
    void SlotOnNewDataHandler(net::SocketId client_id, common::Byteset data)
134
    {
134
    {
135
        for (unsigned int n = 0; n < data.size(); n++)
135
        for (unsigned int n = 0; n < data.size(); n++)
136
        {
136
        {
137
            this->buffer_.push_back(data[n]);
137
            this->buffer_.push_back(data[n]);
138
        }
138
        }
139
 
139
 
140
        while (this->buffer_.size() >= 8)
140
        while (this->buffer_.size() >= 8)
141
        {
141
        {
142
            std::string command = "";
142
            std::string command = "";
143
            command += (char)this->buffer_[0];
143
            command += (char)this->buffer_[0];
144
            command += (char)this->buffer_[1];
144
            command += (char)this->buffer_[1];
145
            command += (char)this->buffer_[2];
145
            command += (char)this->buffer_[2];
146
            command += (char)this->buffer_[3];
146
            command += (char)this->buffer_[3];
147
 
147
 
148
            std::string payload_length_str = "";
148
            std::string payload_length_str = "";
149
            payload_length_str += (char)this->buffer_[4];
149
            payload_length_str += (char)this->buffer_[4];
150
            payload_length_str += (char)this->buffer_[5];
150
            payload_length_str += (char)this->buffer_[5];
151
            payload_length_str += (char)this->buffer_[6];
151
            payload_length_str += (char)this->buffer_[6];
152
            payload_length_str += (char)this->buffer_[7];
152
            payload_length_str += (char)this->buffer_[7];
153
           
153
           
154
            unsigned int payload_length = boost::lexical_cast<unsigned int>(payload_length_str) - 1;
154
            unsigned int payload_length = boost::lexical_cast<unsigned int>(payload_length_str) - 1;
155
           
155
           
156
            if (this->buffer_.size() - 8 < payload_length)
156
            if (this->buffer_.size() - 8 < payload_length)
157
            {
157
            {
158
                return;
158
                return;
159
            }
159
            }
160
         
160
         
161
            std::string payload = "";
161
            std::string payload = "";
162
            for (unsigned int n = 8; n < payload_length + 8; n++)
162
            for (unsigned int n = 8; n < payload_length + 8; n++)
163
            {
163
            {
164
                payload += (char)this->buffer_[n];
164
                payload += (char)this->buffer_[n];
165
            }
165
            }
166
           
166
           
167
            this->buffer_.erase(this->buffer_.begin(), this->buffer_.begin() + payload_length + 8);
167
            this->buffer_.erase(this->buffer_.begin(), this->buffer_.begin() + payload_length + 8);
168
           
168
           
169
            if (command == "TEXT")
169
            if (command == "TEXT")
170
            {
170
            {
171
                std::cout << payload << std::flush;
171
                std::cout << payload << std::flush;
172
            }
172
            }
173
            else if (command == "PROM")
173
            else if (command == "PROM")
174
            {
174
            {
175
                this->prompt_ = payload;
175
                this->prompt_ = payload;
176
                on_message_condition.notify_all();
176
                on_message_condition.notify_all();
177
            }
177
            }
178
            else if (command == "COMP")
178
            else if (command == "COMP")
179
            {
179
            {
180
                autocomplete_list.clear();
180
                autocomplete_list.clear();
181
               
181
               
182
                if (payload.length() > 0)
182
                if (payload.length() > 0)
183
                {
183
                {
184
                    boost::algorithm::split(autocomplete_list, payload, boost::is_any_of("\n"), boost::algorithm::token_compress_on);
184
                    boost::algorithm::split(autocomplete_list, payload, boost::is_any_of("\n"), boost::algorithm::token_compress_on);
185
                }
185
                }
186
               
186
               
187
                on_message_condition.notify_all();
187
                on_message_condition.notify_all();
188
            }
188
            }
189
            else
189
            else
190
            {
190
            {
191
                std::cerr << "Could not parse package." << std::endl;
191
                std::cerr << "Could not parse package." << std::endl;
192
                finish = true;
192
                finish = true;
193
                on_message_condition.notify_all();
193
                on_message_condition.notify_all();
194
                break;
194
                break;
195
            }
195
            }
196
        }
196
        }
197
    }
197
    }
198
};
198
};
199
 
199
 
200
ConsoleClient::Pointer cc;
200
ConsoleClient::Pointer cc;
201
 
201
 
202
 
202
 
203
int main(int argc, char **argv)
203
int main(int argc, char **argv)
204
{
204
{
205
    // Signal handlers
205
    // Signal handlers
206
    signal(SIGTERM, Handler);
206
    signal(SIGTERM, Handler);
207
    signal(SIGINT, Handler);
207
    signal(SIGINT, Handler);
208
    signal(SIGQUIT, Handler);
208
    signal(SIGQUIT, Handler);
209
    signal(SIGABRT, Handler);
209
    signal(SIGABRT, Handler);
210
    signal(SIGPIPE, Handler);
210
    signal(SIGPIPE, Handler);
211
   
211
   
212
    boost::mutex guard_mutex;
212
    boost::mutex guard_mutex;
213
   
213
   
214
    // Setup readline
214
    // Setup readline
215
    history_filename = GetUserHomeDirectory() + "/.atomic_history";
215
    history_filename = GetUserHomeDirectory() + "/.atomic_history";
216
    read_history(history_filename.data());
216
    read_history(history_filename.data());
217
   
217
   
218
    rl_attempted_completion_function = AutoComplete;
218
    rl_attempted_completion_function = AutoComplete;
219
   
219
   
220
    // Save command line state
220
    // Save command line state
221
    tcgetattr(fileno(stdin), &original_flags);
221
    tcgetattr(fileno(stdin), &original_flags);
222
   
222
   
223
    // Parse commandline
223
    // Parse commandline
224
    boost::program_options::options_description command_line;
224
    boost::program_options::options_description command_line;
225
    boost::program_options::variables_map variable_map;
225
    boost::program_options::variables_map variable_map;
226
   
226
   
227
    //log::SetLevel(log::LOG_LEVEL_ALL);
227
    //log::SetLevel(log::LOG_LEVEL_ALL);
228
   
228
   
229
    command_line.add_options()
229
    command_line.add_options()
230
    ("help,h",    "produce help message")
230
    ("help,h",    "produce help message")
231
    ("command,c", boost::program_options::value<std::string>()->default_value(""), "command")
231
    ("command,c", boost::program_options::value<std::string>()->default_value(""), "command")
232
    ("server,s",  boost::program_options::value<std::string>()->default_value("localhost"), "server address")
232
    ("server,s",  boost::program_options::value<std::string>()->default_value("localhost"), "server address")
233
    ("port,p",    boost::program_options::value<unsigned int>()->default_value(1202), "server port");
233
    ("port,p",    boost::program_options::value<unsigned int>()->default_value(1202), "server port");
234
   
234
   
235
    try
235
    try
236
    {
236
    {
237
        boost::program_options::store(boost::program_options::command_line_parser(argc, argv).options(command_line).run(), variable_map);
237
        boost::program_options::store(boost::program_options::command_line_parser(argc, argv).options(command_line).run(), variable_map);
238
    }
238
    }
239
    catch (boost::program_options::unknown_option e)
239
    catch (boost::program_options::unknown_option e)
240
    {
240
    {
241
        std::cerr << e.what() << std::endl;
241
        std::cerr << e.what() << std::endl;
242
        std::cout << command_line << std::endl;
242
        std::cout << command_line << std::endl;
243
        CleanUp();
243
        CleanUp();
244
        return EXIT_FAILURE;
244
        return EXIT_FAILURE;
245
    }
245
    }
246
    catch (boost::program_options::invalid_syntax e)
246
    catch (boost::program_options::invalid_syntax e)
247
    {
247
    {
248
        std::cerr << e.what() << std::endl;
248
        std::cerr << e.what() << std::endl;
249
        std::cout << command_line << std::endl;
249
        std::cout << command_line << std::endl;
250
        CleanUp();
250
        CleanUp();
251
        return EXIT_FAILURE;
251
        return EXIT_FAILURE;
252
    }
252
    }
253
   
253
   
254
    if (variable_map.count("help") != 0)
254
    if (variable_map.count("help") != 0)
255
    {
255
    {
256
        std::cout << command_line << std::endl;
256
        std::cout << command_line << std::endl;
257
        CleanUp();
257
        CleanUp();
258
        return EXIT_SUCCESS;
258
        return EXIT_SUCCESS;
259
    }
259
    }
260
   
260
   
261
    net::Manager::Create();
261
    net::Manager::Create();
262
 
262
 
263
    if (variable_map["command"].as<std::string>() == "")
263
    if (variable_map["command"].as<std::string>() == "")
264
    {
264
    {
265
        std::cout << "\033[29;1mAtom Interactive Console, version " + std::string(VERSION) + " starting...\033[0m" << std::endl;
265
        std::cout << "\033[29;1mAtom Interactive Console, version " + std::string(VERSION) + " starting...\033[0m" << std::endl;
266
        std::cout << "\033[29;1mReleased under " + std::string(LICENSE) + ".\033[0m" << std::endl;
266
        std::cout << "\033[29;1mReleased under " + std::string(LICENSE) + ".\033[0m" << std::endl;
267
        std::cout << "Written by Mattias Runge 2010." << std::endl;
267
        std::cout << "Written by Mattias Runge 2010." << std::endl;
268
       
268
       
269
        std::cout << "Connecting to " << variable_map["server"].as<std::string>().data() << ":" << variable_map["port"].as<unsigned int>() << "..." << std::endl;
269
        std::cout << "Connecting to " << variable_map["server"].as<std::string>().data() << ":" << variable_map["port"].as<unsigned int>() << "..." << std::endl;
270
    }
270
    }
271
   
271
   
272
    try
272
    try
273
    {
273
    {
274
        cc = ConsoleClient::Pointer(new ConsoleClient(variable_map["server"].as<std::string>(), variable_map["port"].as<unsigned int>()));
274
        cc = ConsoleClient::Pointer(new ConsoleClient(variable_map["server"].as<std::string>(), variable_map["port"].as<unsigned int>()));
275
    }
275
    }
276
    catch (std::runtime_error& e)
276
    catch (std::runtime_error& e)
277
    {
277
    {
278
        std::cerr << "Connection error: " << e.what() << std::endl;
278
        std::cerr << "Connection error: " << e.what() << std::endl;
279
        CleanUp();
279
        CleanUp();
280
        return EXIT_FAILURE;
280
        return EXIT_FAILURE;
281
    }
281
    }
282
   
282
   
283
    if (variable_map["command"].as<std::string>() != "")
283
    if (variable_map["command"].as<std::string>() != "")
284
    {
284
    {
285
        boost::mutex::scoped_lock guard(guard_mutex);
285
        boost::mutex::scoped_lock guard(guard_mutex);
286
        on_message_condition.wait(guard);
286
        on_message_condition.wait(guard);
287
       
287
       
288
        if (!finish)
288
        if (!finish)
289
        {
289
        {
290
            cc->SendResponse(variable_map["command"].as<std::string>());
290
            cc->SendResponse(variable_map["command"].as<std::string>());
291
           
291
           
292
            if (!finish)
292
            if (!finish)
293
            {
293
            {
294
                on_message_condition.wait(guard);
294
                on_message_condition.wait(guard);
295
            }
295
            }
296
        }
296
        }
297
    }
297
    }
298
    else
298
    else
299
    {
299
    {
300
        while (true)
300
        while (true)
301
        {
301
        {
302
            boost::mutex::scoped_lock guard(guard_mutex);
302
            boost::mutex::scoped_lock guard(guard_mutex);
303
            on_message_condition.wait(guard);
303
            on_message_condition.wait(guard);
304
           
304
           
305
            if (finish)
305
            if (finish)
306
            {
306
            {
307
                break;
307
                break;
308
            }
308
            }
309
           
309
           
310
            while ((buffer = readline(cc->GetPrompt().data())) != NULL)
310
            while ((buffer = readline(cc->GetPrompt().data())) != NULL)
311
            {
311
            {
312
                if (finish)
312
                if (finish)
313
                {
313
                {
314
                    break;
314
                    break;
315
                }
315
                }
316
               
316
               
317
                if (strlen(buffer) == 0)
317
                if (strlen(buffer) == 0)
318
                {
318
                {
319
                    continue;
319
                    continue;
320
                }
320
                }
321
               
321
               
322
                break;
322
                break;
323
            }
323
            }
324
           
324
           
325
            if (finish)
325
            if (finish)
326
            {
326
            {
327
                break;
327
                break;
328
            }
328
            }
329
           
329
           
330
            cc->SendResponse(buffer);
330
            cc->SendResponse(buffer);
331
            add_history(buffer);
331
            add_history(buffer);
332
        }
332
        }
333
    }
333
    }
334
   
334
   
335
    CleanUp();
335
    CleanUp();
336
   
336
   
337
    return EXIT_SUCCESS;
337
    return EXIT_SUCCESS;
338
}
338
}
339
 
339
 
340
static char** AutoComplete(const char* text, int start, int end)
340
static char** AutoComplete(const char* text, int start, int end)
341
{
341
{
342
    unsigned int count = 0;
342
    unsigned int count = 0;
343
    boost::mutex guard_mutex;
343
    boost::mutex guard_mutex;
344
 
344
 
345
    for (unsigned int n = 0; n < (unsigned int)start; n++)
345
    for (unsigned int n = 0; n < (unsigned int)start; n++)
346
    {
346
    {
347
        if (rl_line_buffer[n] == ' ')
347
        if (rl_line_buffer[n] == ' ')
348
        {
348
        {
349
            count++;
349
            count++;
350
        }
350
        }
351
    }
351
    }
352
   
352
   
353
    cc->AutoCompleteRequest(count, rl_line_buffer);
353
    cc->AutoCompleteRequest(count, rl_line_buffer);
354
   
354
   
355
    boost::mutex::scoped_lock guard(guard_mutex);
355
    boost::mutex::scoped_lock guard(guard_mutex);
356
    on_message_condition.wait(guard);
356
    on_message_condition.wait(guard);
357
   
357
   
358
    /*if (autocomplete_list.size() == 0)
358
    /*if (autocomplete_list.size() == 0)
359
    {
359
    {
360
        return NULL;
360
        return NULL;
361
    }*/
361
    }*/
362
   
362
   
363
    return rl_completion_matches(text, &AutoCompleteGet);
363
    return rl_completion_matches(text, &AutoCompleteGet);
364
}
364
}
365
 
365
 
366
char* AutoCompleteGet(const char* text, int state)
366
char* AutoCompleteGet(const char* text, int state)
367
{
367
{
368
    static int index = 0;
368
    static int index = 0;
369
    int length = strlen(text);
369
    int length = strlen(text);
370
    std::string name;
370
    std::string name;
371
   
371
   
372
    if (!state) // First run
372
    if (!state) // First run
373
    {
373
    {
374
        index = 0;
374
        index = 0;
375
    }
375
    }
376
   
376
   
377
    while (autocomplete_list.size() > (unsigned int) index)
377
    while (autocomplete_list.size() > (unsigned int) index)
378
    {
378
    {
379
        name = autocomplete_list[index];
379
        name = autocomplete_list[index];
380
       
380
       
381
        index++;
381
        index++;
382
       
382
       
383
        if (strncmp(name.data(), text, length) == 0)
383
        if (strncmp(name.data(), text, length) == 0)
384
        {
384
        {
385
            char *result = (char*)malloc(name.size() + 1);
385
            char *result = (char*)malloc(name.size() + 1);
386
            strcpy(result, name.data());
386
            strcpy(result, name.data());
387
           
387
           
388
            return result;
388
            return result;
389
        }
389
        }
390
    }
390
    }
391
   
391
   
392
    return NULL;
392
    return NULL;
393
}
393
}
394
 
394
 
395
void CleanUp()
395
void CleanUp()
396
{
396
{
397
    std::cout << std::endl;
397
    std::cout << std::endl;
398
    //std::cout << "Cleaning up..." << std::endl;
398
    //std::cout << "Cleaning up..." << std::endl;
399
 
399
 
400
    write_history(history_filename.data());
400
    write_history(history_filename.data());
401
   
401
   
402
    cc.reset();
402
    cc.reset();
403
   
403
   
404
    net::Manager::Delete();
404
    net::Manager::Delete();
405
   
405
   
406
    if (buffer != NULL)
406
    if (buffer != NULL)
407
    {
407
    {
408
        free(buffer);
408
        free(buffer);
409
    }
409
    }
410
   
410
   
411
    //std::cout << "Thank you for using Atom. Goodbye!" << std::endl;
411
    //std::cout << "Thank you for using Atom. Goodbye!" << std::endl;
412
   
412
   
413
    tcsetattr(fileno(stdin), TCSANOW, &original_flags); // Restore
413
    tcsetattr(fileno(stdin), TCSANOW, &original_flags); // Restore
414
}
414
}
415
 
415
 
416
void Handler(int status)
416
void Handler(int status)
417
{
417
{
418
    std::string signal_name = "Unknown";
418
    std::string signal_name = "Unknown";
419
   
419
   
420
    switch (status)
420
    switch (status)
421
    {
421
    {
422
        case SIGTERM:
422
        case SIGTERM:
423
        {
423
        {
424
            signal_name = "Terminate";
424
            signal_name = "Terminate";
425
            break;
425
            break;
426
        }  
426
        }  
427
        case SIGINT:
427
        case SIGINT:
428
        {
428
        {
429
            signal_name = "Interrupt";
429
            signal_name = "Interrupt";
430
            break;
430
            break;
431
        }  
431
        }  
432
        case SIGQUIT:
432
        case SIGQUIT:
433
        {
433
        {
434
            signal_name = "Quit";
434
            signal_name = "Quit";
435
            break;
435
            break;
436
        }  
436
        }  
437
        case SIGABRT:
437
        case SIGABRT:
438
        {
438
        {
439
            signal_name = "Abort";
439
            signal_name = "Abort";
440
            break;
440
            break;
441
        }  
441
        }  
442
        case SIGIO:
442
        case SIGIO:
443
        {
443
        {
444
            signal_name = "I/O";
444
            signal_name = "I/O";
445
            break;
445
            break;
446
        }  
446
        }  
447
        case SIGPIPE:
447
        case SIGPIPE:
448
        {
448
        {
449
            signal_name = "Pipe";
449
            signal_name = "Pipe";
450
            break;
450
            break;
451
        }
451
        }
452
    }
452
    }
453
   
453
   
454
   
454
   
455
    if (status != SIGPIPE)
455
    if (status != SIGPIPE)
456
    {
456
    {
457
        CleanUp();
457
        CleanUp();
458
        exit(0);
458
        exit(0);
459
    }
459
    }
460
}
460
}
461
 
461
 
462
 
462