]> git.sesse.net Git - freerainbowtables/blob - Common/rt api/Public.cpp
(C)
[freerainbowtables] / Common / rt api / Public.cpp
1 /*
2  * freerainbowtables is a project for generating, distributing, and using
3  * perfect rainbow tables
4  *
5  * Copyright (C) Zhu Shuanglei <shuanglei@hotmail.com>
6  * Copyright Martin Westergaard Jørgensen <martinwj2005@gmail.com>
7  * Copyright 2009, 2010 Daniël Niggebrugge <niggebrugge@fox-it.com>
8  * Copyright 2009, 2010, 2011 James Nobis <frt@quelrod.net>
9  *
10  * This file is part of freerainbowtables.
11  *
12  * freerainbowtables is free software: you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation, either version 2 of the License.
15  *
16  * freerainbowtables is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with freerainbowtables.  If not, see <http://www.gnu.org/licenses/>.
23 */
24
25 #if defined(_WIN32) && !defined(__GNUC__)
26         #pragma warning(disable : 4786)
27 #endif
28
29 #ifdef _WIN32
30         #ifdef BOINC
31                 #include "boinc_win.h"
32         #endif
33 #else
34 //#include "config.h"
35 #include <cstdio>
36 #include <cctype>
37 #include <ctime>
38 #include <cstring>
39 #include <cstdlib>
40 #include <csignal>
41 #include <unistd.h>
42
43 #endif
44 #ifdef BOINC
45         #include "filesys.h"
46         #include "boinc_api.h"
47 #endif
48 #include "Public.h"
49
50 #ifdef _WIN32
51         #include <windows.h>
52 #endif
53
54 #if defined(_WIN32) && !defined(__GNUC__)
55         #include <windows.h>
56         #include <time.h>
57
58         #if defined(_MSC_VER) || defined(_MSC_EXTENSIONS)
59                 #define DELTA_EPOCH_IN_MICROSECS  11644473600000000Ui64
60         #else
61                 #define DELTA_EPOCH_IN_MICROSECS  11644473600000000ULL
62         #endif
63  
64         struct timezone
65         {
66                 int tz_minuteswest; /* minutes W of Greenwich */
67                 int tz_dsttime;     /* type of dst correction */
68         };
69  
70         int gettimeofday(struct timeval *tv, struct timezone *tz)
71         {
72                 // Define a structure to receive the current Windows filetime
73                 FILETIME ft;
74  
75                 // Initialize the present time to 0 and the timezone to UTC
76                 unsigned __int64 tmpres = 0;
77                 static int tzflag = 0;
78  
79                 if (NULL != tv)
80                 {
81                         GetSystemTimeAsFileTime(&ft);
82  
83                         // The GetSystemTimeAsFileTime returns the number of 100 nanosecond 
84                         // intervals since Jan 1, 1601 in a structure. Copy the high bits to 
85                         // the 64 bit tmpres, shift it left by 32 then or in the low 32 bits.
86                         tmpres |= ft.dwHighDateTime;
87                         tmpres <<= 32;
88                         tmpres |= ft.dwLowDateTime;
89  
90                         // Convert to microseconds by dividing by 10
91                         tmpres /= 10;
92  
93                         // The Unix epoch starts on Jan 1 1970.  Need to subtract the difference 
94                         // in seconds from Jan 1 1601.
95                         tmpres -= DELTA_EPOCH_IN_MICROSECS;
96          
97                         // Finally change microseconds to seconds and place in the seconds value. 
98                         // The modulus picks up the microseconds.
99                         tv->tv_sec = (long)(tmpres / 1000000UL);
100                         tv->tv_usec = (long)(tmpres % 1000000UL);
101                 }
102          
103                 if (NULL != tz)
104                 {
105                         if (!tzflag)
106                         {
107                                 _tzset();
108                                 tzflag++;
109                         }
110           
111                         // Adjust for the timezone west of Greenwich
112                         tz->tz_minuteswest = _timezone / 60;
113                         tz->tz_dsttime = _daylight;
114                 }
115          
116                 return 0;
117         }
118
119 #elif defined(__APPLE__) || \
120         ((defined(__unix__) || defined(unix)) && !defined(USG))
121
122         #include <sys/param.h>
123
124         #if defined(BSD)
125                 #include <sys/sysctl.h>
126         #elif defined(__linux__)
127                 #include <sys/sysinfo.h>
128         #else
129                 #error Unsupported Operating System
130         #endif
131 #endif
132
133 //////////////////////////////////////////////////////////////////////
134
135 timeval sub_timeofday( timeval tv2, timeval tv )
136 {
137         timeval final;
138
139         final.tv_usec = tv2.tv_usec - tv.tv_usec;
140         final.tv_sec = tv2.tv_sec - tv.tv_sec;
141
142         if ( final.tv_usec < 0 )
143         {
144                 final.tv_usec += 1000000;
145                 --final.tv_sec;
146         }
147
148         return final;
149 }
150
151 long GetFileLen(FILE* file)
152 {
153         // XXX on x86/x86_64 linux returns long
154         // 32-bit this is a problem if the file is > (2^31-1) bytes
155         long pos = ftell(file);
156         fseek(file, 0, SEEK_END);
157         long len = ftell(file);
158         fseek(file, pos, SEEK_SET);
159
160         return len;
161 }
162
163 string TrimString(string s)
164 {
165         while (s.size() > 0)
166         {
167                 if (s[0] == ' ' || s[0] == '\t')
168                         s = s.substr(1);
169                 else
170                         break;
171         }
172
173         while (s.size() > 0)
174         {
175                 if (s[s.size() - 1] == ' ' || s[s.size() - 1] == '\t')
176                         s = s.substr(0, s.size() - 1);
177                 else
178                         break;
179         }
180
181         return s;
182 }
183 bool GetHybridCharsets(string sCharset, vector<tCharset>& vCharset)
184 {
185         // Example: hybrid(mixalpha-numeric-all-space#1-6,numeric#1-4)
186         if(sCharset.substr(0, 6) != "hybrid") // Not hybrid charset
187                 return false;
188
189         string::size_type nEnd = sCharset.rfind(')');
190         string::size_type nStart = (int) sCharset.rfind('(');
191         string sChar = sCharset.substr(nStart + 1, nEnd - nStart - 1);
192         vector<string> vParts;
193         SeperateString(sChar, ",", vParts);
194         for(uint32 i = 0; i < vParts.size(); i++)
195         {
196                 tCharset stCharset;
197                 vector<string> vParts2;
198                 SeperateString(vParts[i], "#", vParts2);
199                 stCharset.sName = vParts2[0];
200                 vector<string> vParts3;
201                 SeperateString(vParts2[1], "-", vParts3);
202                 stCharset.nPlainLenMin = atoi(vParts3[0].c_str());
203                 stCharset.nPlainLenMax = atoi(vParts3[1].c_str());
204                 vCharset.push_back(stCharset);
205         }
206         return true;
207 }
208 #ifdef BOINC
209 bool boinc_ReadLinesFromFile(string sPathName, vector<string>& vLine)
210 {
211         vLine.clear();
212 #ifdef USE_INTEGRATED_CHARSET
213         vLine.push_back("byte                        = []");
214         vLine.push_back("alpha                       = [ABCDEFGHIJKLMNOPQRSTUVWXYZ]");
215         vLine.push_back("alpha-space                 = [ABCDEFGHIJKLMNOPQRSTUVWXYZ ]");
216         vLine.push_back("alpha-numeric               = [ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789]");
217         vLine.push_back("alpha-numeric-space         = [ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 ]");
218         vLine.push_back("alpha-numeric-symbol14      = [ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\x21\x40\x23\x24\x25\x5E\x26\x2A\x28\x29\x2D\x5F\x2B\x3D]");
219         vLine.push_back("alpha-numeric-symbol14-space= [ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\x21\x40\x23\x24\x25\x5E\x26\x2A\x28\x29\x2D\x5F\x2B\x3D\x20]");
220         vLine.push_back("all                         = [ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\x21\x40\x23\x24\x25\x5E\x26\x2A\x28\x29\x2D\x5F\x2B\x3D\x7E\x60\x5B\x5D\x7B\x7D\x7C\x5C\x3A\x3B\x22\x27\x3C\x3E\x2C\x2E\x3F\x2F]");
221         vLine.push_back("all-space                   = [ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\x21\x40\x23\x24\x25\x5E\x26\x2A\x28\x29\x2D\x5F\x2B\x3D\x7E\x60\x5B\x5D\x7B\x7D\x7C\x5C\x3A\x3B\x22\x27\x3C\x3E\x2C\x2E\x3F\x2F\x20]");
222         vLine.push_back("alpha-numeric-symbol32-space = [ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\x21\x40\x23\x24\x25\x5E\x26\x2A\x28\x29\x2D\x5F\x2B\x3D\x7E\x60\x5B\x5D\x7B\x7D\x7C\x5C\x3A\x3B\x22\x27\x3C\x3E\x2C\x2E\x3F\x2F\x20]");
223         vLine.push_back("lm-frt-cp437                = [\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2A\x2B\x2C\x2D\x2E\x2F\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3A\x3B\x3C\x3D\x3E\x3F\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4A\x4B\x4C\x4D\x4E\x4F\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5A\x5B\x5C\x5D\x5E\x5F\x60\x7B\x7C\x7D\x7E\x80\x8E\x8F\x90\x92\x99\x9A\x9B\x9C\x9D\x9E\x9F\xA5\xE0\xE1\xE2\xE3\xE4\xE6\xE7\xE8\xE9\xEA\xEB\xEE]");
224         vLine.push_back("lm-frt-cp850                = [\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2A\x2B\x2C\x2D\x2E\x2F\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3A\x3B\x3C\x3D\x3E\x3F\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4A\x4B\x4C\x4D\x4E\x4F\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5A\x5B\x5C\x5D\x5E\x5F\x60\x7B\x7C\x7D\x7E\x80\x8E\x8F\x90\x92\x99\x9A\x9C\x9D\x9F\xA5\xB5\xB6\xB7\xBD\xBE\xC7\xCF\xD1\xD2\xD3\xD4\xD5\xD6\xD7\xD8\xDE\xE0\xE1\xE2\xE3\xE5\xE6\xE8\xE9\xEA\xEB\xED\xEF]");
225         vLine.push_back("lm-frt-cp437-850            = [\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2A\x2B\x2C\x2D\x2E\x2F\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3A\x3B\x3C\x3D\x3E\x3F\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4A\x4B\x4C\x4D\x4E\x4F\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5A\x5B\x5C\x5D\x5E\x5F\x60\x7B\x7C\x7D\x7E\x80\x8E\x8F\x90\x92\x99\x9A\x9B\x9C\x9D\x9E\x9F\xA5\xB5\xB6\xB7\xBD\xBE\xC7\xCF\xD1\xD2\xD3\xD4\xD5\xD6\xD7\xD8\xDE\xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xEA\xEB\xED\xEE\xEF]");
226         vLine.push_back("numeric                     = [0123456789]");
227         vLine.push_back("numeric-space               = [0123456789 ]");
228         vLine.push_back("loweralpha                  = [abcdefghijklmnopqrstuvwxyz]");
229         vLine.push_back("loweralpha-space            = [abcdefghijklmnopqrstuvwxyz ]");
230         vLine.push_back("loweralpha-numeric          = [abcdefghijklmnopqrstuvwxyz0123456789]");
231         vLine.push_back("loweralpha-numeric-space    = [abcdefghijklmnopqrstuvwxyz0123456789 ]");
232         vLine.push_back("loweralpha-numeric-symbol14 = [abcdefghijklmnopqrstuvwxyz0123456789\x21\x40\x23\x24\x25\x5E\x26\x2A\x28\x29\x2D\x5F\x2B\x3D]");
233         vLine.push_back("loweralpha-numeric-all      = [abcdefghijklmnopqrstuvwxyz0123456789\x21\x40\x23\x24\x25\x5E\x26\x2A\x28\x29\x2D\x5F\x2B\x3D\x7E\x60\x5B\x5D\x7B\x7D\x7C\x5C\x3A\x3B\x22\x27\x3C\x3E\x2C\x2E\x3F\x2F]");
234         vLine.push_back("loweralpha-numeric-symbol32-space= [abcdefghijklmnopqrstuvwxyz0123456789\x21\x40\x23\x24\x25\x5E\x26\x2A\x28\x29\x2D\x5F\x2B\x3D\x7E\x60\x5B\x5D\x7B\x7D\x7C\x5C\x3A\x3B\x22\x27\x3C\x3E\x2C\x2E\x3F\x2F\x20]");
235         vLine.push_back("mixalpha                    = [abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ]");
236         vLine.push_back("mixalpha-space              = [abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ ]");
237         vLine.push_back("mixalpha-numeric            = [abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789]");
238         vLine.push_back("mixalpha-numeric-space      = [abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 ]");
239         vLine.push_back("mixalpha-numeric-symbol14   = [abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\x21\x40\x23\x24\x25\x5E\x26\x2A\x28\x29\x2D\x5F\x2B\x3D]");
240         vLine.push_back("mixalpha-numeric-all        = [abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\x21\x40\x23\x24\x25\x5E\x26\x2A\x28\x29\x2D\x5F\x2B\x3D\x7E\x60\x5B\x5D\x7B\x7D\x7C\x5C\x3A\x3B\x22\x27\x3C\x3E\x2C\x2E\x3F\x2F]");
241         vLine.push_back("mixalpha-numeric-symbol32-space  = [abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\x21\x40\x23\x24\x25\x5E\x26\x2A\x28\x29\x2D\x5F\x2B\x3D\x7E\x60\x5B\x5D\x7B\x7D\x7C\x5C\x3A\x3B\x22\x27\x3C\x3E\x2C\x2E\x3F\x2F\x20]");
242         vLine.push_back("mixalpha-numeric-all-space  = [abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\x21\x40\x23\x24\x25\x5E\x26\x2A\x28\x29\x2D\x5F\x2B\x3D\x7E\x60\x5B\x5D\x7B\x7D\x7C\x5C\x3A\x3B\x22\x27\x3C\x3E\x2C\x2E\x3F\x2F\x20]");
243 #endif
244
245         char input_path[512];
246         boinc_resolve_filename(sPathName.c_str(), input_path, sizeof(input_path));
247         FILE *file = boinc_fopen(input_path, "rb");
248         if (!file) {
249                 fprintf(stderr,
250                         "Couldn't find input file, resolved name %s.\n", input_path
251                 );
252                 exit(-1);
253         }
254
255         if (file != NULL)
256         {
257                 long len = GetFileLen(file);
258                 char* data = new char[len + 1];
259                 fread(data, 1, len, file);
260                 data[len] = '\0';
261                 string content = data;
262                 content += "\n";
263                 delete [] data;
264
265                 unsigned int i;
266                 for (i = 0; i < content.size(); i++)
267                 {
268                         if (content[i] == '\r')
269                                 content[i] = '\n';
270                 }
271
272                 string::size_type n;
273                 while ((n = content.find("\n", 0)) != string::npos)
274                 {
275                         string line = content.substr(0, n);
276                         line = TrimString(line);
277                         if (line != "")
278                                 vLine.push_back(line);
279                         content = content.substr(n + 1);
280                 }
281
282                 fclose(file);
283         }
284         else
285                 return false;
286
287         return true;
288 }
289 #endif
290 bool ReadLinesFromFile(string sPathName, vector<string>& vLine)
291 {
292         vLine.clear();
293
294         FILE* file = fopen(sPathName.c_str(), "rb");
295         if (file != NULL)
296         {
297                 long len = GetFileLen(file);
298                 char* data = new char[len + 1];
299                 fread(data, 1, len, file);
300                 data[len] = '\0';
301                 string content = data;
302                 content += "\n";
303                 delete [] data;
304
305                 unsigned int i;
306                 for (i = 0; i < content.size(); i++)
307                 {
308                         if (content[i] == '\r')
309                                 content[i] = '\n';
310                 }
311
312                 string::size_type n;
313                 while ((n = content.find("\n", 0)) != string::npos)
314                 {
315                         string line = content.substr(0, n);
316                         line = TrimString(line);
317                         if (line != "")
318                                 vLine.push_back(line);
319                         content = content.substr(n + 1);
320                 }
321
322                 fclose(file);
323         }
324         else
325                 return false;
326
327         return true;
328 }
329
330 bool writeResultLineToFile(string sOutputFile, string sHash, string sPlain, string sBinary)
331 {
332         FILE* file = fopen(sOutputFile.c_str(), "a");
333         if (file!=NULL)
334         {
335                 string buffer = sHash + ":" + sPlain + ":" + sBinary + "\n";
336                 fputs (buffer.c_str(), file);
337                 fclose (file);
338                 return true;
339         }
340         else
341                 return false;
342 }
343
344 bool SeperateString(string s, string sSeperator, vector<string>& vPart)
345 {
346         vPart.clear();
347
348         unsigned int i;
349         for (i = 0; i < sSeperator.size(); i++)
350         {
351                 string::size_type n;
352                 if ( (n = s.find(sSeperator[i])) != string::npos)
353                 {
354                         vPart.push_back(s.substr(0, n));
355                         s = s.substr(n + 1);
356                 }
357                 else
358                 {
359                         printf("not found: %c\n", sSeperator[i]);
360                         printf("s: %s\n", s.c_str());
361                         return false;
362                 }
363         }
364         vPart.push_back(s);
365
366         return true;
367 }
368
369 string uint64tostr(uint64 n)
370 {
371         char str[32];
372
373 #ifdef _WIN32
374         sprintf(str, "%I64u", n);
375 #else
376         sprintf(str, "%llu", n);
377 #endif
378
379         return str;
380 }
381
382 string uint64tohexstr(uint64 n)
383 {
384         char str[32];
385
386 #ifdef _WIN32
387         sprintf(str, "%016I64x", n);
388 #else
389         sprintf(str, "%016llx", n);
390 #endif
391
392         return str;
393 }
394
395 string HexToStr(const unsigned char* pData, int nLen)
396 {
397         string sRet;
398         int i;
399         for (i = 0; i < nLen; i++)
400         {
401                 char szByte[3];
402                 sprintf(szByte, "%02x", pData[i]);
403                 sRet += szByte;
404         }
405
406         return sRet;
407 }
408
409 unsigned long GetAvailPhysMemorySize()
410 {
411 #ifdef _WIN32
412         MEMORYSTATUS ms;
413         GlobalMemoryStatus(&ms);
414         return ms.dwAvailPhys;
415 #elif defined(BSD)
416         int mib[2] = { CTL_HW, HW_PHYSMEM };
417         uint64 physMem;
418         //XXX warning size_t isn't portable
419         size_t len;
420         len = sizeof(physMem);
421         sysctl(mib, 2, &physMem, &len, NULL, 0);
422         return physMem;
423 #elif defined(__linux__)
424         struct sysinfo info;
425         sysinfo(&info);
426         return ( info.freeram + info.bufferram ) * (unsigned long) info.mem_unit;
427 #else
428         return 0;
429         #error Unsupported Operating System
430 #endif
431 }
432
433 string GetApplicationPath()
434 {
435         char fullPath[FILENAME_MAX];
436
437 #ifdef _WIN32
438         GetModuleFileName(NULL, fullPath, FILENAME_MAX);
439 #else
440         char szTmp[32];
441         // XXX linux/proc file system dependent
442         sprintf(szTmp, "/proc/%d/exe", getpid());
443         int bytes = readlink(szTmp, fullPath, FILENAME_MAX);
444
445         if( bytes >= 0 )
446                 fullPath[bytes] = '\0';
447 #endif
448
449         string sApplicationPath = fullPath;
450 #ifdef _WIN32
451         string::size_type nIndex = sApplicationPath.find_last_of('\\');
452 #else
453         string::size_type nIndex = sApplicationPath.find_last_of('/');
454 #endif
455
456         if ( nIndex != string::npos )
457                 sApplicationPath = sApplicationPath.substr(0, nIndex+1);
458
459         return sApplicationPath;
460 }
461
462 void ParseHash(string sHash, unsigned char* pHash, int& nHashLen)
463 {
464         uint32 i;
465         for (i = 0; i < sHash.size() / 2; i++)
466         {
467                 string sSub = sHash.substr(i * 2, 2);
468                 int nValue;
469                 sscanf(sSub.c_str(), "%02x", &nValue);
470                 pHash[i] = (unsigned char)nValue;
471         }
472
473         nHashLen = (int) sHash.size() / 2;
474 }
475
476 void Logo()
477 {
478         printf("RainbowCrack (improved) 2.0 - Making a Faster Cryptanalytic Time-Memory Trade-Off\n");
479         printf("by Martin Westergaard <martinwj2005@gmail.com>\n");
480         printf("http://www.freerainbowtables.com/\n");
481         printf("original code by Zhu Shuanglei <shuanglei@hotmail.com>\n");
482         printf("http://www.antsight.com/zsl/rainbowcrack/\n\n");
483 }
484
485 // XXX nmap is GPL2, will check newer releases regarding license
486 // Code comes from nmap, used for the linux implementation of kbhit()
487 #ifndef _WIN32
488
489 static int tty_fd = 0;
490 struct termios saved_ti;
491
492 int tty_getchar()
493 {
494         int c, numChars;
495
496         if (tty_fd && tcgetpgrp(tty_fd) == getpid()) {
497                 c = 0;
498                 numChars = read(tty_fd, &c, 1);
499                 if (numChars > 0) return c;
500         }
501
502         return -1;
503 }
504
505 void tty_done()
506 {
507         if (!tty_fd) return;
508
509         tcsetattr(tty_fd, TCSANOW, &saved_ti);
510
511         close(tty_fd);
512         tty_fd = 0;
513 }
514
515 void tty_init()
516 {
517         struct termios ti;
518
519         if (tty_fd)
520                 return;
521
522         if ((tty_fd = open("/dev/tty", O_RDONLY | O_NONBLOCK)) < 0) return;
523
524         tcgetattr(tty_fd, &ti);
525         saved_ti = ti;
526         ti.c_lflag &= ~(ICANON | ECHO);
527         ti.c_cc[VMIN] = 1;
528         ti.c_cc[VTIME] = 0;
529         tcsetattr(tty_fd, TCSANOW, &ti);
530
531         atexit(tty_done);
532 }
533
534 void tty_flush(void)
535 {
536         tcflush(tty_fd, TCIFLUSH);
537 }
538 // end nmap code
539 #endif