![]() |
WhiteCat LogCleaner 1.0 by ShadOS
Приветствую всех. Вот зарелизил свой логклинер (видимо это традиция для большинства команд, в т.ч. и для HellKnights =)) с поддержкой регулярных выражений. Без тени скромности можно сказать что он один из лучших в своём роде, тем более в природе логклинеров с поддержкой Perl-совместимых регулярных выражений я не видел. Может чистить как бинарные так и текстовые логи. Пользутесь наздоровье. Жду отзывов и пожеланий по развитию проекта.
Скачать можно здесь: http://shados.0x48k.cc/releases/whitecat.c http://hellknights.void.ru/releases/0x48k-whitecat.c |
Молоток! Лог-клинер что надо :) Все работает как положено, но нашёлся один недостаток - в процессе своей работы программа создает гигантские временные файлы, и как получилось в моем случае, размер временного файла превысил максимально допустимый размер файла для ext2 - 2Gb, и программа получила SIGKILL, а временный файл остался. Это может привести например к тому, что логи могут быть вычищены неполностью(потому что whitecat немедленно завершается). Исходя из того что на большинстве Linux-серверов используется именно ext2 в качестве корневой ФС, предлагаю добавить функцию периодической проверки размера временного файла, и если размер временного файла превышает определенный допустимый размер (например 1 Gb) - то удалить все что уже не используется из этого файла(вычистить его), либо если какие-то данные из этого файла все еще нужны, то скинуть их в отдельный файл. Так клинер не превысит пределов на размер файла, и спокойно завершит все что ему положено. Ну или придумать что-нить помудрее :D
Прикладываю скрин, там то, что произошло при работе whitecat :) http://img254.imageshack.us/img254/8...2312rk6.th.jpg |
HaOS, молодец. Спасибо за тестирование (+++ даю) - обязательно что-нибудь придумаю. Если есть ещё предложения по совершенствованию - пиши, исправим! А исходный файл какого размера был? Какая там ФС для /var/log ? На скриншоте ничего не вижу.
|
Да. Логклинер тоже очень нам нужен! Но руткиты важнее.. Кстати он корректно работает под FreeBsd ???
|
Цитата:
|
Начнем с компилляции
In file included from whitecat.c:33: /usr/include/utmp.h:54: error: syntax error before "int32_t" /usr/include/utmp.h:63: error: syntax error before "int32_t" whitecat.c:38:21: lastlog.h: No such file or directory whitecat.c: In function `clear_uwbtmp': whitecat.c:247: error: structure has no member named `ut_user' whitecat.c:247: error: structure has no member named `ut_user' whitecat.c: In function `clear_lastlog': whitecat.c:289: error: structure has no member named `ll_time' Это 6.2-STABLE FreeBSD . Тут, как я понимаю, нету библиотеки. Но я могу ошибаться. |
Ok, значит на FreeBSD не так всё ажурно как в Linux. Но эти ошибки не проблема - исправим. Спасибо.
|
Цитата:
Цитата:
|
хм... странно получается. Если /var/log тоже на корневом разделе, то как там может поместиться исходный файл-лог больше чем допустимый размер файла? Временный файл должен быть аналогичен по размеру или меньше исходного. А исходники whitecat.c здесь непричём =) Протестируй ещё раз, пожалуйста, и посмотри размеры файлов предварительно. И ещё раз глянь внимательно в /etc/fstab.
|
Цитата:
Код:
root@HaPriS(21:25:03)/tmp # gcc -o whitecat whitecat.cЦитата:
Код:
root@HaPriS(21:43:04)/tmp # df -h /var/log |
это уже какие-то страные баги. жуть. Покажи размер логов после очистки.
|
Кое-что прояснилось, я совсем забыл про /var/log/messages. Он у меня был довольно внушительных размеров - 455 Мб, а старый файл вообще - 1.3 Gb (но этот лог клинер не затрагивал, этот файл хранился забэкапеным) :) Я как поставил систему, так до сих пор не удалял никаких логов. Общий размер /var/log был почти 2 гига :) Почистив этот файл(ну и за компанию половину ненужных логов столетней давности :)), все стало путем. Хотя в общем плане проблема не исчезла, проверять в ходе работы размер temp-файлов на ext2 фс, я думаю, все же стоит, потому что на сервере логи могут быть и побольше размером чем у меня в системе, а это значит что там может возникнуть такая же проблема.
|
Насчет фри. Я попробую на днях на 5 и 4 ветках, если получиться. И отпишусь еще.
|
Цитата:
|
Под BSD действительно не компилируется
Код:
whitecat.c:38:21: lastlog.h: No such file or directory |
Ошибку с размерами логов локализовал и исправил. Под FreeBSD тоже скоро готово будет. Ждите.
UPD: исправленная версия для GNU/Linux доступна по тем же ссылкам. Теперь всё работает отлично. Помимо этого незнаю зачем выложил бинарник: http://shados.0x48k.cc/releases/whitecat |
Все ошибки исправил. Теперь работать должно и под FreeBSD. Ссылки остаются прежними.
|
Все отлично заработало под фрю 6.2
Вычистил отлично. Респект. MustHave!!!! |
Я тут решил устроить нечно вроде опроса: надо ли добавлять возможность чистки других текстовых логов типа access.log Апача и т.п, ведь это можно и вручную сделать с помощью perl или того же grep? Отпишитесь, пожалуйста, все кому интересен проект действительно качественного логклинера для Linux/xBSD. Я лично не вижу смысла в чистке текстовых логов и вообще подумываю убить эту возможность из своего клинера, не unixway это.
|
Даже не вопрос. конечно интересует.
только сначало желательна совместимость, а потом уже функциональность... |
Цитата:
|
Упс..забыл кавычку:
#define _PATH_LASTLOG "/var/log/lastlog в старых системах без нее не компилится. Если хотите получить универсальный бинарник (чтоб не тратить время компиляцию) нужно собирать с наиболее древней Glibc, Т.к. если версия в системе старше, чем та с которой вы собирали бинарник, выдаст ошибку и попросит обновить. Цитата:
|
Цитата:
Насчёт текстовых логов - жду хотя-бы большинства ответов от интересующихся, нужно ли действительно это. |
Цитата:
|
Цитата:
Код:
cat /var/log/messages | grep -n <text_to_cleanup> > /var/log/messagesКод:
whitecat -u <text_to_cleanup> --textlog /var/log/messages |
Цитата:
Цитата:
Код:
cat /var/log/messages | grep -v <text_to_cleanup> > /var/log/messages |
Цитата:
|
Йоптель... уже на packetstormsecurity.nl:
http://packetstormsecurity.nl/UNIX/penetration/log-wipers/indexdate.html Только вот там версия немного устарела... |
Ещё актуально?
|
В OpenSolaris 2008.11 не компилируется:
Код:
alex@opensolaris:~$ gcc -o whitecat whitecat.c |
Жаль, но OpenSolaris этой версии нет под рукой. Нет возможости проверить, но уже вижу что исправляется всё банально + подключение нескольких библиотек + #ifdef по поводу солярки
|
Собственно, версия 1.1. Скорее всего баги есть, требуется отловить.
/* * This is WhiteCat logcleaner version 1.1 by ShadOS from Hell Knights Crew. * It supports perl compatible regular expressions and cleans any binary and * text log files (just correct source a little). WhiteCat is designed for * almost any (maybe) UNIX-like system. * Distributed under GPLv2. Use it only for educational purpose only. * Thanks to Ivan Sklyaroff for his articles. * Don't forget to visit our site and my homepage for new releases: * http://hellknights.void.ru * Also, you can mail me any bugs or suggestions: * mailto: shados /at/ real /dot/ xakep /dot/ ru * mailto: shados /at/ mail /dot/ ru * * * Copyright (C) 89, 90, 91, 1995-2007 Free Software Foundation. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ //#define SUNOS #define DEBUG #include <stdio.h> #include <sys/param.h> #include <stdint.h> #include <errno.h> #include <stdlib.h> #include <fcntl.h> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <pwd.h> #include <string.h> #include <regex.h> #include <limits.h> /* for PATH_MAX */ #include <getopt.h> #include <locale.h> #include <utmp.h> #ifdef SUNOS #include <utmpx.h> #include <lastlog.h> #endif /* SOLARIS */ #ifdef SUNOS #ifndef LASTLOG_FILE #define LASTLOG_FILE "/var/adm/lastlog" #endif #ifndef BTMPX_FILE #define BTMPX_FILE "/var/adm/btmpx" #endif #else /* Linux, FreeBSD */ #ifndef UTMP_FILE #ifndef _PATH_UTMP #define UTMP_FILE "/var/run/utmp" #else #define UTMP_FILE _PATH_UTMP #endif #endif #ifndef WTMP_FILE #ifndef _PATH_WTMP #define WTMP_FILE "/var/log/wtmp" #else #define WTMP_FILE _PATH_WTMP #endif #endif #ifndef LASTLOG_FILE #ifndef _PATH_LASTLOG #define LASTLOG_FILE "/var/log/lastlog" #else #define LASTLOG_FILE _PATH_LASTLOG #endif #endif #ifndef BTMP_FILE #ifndef _PATH_BTMP #define BTMP_FILE "/var/log/btmp" #else #define BTMP_FILE _PATH_BTMP #endif #endif #endif //modify parametrs as in your box ;) #define SECURE_FILE "/var/log/secure" #ifdef SUNOS #define SYSLOG_FILE "/var/log/syslog" #else #define SYSLOG_FILE "/var/log/messages" #endif #define MAXBUFF 8*1024 #define PROGRAM_NAME "WhiteCat logcleaner" #define PROGRAM_VERSION 1.1 #define PROGRAM_RELEASE 1 #define AUTHORS "Shad0S [Hell Knights Crew]" char *myname; /* for error messages */ int do_ignorecase = 0; /* -i option: ignore case */ int do_extended = 0; /* -E option: use extended RE's */ int do_username = 0; int do_hostname = 0; int do_tty = 0; int errors = 0; /* number of errors */ /* patterns to match */ regex_t username; regex_t hostname; regex_t tty; int copy_tmp(char *dstfilename, char *tmpfilename); int clear_textlog(char *filename); int clear_uwbtmp(char *filename); int clear_lastlog (char *filename); regex_t compile_pattern(const char *pat); int process_regexp(regex_t *pattern, char *buf, size_t size); char *xgethostname(void); void usage(void); void version(void); int main(int argc, char *argv[]) { myname = argv[0]; char c; struct stat statbuf; //buffer for stat() /* i18n */ //setlocale (LC_ALL, ""); //struct lconv l = *localeconv(); //l.decimal_point = "."; struct option longopts[]={ { "user", required_argument, &do_username, 'u'}, { "tty", required_argument, &do_tty, 't'}, { "hostname", required_argument, &do_hostname, 'a'}, { "extended", no_argument, &do_extended, 'e'}, { "ignore", no_argument, &do_ignorecase, 'i'}, { "help", no_argument, NULL, 'h'}, { "version", no_argument, NULL, 'V'}, { 0, 0, 0, 0 } }; if ((argc < 2) || (argc > 18)) { version(); usage(); } while ((c=getopt_long(argc,argv,"u:t:a:reihVW;",longopts ,NULL)) != -1) { switch (c) { case 'u': username = compile_pattern(optarg); if (errors) usage(); //compile failed do_username=1; break; case 't': tty = compile_pattern(optarg); if (errors) usage(); //compile failed do_tty=1; break; case 'a': hostname = compile_pattern(optarg); if (errors) usage(); //compile failed do_hostname=1; break; case 'e': do_extended = 1; break; case 'i': do_ignorecase = 1; break; case 'h': version(); usage(); case 'V': version(); exit(0); break; case 0: break; case ':': fprintf(stderr, "%s: option '-%c' requires an argument\n", myname, optopt); usage(); case '?': default: fprintf(stderr, "%s: option '-%c' is invalid\n", myname, optopt); usage(); } } //sanity check if (!do_username && !do_tty && !do_hostname){ fprintf(stderr, "%s: did not found any parametr to clean (username, hostname, tty)!\n", myname); usage(); } version(); #ifdef SUNOS if (!clear_uwbtmp(UTMPX_FILE)) printf("\033[1mutmp cleaning \t\t\t\t\t\t\t \033[32;1m[ OK ] \033[0m\n"); else printf("\033[1mutmp cleaning \t\t\t\t\t\t\t \033[31;1m[ Failed ] \033[0m\n"); if (!clear_uwbtmp(WTMPX_FILE)) printf("\033[1mwtmp cleaning \t\t\t\t\t\t\t \033[32;1m[ OK ] \033[0m\n"); else printf("\033[1mwtmp cleaning \t\t\t\t\t\t\t \033[31;1m[ Failed ] \033[0m\n"); /* we able to get file attributes, so BTMPX_FILE obviously exists */ if (stat(BTMPX_FILE, &statbuf) == 0) if (!clear_uwbtmp(BTMPX_FILE)) printf("\033[1mbtmp cleaning \t\t\t\t\t\t\t \033[32;1m[ OK ] \033[0m\n"); else printf("\033[1mbtmp cleaning \t\t\t\t\t\t \033[31;1m[ Failed ] \033[0m\n"); #else if (!clear_uwbtmp(UTMP_FILE)) printf("\033[1mutmp cleaning \t\t\t\t\t\t\t \033[32;1m[ OK ] \033[0m\n"); else printf("\033[1mutmp cleaning \t\t\t\t\t\t\t \033[31;1m[ Failed ] \033[0m\n"); if (!clear_uwbtmp(WTMP_FILE)) printf("\033[1mwtmp cleaning \t\t\t\t\t\t\t \033[32;1m[ OK ] \033[0m\n"); else printf("\033[1mwtmp cleaning \t\t\t\t\t\t\t \033[31;1m[ Failed ] \033[0m\n"); /* we able to get file attributes, so BTMP_FILE obviously exists */ if (stat(BTMP_FILE, &statbuf) == 0) if (!clear_uwbtmp(BTMP_FILE)) printf("\033[1mbtmp cleaning \t\t\t\t\t\t\t \033[32;1m[ OK ] \033[0m\n"); else printf("\033[1mbtmp cleaning \t\t\t\t\t\t \033[31;1m[ Failed ] \033[0m\n"); #endif if (!clear_lastlog(LASTLOG_FILE)) printf("\033[1mlastlog cleaning \t\t\t\t\t\t \033[32;1m[ OK ] \033[0m\n"); else printf("\033[1mlastlog cleaning \t\t\t\t\t\t \033[31;1m[ Failed ] \033[0m\n"); if (!clear_textlog(SYSLOG_FILE)) printf("\033[1msyslog cleaning \t\t\t\t\t\t \033[32;1m[ OK ] \033[0m\n"); else printf("\033[1msyslog cleaning \t\t\t\t\t\t \033[31;1m[ Failed ] \033[0m\n"); if (stat(SECURE_FILE, &statbuf) == 0) //we able to get file attributes, so SECURE_FILE obviously exists if (!clear_textlog(SECURE_FILE)) printf("\033[1msecure cleaning \t\t\t\t\t\t \033[32;1m[ OK ] \033[0m\n"); else printf("\033[1msecure cleaning \t\t\t\t\t\t \033[31;1m[ Failed ] \033[0m\n"); return 0; } /* replace logfile with tempfile */ int copy_tmp(char *dstfilename, char *tmpfilename) { char buffer[BUFSIZ]; sprintf(buffer, "cat %s > %s", tmpfilename, dstfilename); #ifdef DEBUG printf("%s\n", buffer); #endif if (system(buffer) < 0) { printf("Error copying from tempfile!"); return 0x48; } //unlink(tmpfilename); } /* cleanup plaintext logfiles */ int clear_textlog(char *filename) { char buftmp[MAXBUFF]; FILE *fd; int fdtmp; int found = 0; int errors = 0; ssize_t rcnt, wcnt; static char template[] = "tmpfileXXXXXX"; char ftmpname[PATH_MAX]; char *localhostname; char *tmpdir; if (do_username) if ((localhostname = xgethostname()) == NULL) { fprintf(stderr, "%s: could not determine hostname: %s\n", myname, strerror(errno)); return 0x48; } else { if (process_regexp(&username, localhostname, strlen(localhostname))) fprintf(stdout, "%s: warning: local hostname (%s) is like the username string!\n", myname, localhostname, username); } if ((fd = fopen(filename, "r")) == 0) { fprintf(stderr, "%s: %s: could not open: %s\n", myname, filename, strerror(errno)); return 0x48; } //get TMPDIR value, else use "/tmp" if ((tmpdir = getenv("TMPDIR")) == NULL) tmpdir = "/tmp"; sprintf(ftmpname, "%s/%s", tmpdir, template); if ((fdtmp = mkstemp(ftmpname)) == -1) { fprintf(stderr, "%s: %s: could not create temp file: %s\n", myname, filename, strerror(errno)); return 0x48; } //while ((rcnt = getline(&buftmp, &rcnt, fd)) != -1) while (fgets(buftmp, MAXBUFF, fd) != NULL) { //length of null-terminated string rcnt = strlen(buftmp); if (do_hostname) found = process_regexp(&hostname, buftmp, rcnt); if (do_username) found = process_regexp(&username, buftmp, rcnt); if (do_tty) found = process_regexp(&tty, buftmp, rcnt); if (!found) { wcnt = write(fdtmp, buftmp, rcnt); if (wcnt != rcnt) { fprintf(stderr, "%s: %s: write error: %s\n", myname, ftmpname, strerror(errno)); errors++; break; } } found = 0; } if ((rcnt < 0) && (errno != EXIT_SUCCESS)) { fprintf(stderr, "%s: %s: read error: %s\n", myname, filename, strerror(errno)); errors++; } if (fd != 0) { if (fclose(fd) < 0) { fprintf(stderr, "%s: %s: close error: %s\n", myname, filename, strerror(errno)); errors++; } } if (fdtmp != 0) { if (close(fdtmp) < 0) { fprintf(stderr, "%s: %s: close error: %s\n", myname, ftmpname, strerror(errno)); errors++; } } copy_tmp(filename, ftmpname); return (errors != 0); } /* cleanup binary log entries */ int clear_uwbtmp(char *filename) { #ifndef SUNOS struct utmp entry; #else struct utmpx entry; #endif int fd; int fdtmp; int found = 0; int errors = 0; ssize_t rcnt, wcnt; static char template[] = "tmpfileXXXXXX"; char ftmpname[PATH_MAX]; char *tmpdir; if ((fd = open(filename, O_RDONLY)) == -1) { fprintf(stderr, "%s: %s: could not open: %s\n", myname, filename, strerror(errno)); return 0x48; } //get TMPDIR value, else use "/tmp" if ((tmpdir = getenv("TMPDIR")) == NULL) tmpdir = "/tmp"; sprintf(ftmpname, "%s/%s", tmpdir, template); if ((fdtmp = mkstemp(ftmpname)) == -1) { fprintf(stderr, "%s: %s: could not create temp file: %s\n", myname, filename, strerror(errno)); return 0x48; } while ((rcnt = read(fd, &entry, sizeof(struct utmp))) > 0) { #ifdef DEBUG printf("line: %s\n", entry.ut_line); printf("host: %s\n", entry.ut_host); printf("name: %s\n", entry.ut_name); #endif if (do_hostname) found = process_regexp(&hostname, entry.ut_host, sizeof(entry.ut_host)); if (do_username) found = process_regexp(&username, entry.ut_name, sizeof(entry.ut_name)); if (do_tty) found = process_regexp(&tty, entry.ut_line, sizeof(entry.ut_line)); if (!found) { wcnt = write(fdtmp, &entry, sizeof(struct utmp)); if (wcnt != rcnt) { fprintf(stderr, "%s: %s: write error: %s\n", myname, ftmpname, strerror(errno)); errors++; break; } } found = 0; } if (rcnt < 0) { fprintf(stderr, "%s: %s: read error: %s\n", myname, filename, strerror(errno)); errors++; } if (fd != 0) { if (close(fd) < 0) { fprintf(stderr, "%s: %s: close error: %s\n", myname, filename, strerror(errno)); errors++; } } if (fdtmp != 0) { if (close(fdtmp) < 0) { fprintf(stderr, "%s: %s: close error: %s\n", myname, ftmpname, strerror(errno)); errors++; } } copy_tmp(filename, ftmpname); return (errors != 0); } /* cleanup lastlog binary file with holes */ int clear_lastlog (char *filename) { struct passwd *pwd; struct lastlog entry; int uid = 0; int found = 0; int errors = 0; int fd; ssize_t rcnt, wcnt; if ((fd = open(filename, O_RDWR)) < 0) { fprintf(stderr, "%s: %s: could not open: %s\n", myname, filename, strerror(errno)); return 0x48; } /* set position to the beginning of the file */ if (lseek(fd, (off_t)0, SEEK_SET) == (off_t)-1) { fprintf(stderr, "%s: %s: could not set position in file: %s\n", myname, filename, strerror(errno)); return 0x48; } while ((rcnt = read(fd, &entry, sizeof(struct lastlog))) > 0) { if (do_username) { if ((pwd = getpwuid(uid)) != NULL) found = process_regexp(&username, pwd->pw_name, sizeof(pwd->pw_name)); uid++; } if (do_hostname) found = process_regexp(&hostname, entry.ll_host, sizeof(entry.ll_host)); if (do_tty) found = process_regexp(&tty, entry.ll_line, sizeof(entry.ll_line)); if (found) { //XXX is this correct? bzero(&entry, sizeof(struct lastlog)); found = 0; } if (lseek(fd, -(off_t)rcnt, SEEK_CUR) == (off_t)-1) { fprintf(stderr, "%s: %s: could not set position in file: %s\n", myname, filename, strerror(errno)); return 0x48; } wcnt = write(fd, &entry, sizeof(struct lastlog)); if (wcnt != rcnt) { fprintf(stderr, "%s: %s: write error: %s\n", myname, filename, strerror(errno)); errors++; break; } } if (rcnt < 0) { fprintf(stderr, "%s: %s: read error: %s\n", myname, filename, strerror(errno)); errors++; } if (fd != 0) { if (close(fd) < 0) { fprintf(stderr, "%s: %s: close error: %s\n", myname, filename, strerror(errno)); errors++; } } return (errors != 0); } /* compile the regex pattern */ regex_t compile_pattern(const char *pat) { int flags = REG_NOSUB; /* don't need where-matched info */ int ret; regex_t pattern; #define MSGBUFSIZE 512 /* arbitrary */ char error[MSGBUFSIZE]; if (do_ignorecase) flags |= REG_ICASE; if (do_extended) flags |= REG_EXTENDED; ret = regcomp(&pattern, pat, flags); if (ret != 0) { (void) regerror(ret, &pattern, error, sizeof error); fprintf(stderr, "%s: pattern `%s': %s\n", myname, pat, error); errors++; } else return pattern; } /* process regular expression */ int process_regexp(regex_t *pattern, char *buf, size_t size) { char error[MSGBUFSIZE]; int ret; if ((ret = regexec(pattern, buf, 0, NULL, 0)) != 0) { if (ret != REG_NOMATCH) { (void) regerror(ret, pattern, error, sizeof error); fprintf(stderr, "%s: %s\n", myname, error); errors++; return 0; } return 0; } else return 1; } #ifndef INITIAL_HOSTNAME_LENGTH # define INITIAL_HOSTNAME_LENGTH 34 #endif /* Return the current hostname in malloc'd storage. If malloc fails, exit. Upon any other failure, return NULL and set errno. */ char *xgethostname(void) { char *hostname = NULL; size_t size = INITIAL_HOSTNAME_LENGTH; while(1) { /* Use SIZE_1 here rather than SIZE to work around the bug in SunOS 5.5's gethostname whereby it NUL-terminates HOSTNAME even when the name is as long as the supplied buffer. */ size_t size_1; hostname = realloc(hostname, size); size_1 = size - 1; hostname[size_1 - 1] = '\0'; errno = 0; if (gethostname(hostname, size_1) == 0) { if (!hostname[size_1 - 1]) break; } else if (errno != 0 && errno != ENAMETOOLONG && errno != EINVAL /* OSX/Darwin does this when the buffer is not large enough */ && errno != ENOMEM) { int saved_errno = errno; free(hostname); errno = saved_errno; return NULL; } } return hostname; } /* print usage message and exit with 0x48k status */ void usage(void) { printf("Usage:\n"); printf("\t %s [-u user] [-t tty] [-a hostname|ipaddr] [OPTIONS]\n", myname); printf("OPTIONS:\n"); printf("\t -i --ignore \t ignore case in regexps\n"); printf("\t -e --extended \t use extended regexps\n"); printf("\t -V --version \t show version info and exit\n"); printf("\t -h --help \t show this help screen and exit\n"); printf("\n"); exit(0x48); } /* print version information */ void version(void) { fprintf(stdout, "\t ================================================== =====================\n"); fprintf(stdout, "\t = \033[1m%s %1.1f.%d by %s, 2007-2009.\033[0m =\n", PROGRAM_NAME, PROGRAM_VERSION, PROGRAM_RELEASE, AUTHORS); fprintf(stdout, "\t ================================================== =====================\n"); } |
+10 первому нашедшему косяк с подробным описанием.
|
у меня какой-то косяк творится,не запустить + инет не пашет.
Помогает восстановление, но меня насторожило, что это уже 2-й раз происходит. |
Цитата:
|
Цитата:
|
щас затестил на
Цитата:
кстате, версия 1,0 даже не скопелилась... |
Цитата:
Что самое интересное - Log никаких логов нет, пусто! :( |
Цитата:
Код:
#ifndef _PATH_LASTLOG |
млять... тестируем версию 1.1!
|
| Время: 03:35 |