Subversion Repositories HomeAutomation

Rev

Rev 1959 | Rev 1987 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | SVN | RSS feed

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