Показаны сообщения с ярлыком debian. Показать все сообщения
Показаны сообщения с ярлыком debian. Показать все сообщения

среда, 5 мая 2021 г.

Конфигурирование связки SPF, DKIM, DMARC записей и sendmail на debian

    Что такое SPF, DKIM, DMARC объяснять не буду. Раз вы это читаете, то вы уже знаете, что это или хотя бы зачем. Тут просто расскажу как я это установил на debian buster c почтовым сервером sendmail. 

#apt install opendkim opendkim-tools

#vim /etc/opendkim.conf

Syslog                         yes
SyslogSuccess            Yes
LogWhy                      Yes
AutoRestart                Yes
AutoRestartRate        10/1h
UMask                        002
Canonicalization        relaxed/simple
Mode                          sv
Socket                        inet:8891@127.0.0.1
PidFile                       /var/run/opendkim/opendkim.pid
SignatureAlgorithm   rsa-sha256
UserID                       opendkim:opendkim
Domain                       my.domain.ua
Selector                      mymail

OversignHeaders       From
TrustAnchorFile         /usr/share/dns/root.key
ExternalIgnoreList     refile:/etc/opendkim/TrustedHosts
InternalHosts             refile:/etc/opendkim/TrustedHosts
KeyTable                     refile:/etc/opendkim/KeyTable

SigningTable               refile:/etc/opendkim/SigningTable

Обратите внимание на пять строчек, выделенных жирным шрифтом. Их понимание, на мое мнение, особенно важно для того, что мы хотим сделать.

вместо my.domain.ua подставим вывод команды  (на почовом сервере)

#hostname -d

вместо mymail подставим вывод команды (также на почтовике) 

#hostname 

Далее создаем директорию, где находится пара приватный-публичный ключи:

#mkdir -p /etc/opendkim/keys

И создаем собственно эти ключи:

#opendkim-genkey -D /etc/opendkim/keys -d my.domain.ua  -s mymail
#chown -R opendkim:opendkim /etc/opendkim/keys
#chmod 640 /etc/opendkim/keys/mymail.private
#chmod 644 /etc/opendkim/keys/mymail.txt

mymail.private - здесь хранится приватный ключ, доступ к которому имеет только почтовый демон (в нашем случае - сендмейл).
mymail.txt - здесь хранится публичный ключ, который мы впишем в файл зоны днс.
    Далее создаем и редактируем три таких файла:

#vim /etc/opendkim/KeyTable

mymail._domainkey.my.domain.ua my.domain.ua:mymail:/etc/opendkim/keys/mymail.private
Здесь мы говорим мы говорим мильтеру opendkim, а значит сендмейлу, где находится приватный ключ.

#vim /etc/opendkim/SigningTable

*@my.domain.ua mymail._domainkey.my.domain.ua
Здесь мы говорим какие почтовые адреса соответствуют dkim-записи в днс.

#vim /etc/opendkim/TrustedHosts

127.0.0.1
localhost
my.domain.ua
Тут имя файла говорит само за себя.
 
    Рестартуем опендким и смотрим, слушает ли он порт, что мы прописали в конфиге выше:
#systemctl restart opendkim
#netstat -nlp | grep 8891
tcp        0      0 127.0.0.1:8891          0.0.0.0:*               LISTEN      23116/opendkim

    Расскажем сендмейлу, что у него появился новый мильтер (о мильтере можно думать как о некоем плагине, который подсоединяется к главному процессу сендмейла с помощью специального API - milter API). Редактируем текстовый конфиг сендмейла:
#vim /etc/mail/sendmail.mc
...

INPUT_MAIL_FILTER(`milter1', `...')dnl
INPUT_MAIL_FILTER(`milter2', `...')dnl
INPUT_MAIL_FILTER(`opendkim', `S=inet:8891@127.0.0.1')dnl
define(`confINPUT_MAIL_FILTERS',`opendkim,milter1,milter2')dnl
...

milter1 и milter2 вписаны для примера. Их может и не быть или может быть больше двух. У меня, например, к сендмейлу подсоединены два мильтера кламава и спамассассина. Третий стало быть опендким. Обратите внимание на `S=inet:8891@127.0.0.1' - эта запись должна совпадать с тем, что мы прописали в конфиге выше.

Выполняем

#sendmailconfig
#systemctl restart sendmail 

Осталось отконфигурировать файл прямой зоны авторитетного днс для домена, который обслуживает наш почтовый сервер:

$ORIGIN         my.domain.ua.
@                     IN SOA  mydns.my.domain.ua. hostm.my.domain.ua. ( ... )
                        IN      NS      mydns.my.domain.ua.
                        IN      MX      10 mymail.my.domain.ua.
@                     IN      TXT     "v=spf1 +mx +a ip4:11.11.11.11 -all"
mymail._domainkey        IN    TXT    "v=DKIM1\; h=sha256\; k=rsa\; p=""xxxx""xxxx""xxxx""xxxx" 
_adsp._domainkey        IN    TXT    "dkim=all"
_dmarc                        IN    TXT    "v=DMARC1\; p=reject\; rua=mailto:hostm@my.domain.ua"

    11.11.11.11 - айпишник нашего почтовика. Строка

mymail._domainkey        IN      TXT     "v=DKIM1\; h=sha256\; k=rsa\; p=""xxxx""xxxx""xxxx""xxxx"

полностью соответствует содержимому файла mymail.txt, что мы создали ранее. ххххххх - так обозначены цифры ключа. Есть пара нюансов. Точки с запятой в файле днс соответствуют началу комментариев. Поэтому мы их экранируем слэшем. Также, строки в файле зоны днс не могут быть длиннее кажется 256 символов, что меньше, чем длина нашей строки (строка, что начинается из v= ), из-за чего эту длинную строку надо разбить несколькими вставками "" - они обозначены синим цветом. Также длинные строки можно заключать в круглые скобки, но у меня почему-то это не работало.

    Строка с v=spf1 и есть spf запись. Строка с v=DKIM1 и есть dkim запись. Строка с v=DMARC1 и есть dmarc запись. Две строки, начинающиеся с _adsp и _dmarc просят всех не принимать письма без DKIM-подписи нашего домена. Собственно для этого все это и затевалось.

    Теперь при отсылке почты в логах почтовика появяться соответствующие строки:

# journalctl -u opendkim

DKIM-Signature field added (s=mymail, d=my.domain.ua)

    Также в служебной информации писем появяться DKIM-подписи вашего домена.

    Я б рекомендовал бы вот эту ссылку , которая была основой данного изложения, но надеюсь, здесь все написано достаточно точно.

воскресенье, 17 января 2021 г.

Sendmail: анализ логов

    Отчаявшись найти хотя б даже и неинтуитивный анализатор логов почтового сервера на Sendmail и Dovecot, пришлось осилить несколько строк командной оболочки. Дело было в Дебиан.

#journalctl --since yesterday -u sendmail|grep ctladdr|grep Sent|awk -F: '{print $5}'|grep -Po 'ctladdr=<\K[^>]*' 

Это смотрим отправщиков писем.

#ls -al /var/mail/|awk '{printf("%-20s%s\n", $3,$5)}'

Это анализируем почтовые ящики.

#journalctl -u dovecot|grep pop3-login|egrep -v Disconnected|awk -F, '{print $1}'|awk -v RS='<' -v FS='>' 'NR>1{print $1}'

Это анализируем читателей писем.


sort|uniq -c|sort -nk1 такое добавляем в конец пайпа для сортировки вывода по числам в первом столбце.

awk '{sum+=$2} END {print $2}' такого типа команду добавляем в конец пайпа, чтоб просуммировать числа во втором столбце.

Ну и напоследок формат по умолчанию записи в журнал сендмейлом в случае если отсылка мыла произошла успешно (схематично):

Date Time MyServerName sm-mta[x]: 10HF0kYP020730: from=<g@g.org>, size=x, class=0, nrcpts=1, msgid=<xxx>, proto=ESMTPSA, daemon=MTA, relay=server.domen [x.x.x.x]
Date Time MeServerName sm-mta[x]: 10HF0kYP020730: to=<g2@g2.org>, ctladdr=<g@g.org> (1254/1498), delay=00:00:02, xdelay=00:00:02, mailer=esmtp, pri=120563, relay=x.net. [x.x.x.x], dsn=2.0.0, stat=Sent (ok dirdel)



 

 

воскресенье, 13 декабря 2020 г.

Основные команды для работы с пакетами в Debian

  • dpkg -i пакет.deb проинсаллировать пакет
  • dpkg -r пакет (без расширения  deb) удалить пакет, исключая файлы конфигурации
  • dpkg -P пакет (без расширения  deb)полностью удалить пакет
  • dpkg -l список всех проинсталлированных пакетов
  • dpkg -l пакет (без расширения  deb) вывод короткой информации про отдельный пакет
  • dpkg -L (без расширения  deb) вывод всех файлов проинсталлированных из данного пакета
  • dpkg -c пакет.deb список файлов в еще непроинсталлированном пакете
  • dpkg -S /path/to/file показывает какому пакету принадлежит файл
  • dpkg -p пакет (без расширения  deb) вывод детальной информации про отдельный пакет
  • dpkg -s пакет (без расширения  deb) проверяет, установлен ли пакет

суббота, 11 октября 2014 г.

Установка googleearth на debian

Чтобы проинсталлировать googleearth на Дебиане  не нужно идти на сайт гугла, загружать пакет googleearth и инсталлировать его командой dpkg. Нужно делать следующее. Выполняем в командной оболочке под администраторской учетной записью: 
#apt-get install googleearth-package
Потом из учетной записи обычного пользователя делаем: 
#make-google-earth-package
В текущей директории появляется пакет googleearth*.deb, который и устанавливаем командой:  
#dpkg -i googleearth*.deb

среда, 9 января 2013 г.

Установка сетевого принтера в Debian GNU/Linux 7.0 (wheezy)

После установки (в моем случае) Debian wheezy штатные утилиты гнома почему-то не устанавливали (а, возможно, и не должны) сетевого принтера. Но это не есть большой трудностью. Достаточно доустановить пакет system-config-printer. И после запуска кочанды system-config-printer из-под администратора легко найти и подсоединить принтер

пятница, 4 января 2013 г.

Два монитора на компьютере с Debian

Хорошо, если у нас есть ноутбук с Debian wheezy. А что если у нас есть второй монитор и мы хотим его подсоединить к нашему ноутбуку? В моем случае второй монитор подсоединился автоматически, но при этом не только на нем вывод был с плохой разрешающей способностью, но и на экране самого ноутбука качество изображения изменилось не вbлучшую сторону. Вобщем встал вопрос: как "правильно" подсоединить второй монитор к нашему ноутбуку? Выполним программу xandr:
#xrandr
В моем случае вывод был такой:
Screen 0: minimum 320 x 200, current 1920 x 1080, maximum 8192 x 8192
LVDS1 connected (normal left inverted right x axis y axis)
   1366x768       60.0 +
   1360x768       59.8     60.0  
   1024x768       60.0  
   800x600        60.3     56.2  
   640x480        59.9  
VGA1 connected 1920x1080+0+0 (normal left inverted right x axis y axis) 509mm x 286mm
   1920x1080      60.0*+
   1280x1024      75.0     60.0  
   1152x864       75.0  
   1024x768       75.1     60.0  
   800x600        75.0     60.3  
   640x480        75.0     60.0  
   720x400        70.1  
HDMI1 disconnected (normal left inverted right x axis y axis)
DP1 disconnected (normal left inverted right x axis y axis)
Достаточно прозрачный вывод. Если выполнить программу xrandr со следующими параметрами (их значения выбираем из вывода предыдущей команды):
#xrandr --output VGA1 --mode 1920x1080 --output LVDS1 --off
то графический вывод будет осуществляться только на присоединенный монитор. Если выполнить команду:
#xrandr --output VGA1 --off --output LVDS1 --mode 1366x768 --pos 0x0
то вывод будет выполняться только на экран ноутбука. Общая идея понятна. Теперь мы хотим следующее. При включении компьютера, если подсоединен второй монитор, нам надо, чтобы включался только этот второй моитор. Если второго монитора нет, то пусть включается только (а что ж еще?) монито ноутбука. Дя этого создаем файл /etc/X11/Xsession.d/45custom_xrandr со следующим содержанием (он запускается при запуске иксов):
xrandr | grep VGA1 | grep " connected "
if [$? -eq 0]; then
      # Внешний монитор отключен
      # Если мы хотим два показывающих монитора
      # xrandr --output VGA1 --mode 1920x1080 --pos 0x0 --output LVDS1 --mode 1366x768 --pos 0x0
      # Если мы хотим включенный только внешний монитор
      xrandr --output VGA1 --mode 1920x1080 --output LVDS1 --off
      if [$? -ne 0]; then
           # Если что-то не так
           xrandr --output LVDS1 --mode auto --output VGA1 --off
      fi
else
      # Внешний монитор не подключен
      xrandr --output LVDS1 --mode 1366x768 --output VGA --off
fi
Вот и все. Написано по материалам, взятым отсюда.

воскресенье, 1 мая 2011 г.

Инсталляция драйвера NVIDIA в debian Squeeze

Для начала идем на http://packages.debian.org/ и выкачиваем следующие non-free пакеты:

nvidia-xconfig_*.deb
nvidia-libvdpau1_*.deb
nvidia-kernel-source_*.deb
nvidia-kernel-*.deb
nvidia-glx_*.deb
libglx-nvidia-alternatives_*.deb
libgl1-nvidia-glx_*.deb
libgl1-nvidia-alternatives_*.deb

Делаем им всем dpkg -i.
Либо добаляем в соответствующее место файла /etc/apt/sources.list слово non-free и делаем этим пакетам apt-get install.
Потом так:

# apt-get update
# apt-get install module-assistant nvidia-kernel-common build-essential nvidia-settings
# m-a clean nvidia-kernel-source
# m-a purge nvidia-kernel-source
# m-a prepare
# m-a a-i nvidia-kernel-source
# nvidia-xconfig

перезагружаемся и имеем что хотели.

воскресенье, 20 марта 2011 г.

Рекомендуемые для бэкапа директории и файлы в Debian

Кроме собственно ваших рабочих файлов, будет черезвычайно полезно держать в безопасном месте содержимое следующих директорий:
/etc
/var/lib/dpkg

Также необходимо сохранить файл:
/var/lib/apt/extended_states
и вывод команды dpkg --get-selections "*"
если используется aptitude, то сохраняем и файл /var/lib/aptitude/pkgstates
Пакеты, которые установлены в системе хранятся в /var/cache/apt/archives/
Файлы нужныйе для работы apt-file лежат в /var/cache/apt/apt-file

воскресенье, 21 ноября 2010 г.

Сцены OpenGL в виджетах GTK

Весь интернет пестрит примерами использования OpenGL. Найти их не сложно. OpenGL сам по себе является кроссплатформенным. А поэтому, чтобы создать сцену OpenGL вам нужно знать только сам OpenGL. А вот когда сама сцена создана, встает вопрос - и куда мы эту сцену будем "запихивать"? Вот тут-то и всплывает "однобокость" этого великого разнообразия примеров OpenGL: они демонстрируют создание упомянутых сцен в одном единственном окне, окне библиотеки GLUT. Эта библиотека, как я понял, и была создана всего-навсего для написания "образовательных" и демонстрационных целей. И эти цели она выполнила и даже перевыполнила. Также к ее плюсам можно добавить ее кроссплатформенность. Ее реализиция есть и для систем UNIX и для Windows. Но ведь сцены OpenGL не являются необходимыми "сами по себе". Понятно же, что приложение, которое представляет из себя одно единственное окно с ,пусть с даже очень впечатляющим и красивым, двух- или трех- мерным изображением, вряд ли представит из себя какой-либо интерес, кроме, как мы уже указали, демонстрационного.
Здесь мы рассмотрим как вставить сцену OpenGL в виджет GTK. Интерфейс любого приложения GTK является набором, комбинацией так-называемых виджетов, размещенных, как укажет программист, на окнах приложения. Четкого определения, что такое виджет нет, из-за того, что это очень общее, объемное, понятие. Причем его "общность" истинна, так как на самом деле понять, что такое виджет совсем просто. Сложнее рассказать. Виджет - это "нечто", что можно отобразить на эране, окне приложения, диалоге. Любая кнопка, элемент управления, некая область, которая четко отделена и распознаваема от остальной части дилога, окна и есть виджет. Виджет GTK- это просто некий тип, структура GtkWidget.
Вот мы и подобрались вплотную к основной теме. Рассмотрим два виджета, которые позволяют рисовать сцены OpenGL в себя. Эти виджеты: gtkglarea и gtkglext. Имеются их реализации в виде пакетов для. самых распространенных по-крайней мере, дистрибутивов Linux. Также есть их порты для FreeBSD, что заставляет меня предполагать, что они есть для всех систем BSD.
Рассмотрим сначала gtkglarea.
Создаем файл gtkglarea_demo.c следующего содержания (вообще-то это совсем немного измененный для собственных нужд файл взятый отсюда):


#include <GL/gl.h>
#include <GL/glu.h>
#include <gtk/gtk.h>
#include <gtkgl/gtkglarea.h>

gint glarea_button_press (GtkWidget*, GdkEventButton*);
gint glarea_draw (GtkWidget*, GdkEventExpose*);
gint glarea_reshape (GtkWidget*, GdkEventConfigure*);
gint glarea_init (GtkWidget*);
gint glarea_destroy (GtkWidget*);
int main (int, char**);

gint
glarea_button_press (GtkWidget* widget, GdkEventButton* event) {
int x = event->x;
int y = event->y;
if (event->button == 1) {
g_print ("Button 1 press (%d, %d)\n", x, y);
return TRUE;
}
if (event->button == 2) {
g_print ("Button 1 press (%d, %d)\n", x, y);
return TRUE;
}
return FALSE;
}

gint
glarea_draw (GtkWidget* widget, GdkEventExpose* event) {
if (event->count > 0) {
return(TRUE);
}
g_print ("Expose Event\n");
if (gtk_gl_area_make_current(GTK_GL_AREA(widget))) {
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
/* */
/* Insert your drawing code here. */
/* */
gtk_gl_area_swapbuffers (GTK_GL_AREA(widget));
}
return (TRUE);
}

gint
glarea_reshape (GtkWidget* widget, GdkEventConfigure* event) {
int w = widget->allocation.width;
int h = widget->allocation.height;
g_print ("Reshape Event\n");
if (gtk_gl_area_make_current (GTK_GL_AREA(widget))) {
/* This is an example 2D reshape function. Writing reshape */
/* functions is beyond the scope of this demo. Check the */
/* red book or the www.opengl.org for more information on */
/* how to write reshape code to suit your needs. */
glViewport (0, 0, w, h);
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
gluOrtho2D (-(w>>1), (w>>1), -(h>>1), h>>1);
glMatrixMode (GL_MODELVIEW);
}
return (TRUE);
}

gint
glarea_init (GtkWidget* widget) {
g_print ("Realize Event\n");
if (gtk_gl_area_make_current (GTK_GL_AREA(widget))) {
/* Insert your OpenGL initialization code here */
}
return TRUE;
}

gint
glarea_destroy (GtkWidget* widget) {
g_print ("GTK GL Area Destroy Event\n");
/* Insert any required cleanup */
/* code here. */
return TRUE;
}

int
main (int argc, char** argv) {
GtkWidget* window;
GtkWidget* button_quit;
GtkWidget* box_main;
GtkWidget* glarea;
/* These attributes are passed to glXChooseVisual by the */
/* gdk (see gdk_gl_choose_visual in gdkgl.c from the GtkGlarea distro). */
int attrlist[] = {
GDK_GL_RGBA,
GDK_GL_DOUBLEBUFFER,
GDK_GL_DEPTH_SIZE, 1,
GDK_GL_NONE
};
gtk_init (&argc, &argv);
if(gdk_gl_query() == FALSE) {
g_print("OpenGL not supported!\n");
return (1);
}

window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_title (GTK_WINDOW(window), "GtkGLArea Demo For Blogger");
gtk_quit_add_destroy (1, GTK_OBJECT(window));
gtk_signal_connect (GTK_OBJECT(window), "delete_event", GTK_SIGNAL_FUNC(gtk_main_quit), NULL);
gtk_signal_connect (GTK_OBJECT (window), "destroy", GTK_SIGNAL_FUNC(gtk_main_quit), NULL);
gtk_container_set_border_width (GTK_CONTAINER(window), 10);
gtk_widget_show (window);

box_main = gtk_vbox_new (FALSE, 10);
gtk_container_add (GTK_CONTAINER(window), box_main);
gtk_widget_show (box_main);

glarea = gtk_gl_area_new(attrlist);
gtk_widget_set_events(GTK_WIDGET(glarea),
GDK_EXPOSURE_MASK|
GDK_BUTTON_PRESS_MASK);
gtk_signal_connect (GTK_OBJECT(glarea), "button_press_event", GTK_SIGNAL_FUNC(glarea_button_press), NULL);
gtk_signal_connect (GTK_OBJECT(glarea), "expose_event", GTK_SIGNAL_FUNC(glarea_draw), NULL);
gtk_signal_connect (GTK_OBJECT(glarea), "configure_event", GTK_SIGNAL_FUNC(glarea_reshape), NULL);
gtk_signal_connect (GTK_OBJECT(glarea), "realize", GTK_SIGNAL_FUNC(glarea_init), NULL);
gtk_signal_connect (GTK_OBJECT(glarea), "destroy", GTK_SIGNAL_FUNC (glarea_destroy), NULL);
gtk_widget_set_usize(GTK_WIDGET(glarea), 256, 256);
gtk_box_pack_start (GTK_BOX(box_main), glarea, FALSE, TRUE, 0);
gtk_widget_show (glarea);

button_quit = gtk_button_new_with_label ("Quit");
gtk_signal_connect (GTK_OBJECT(button_quit), "clicked", GTK_SIGNAL_FUNC(gtk_main_quit), NULL);
gtk_box_pack_start (GTK_BOX(box_main), button_quit, FALSE, TRUE, 0);
gtk_widget_show (button_quit);

gtk_main ();

return (0);
}


И компиллируем его следующей командой:
#gcc gtkglarea_demo.c -o gtkglarea_demo `pkg-config gtk+-2.0 glib-2.0 gtkgl-2.0 --cflags --libs`
Запускаем на выполнение gtkglarea_demo и видим диалоговое окно с черным квадратом, что и есть (пустая) сцена OpenGL и кнопкой выхода под нашим виджетом.
Файл gtkglarea.h содержится в пакете libgtkgl2.0-dev.
Рассмотрим теперь "конкурента", то есть gtkglext.
Аналогично, создаем файл gtkglext_demo.c с содержимым (он является упрощенной и измененной версией файла simple.c из пакета libgtkglext1-dev):


#include <stdlib.h>
#include <gtk/gtk.h>
#include <gtk/gtkgl.h>
#include <GL/gl.h>
#include <GL/glu.h>

static void
realize (GtkWidget *widget, gpointer data){
GdkGLContext *glcontext = gtk_widget_get_gl_context (widget);
GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable (widget);

if (!gdk_gl_drawable_gl_begin (gldrawable, glcontext))
return;

glClearColor (0.0, 0.0, 0.0, 0.0);
glClearDepth (1.0);
glViewport (0, 0, widget->allocation.width, widget->allocation.height);
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
gluPerspective (40.0, 1.0, 1.0, 10.0);
glMatrixMode (GL_MODELVIEW);
glLoadIdentity ();
gluLookAt ( 0.0, 0.0, 3.0,
0.0, 0.0, 0.0,
0.0, 1.0, 0.0);
glTranslatef (0.0, 0.0, -3.0);

gdk_gl_drawable_gl_end (gldrawable);
}

static gboolean
configure_event (GtkWidget *widget, GdkEventConfigure *event, gpointer data){
GdkGLContext *glcontext = gtk_widget_get_gl_context (widget);
GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable (widget);

if (!gdk_gl_drawable_gl_begin (gldrawable, glcontext))
return FALSE;
glViewport (0, 0, widget->allocation.width, widget->allocation.height);
gdk_gl_drawable_gl_end (gldrawable);

return TRUE;
}

static gboolean
expose_event (GtkWidget *widget, GdkEventExpose *event, gpointer data){
GdkGLContext *glcontext = gtk_widget_get_gl_context (widget);
GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable (widget);

if (!gdk_gl_drawable_gl_begin (gldrawable, glcontext))
return FALSE;
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
if (gdk_gl_drawable_is_double_buffered (gldrawable))
gdk_gl_drawable_swap_buffers (gldrawable);
else
glFlush ();
gdk_gl_drawable_gl_end (gldrawable);

return TRUE;
}

int
main (int argc, char *argv[]){
GdkGLConfig *glconfig;
gint major, minor;
GtkWidget *window;
GtkWidget *vbox;
GtkWidget *drawing_area;
GtkWidget *button;

gtk_init (&argc, &argv);
gtk_gl_init (&argc, &argv);
gdk_gl_query_version (&major, &minor);
g_print ("\nOpenGL extension version - %d.%d\n",major, minor);

glconfig = gdk_gl_config_new_by_mode ( GDK_GL_MODE_RGB |
GDK_GL_MODE_DEPTH |
GDK_GL_MODE_DOUBLE);
if (glconfig == NULL){
glconfig = gdk_gl_config_new_by_mode ( GDK_GL_MODE_RGB |
GDK_GL_MODE_DEPTH);
if (glconfig == NULL)
exit (1);
}

window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_title (GTK_WINDOW (window), "GtkGLExt Demo For Blogger");
gtk_container_set_reallocate_redraws (GTK_CONTAINER (window), TRUE);
g_signal_connect (G_OBJECT (window), "delete_event", G_CALLBACK (gtk_main_quit), NULL);
gtk_container_set_border_width (GTK_CONTAINER(window), 10);
gtk_widget_show (window);

vbox = gtk_vbox_new (FALSE, 10);
gtk_container_add (GTK_CONTAINER (window), vbox);
gtk_widget_show (vbox);

drawing_area = gtk_drawing_area_new ();
gtk_widget_set_size_request (drawing_area, 256, 256);
gtk_widget_set_gl_capability ( drawing_area,
glconfig,
NULL,
TRUE,
GDK_GL_RGBA_TYPE);
g_signal_connect_after (G_OBJECT (drawing_area), "realize", G_CALLBACK (realize), NULL);
g_signal_connect (G_OBJECT (drawing_area), "configure_event", G_CALLBACK (configure_event), NULL);
g_signal_connect (G_OBJECT (drawing_area), "expose_event", G_CALLBACK (expose_event), NULL);
gtk_box_pack_start (GTK_BOX (vbox), drawing_area, TRUE, TRUE, 0);
gtk_widget_show (drawing_area);

button = gtk_button_new_with_label ("Quit");
g_signal_connect (G_OBJECT (button), "clicked",G_CALLBACK (gtk_main_quit), NULL);
gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
gtk_widget_show (button);

gtk_main ();

return 0;
}


Компиллируем
#gcc gtkglext_demo.c -o gtkglext_demo `pkg-config gtk+-2.0 glib-2.0 gtkglext-1.0 --cflags --libs`
И получаем исполняемый файл gtkglext_demo, который дает тот же результат, что и предыдущий пример, только заголовок окна приложения соответственно изменен.
Коротко обсудим разницу между этими двумя протыми приложениями.
Интерфейс gtkglarea можно посмотреть в файле gtkglarea.h из пакета libgtkgl2.0-dev.
Там можно увидеть, что этот виджет является прямым потомком виджета GtkDrawingArea. Еще одним полем в структуре, соответствующей этому виджету, есть переменная типа GdkGLContext. И в первом примере мы с этим виджетом обращаемся стандартно: создаем его своим собственным конструктором, пакуем, устанавливаем сигналы, показываем. Когда рисуем в этот виджет, то пользуемся функцией gtk_gl_area_make_current.
В случае с gtkglext работа происходит несколько иначе. Создается объект типа GdkGLConfig и потом он "привязывается" к виджету GtkDrawingArea. Затем, когда посылаем команды OpenGL в этот виджет, то создаем объекты типа GdkGLContext и GdkGLDrawable, после чего заключаем команды OpenGL в "функциональные скобки" gdk_gl_drawable_gl_begin и gdk_gl_drawable_gl_end.
Оба примера были протестированы на squeeze Debian.

среда, 9 июня 2010 г.

Пример использования LAPACK, BLAS и ATLAS в Дебиан

Рассмотрим сначала использование LAPACK. Для начала создадим файл lapack.c следующего содержания:
$ cat lapack.c


/* Example C code for solving a linear system Ax=b using LAPACK */
#include <stdio.h>

/* Declare function prototype */
extern int sgesv_(int *n, int *nrhs, float *a, int *lda,
int *ipiv, float *b, int *ldb, int *info);

/* -- LAPACK driver routine (version 3.1) --
Purpose
=======

SGESV computes the solution to a real system of linear equations
A * X = B,
where A is an N-by-N matrix and X and B are N-by-NRHS matrices.

The LU decomposition with partial pivoting and row interchanges is
used to factor A as
A = P * L * U,
where P is a permutation matrix, L is unit lower triangular, and U is
upper triangular. The factored form of A is then used to solve the
system of equations A * X = B.

Arguments
=========

N (input) INTEGER
The number of linear equations, i.e., the order of the
matrix A. N >= 0.

NRHS (input) INTEGER
The number of right hand sides, i.e., the number of columns
of the matrix B. NRHS >= 0.

A (input/output) REAL array, dimension (LDA,N)
On entry, the N-by-N coefficient matrix A.
On exit, the factors L and U from the factorization
A = P*L*U; the unit diagonal elements of L are not stored.

LDA (input) INTEGER
The leading dimension of the array A. LDA >= max(1,N).

IPIV (output) INTEGER array, dimension (N)
The pivot indices that define the permutation matrix P;
row i of the matrix was interchanged with row IPIV(i).

B (input/output) REAL array, dimension (LDB,NRHS)
On entry, the N-by-NRHS matrix of right hand side matrix B.
On exit, if INFO = 0, the N-by-NRHS solution matrix X.

LDB (input) INTEGER
The leading dimension of the array B. LDB >= max(1,N).

INFO (output) INTEGER
= 0: successful exit
< 0: if INFO = -i, the i-th argument had an illegal value
> 0: if INFO = i, U(i,i) is exactly zero. The factorization
has been completed, but the factor U is exactly
singular, so the solution could not be computed.

===================================================================== */

#define SIZE 3 /* dimension of matrix */

static int solve(float A[][SIZE], float *b) {

int i,j,info,n,nrhs,lda,ipiv[SIZE],ldb;
float AT[SIZE*SIZE];

/* Permute matrix */
for (i=0; i<SIZE; i++) {
for(j=0; j<SIZE; j++)
AT[j*SIZE+i]=A[i][j];
}

/* Invoke sgesv_ */
n = lda = ldb = SIZE; nrhs = 1;
sgesv_(&n, &nrhs, AT, &lda, ipiv, b, &ldb, &info);
return info;
}

int main(int argc, char **argv)
{
int i, j, pivot[SIZE], ok;
float A[SIZE][SIZE], b[SIZE];

/* Matrix A */
A[0][0]= 1.1; A[0][1]= 2.2; A[0][2]=-3.3;
A[1][0]= 4.4; A[1][1]=-5.5; A[1][2]= 6.6;
A[2][0]=-7.7; A[2][1]= 8.8; A[2][2]= 9.9;

/* Define right hand side vector */
b[0] = 0;
b[1] = 5.5;
b[2] = 11;

/* Call warpper function */
ok = solve(A, b);

/* Print out solution vector x */
for (j=0; j<SIZE; j++)
printf("%g\n", b[j]);
}



Компиллируем этот код с помощью команды:
$ gcc lapack.c -o lapack -llapack

Смотрим - какие пакеты нам нужны (просто для информации)
$ apt-file search /usr/lib/liblapack.so
lapack3: usr/lib/liblapack.so.3
lapack3: usr/lib/liblapack.so.3.0
lapack3-dev: usr/lib/liblapack.so


Рассмотрим теперь пример использования BLAS и еще один пример использования LAPACK в одном файле. Создадим файл blas.c такого содержания:
$ cat blas.c



#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <cblas.h>
#include <clapack.h>

int clapack_sgetrf(const enum CBLAS_ORDER Order, const int M, const int N, float *A, const int lda, int *ipiv);
// a is a column-major array of all the values in the matrix to invert
// The matrix's height and width are the same because it is a square matrix.
void invertMatrix(float *a, unsigned int height)
{
int info, ipiv[height];
info = clapack_sgetrf(CblasColMajor, height, height, a, height, ipiv);
info = clapack_sgetri(CblasColMajor, height, a, height, ipiv);
}

void displayMatrix(float *a, unsigned int height, unsigned int width)
{
int i, j;
for(i = 0; i < height; i++)
{
for(j = 0; j < width; j++)
{
printf("%1.3f ", a[height*j + i]);
}
printf("\n");
}
printf("\n");
}

void multiplyMatrix(float *a, unsigned int aheight, unsigned int awidth, float *b, unsigned int bwidth, float *c)
{
cblas_sgemm(CblasColMajor, CblasNoTrans, CblasNoTrans, aheight, bwidth, awidth, 1.0f, a, aheight, b, awidth, 0.0f, c, aheight);
}

int main(int argc, char *argv[])
{
int i;
float a[9], b[9], c[9];
srand(time(NULL));
for(i = 0; i < 9; i++)
{
a[i] = 1.0f*rand()/RAND_MAX;
b[i] = a[i];
}
displayMatrix(a, 3, 3);
invertMatrix(a, 3);
multiplyMatrix(a, 3, 3, b, 3, c);
displayMatrix(c, 3, 3);
return 0;
}

Компиллируем его:
$ gcc blas.c -o blasAndLapackUsage -llapack -L /usr/lib/atlas
Посмотрим дополнительную информацию про файлы, которые нужны для компиляции этого примера:
$ apt-file search /usr/include/clapack.h
atlas3-headers: usr/include/clapack.h
$ apt-file search /usr/include/cblas.h
refblas3-dev: usr/include/cblas.h
$ apt-file search /usr/lib/liblapack.so
lapack3: usr/lib/liblapack.so.3
lapack3: usr/lib/liblapack.so.3.0
lapack3-dev: usr/lib/liblapack.so

$ apt-file search /usr/lib/atlas
atlas3-base: usr/lib/atlas/libblas.so.3
atlas3-base: usr/lib/atlas/libblas.so.3.0
atlas3-base: usr/lib/atlas/liblapack.so.3
atlas3-base: usr/lib/atlas/liblapack.so.3.0
atlas3-base-dev: usr/lib/atlas/libblas.a
atlas3-base-dev: usr/lib/atlas/libblas.so
atlas3-base-dev: usr/lib/atlas/liblapack.a
atlas3-base-dev: usr/lib/atlas/liblapack.so

Другие полезные ссылки по теме:
ATLAS FAQ
Example C code for solving a linear system Ax=b using LAPACK
Compiling Programs Containing LAPACK Routines
LAPACK build and test guide
Using Lapack Routines in C Programs
netlib, Frequently Asked Questions
BLAS Frequently Asked Questions (FAQ)
GNU Scientific Library -- Reference Manual
Driver Routines
The Linear Algebra Package

суббота, 29 мая 2010 г.

Пример использования GNU Scientific Library (GSL) в Дебиан

Этот исходник взят с GSL-CBLAS-Examples
#cat gsl-cblas.c
Описание функций из библиотеки GSL находиться здесь.

#include <stdio.h>
#include <gsl/gsl_cblas.h>
int
main (void)
{
int lda = 3;
float A[] = { 0.11, 0.12, 0.13,
0.21, 0.22, 0.23 };
int ldb = 2;
float B[] = { 1011, 1012,
1021, 1022,
1031, 1032 };
int ldc = 2;
float C[] = { 0.00, 0.00,
0.00, 0.00 };
/* Compute C = A B */
cblas_sgemm (CblasRowMajor,
CblasNoTrans, CblasNoTrans, 2, 2, 3,
1.0, A, lda, B, ldb, 0.0, C, ldc);
printf ("[ %g, %g\n", C[0], C[1]);
printf (" %g, %g ]\n", C[2], C[3]);
return 0;
}

Процедура просто перемножает две матрицы. Ее описание тут.
Чтобы откомпиллировать этот исходник командой
#gcc -o gsl-cblas gsl-cblas.c -lblas
нам необходимы файлы libblas.so и libblas.so.
#apt-file search /usr/lib/libblas.so
refblas3: usr/lib/libblas.so.3
refblas3: usr/lib/libblas.so.3.0
refblas3-dev: usr/lib/libblas.so

# ls -al /usr/lib/libblas.so
lrwxrwxrwx 1 user user 12 2009-08-06 14:44 /usr/lib/libblas.so -> libblas.so.3
# apt-file search /usr/include/gsl/gsl_cblas.h
libgsl0-dev: usr/include/gsl/gsl_cblas.h
libgsl0-dev: usr/include/gsl/gsl_cblas.h

Вывод команды ./gsl-cblas:
[ 367.76, 368.12
674.06, 674.72 ]
Этот исходник можно откомпиллировать также с помощью команды:
#gcc -Wall gsl-cblas.c -lgslcblas
Для успешной компилляции нужен установленный пакет libgsl0:
#ls -al /usr/lib/libgslcblas.so
lrwxrwxrwx 1 user user 20 2009-12-17 16:45 /usr/lib/libgslcblas.so -> libgslcblas.so.0.0.0
#ls -al /usr/lib/libgslcblas.so.0.0.0
-rw-r--r-- 1 user user 188936 2006-11-19 03:26 /usr/lib/libgslcblas.so.0.0.0
#apt-file search /usr/lib/libgslcblas.so.0.0.0
libgsl0: usr/lib/libgslcblas.so.0.0.0

четверг, 29 апреля 2010 г.

Апгрейд с lenny на sqeeze

Аналогичные действия делаем при переходе с etch на lenny.
#sudo vim /etc/apt/sources.list
Заменить каждое слово "lenny" на слово "squeeze" ("etch" на "lenny").
Ну и наконец:
#sudo aptitude update
#sudo aptitude install apt dpkg aptitude
#sudo aptitude full-upgrade