28 de agosto de 2006

Dos libros importantes en formato electrónico

De la lista de correo de los CISSP, me llega la información que el excelente libro Security Engineering está disponible por parte del autor en formato electrónico aquí.

En esa página muestran también el link a un libro interesante (también en formato electrónico) de Teoría de la Información y Codificación, disponible aquí.

DVD: Pink Floyd Pulse
Libro: 10 años con Mafalda

13 de julio de 2006

Textos clásicos de Computer Science

Llevo muchísimo tiempo sin postear, por la cantidad de actividades que he estado haciendo últimamente. Terminó el semestre de Compiladores, y ahora es tiempo de entrarle a Sistemas Operativos. Estoy contento del cambio.

Una joya que encontré, no sé si en digg o reddit, es la siguiente: Classic Texts in Computer Science, una página que recoge links a documentos famosos o clásicos sobre CS, que han impuesto nuevas tendencias o forman parte de los cimientos de nuestra querida área de estudio.

En otras cosas, estoy probando discos encriptados, usando TrueCrypt, que provee de particiones o discos encriptados para Windows y Linux. Una de las ventajas que me gustan sobre otras soluciones (aparte que es gratis y de Código Abierto), es que no está atado a un hardware en específico y que los discos encriptados son transportables. Hay que hacer más pruebas, pero en lo poco que he visto está buenísimo. Me falta trabajar en los temas de usabilidad del software para la facilidad del usuario.

Video: Star Trek: The Original Series Season 1

17 de junio de 2006

Ejercicios para conocer un lenguaje de programación

En digg salió hace poco un artículo titulado "15 exercises to learn a new programming language", que está interesante pero me ha parecido que le falta algo de estructura, y que son ejercicios con una dificultad moderada, que permiten mas o menos agarrarle la onda a un nuevo lenguaje. Al respecto de esto, una persona en una lista de correo sugirió ver esta página en vez de la anterior.

En verdad que la segunda opción me ha parecido buenísima, ya que tiene el toque de lo que se espera de un programador que trabaja actualmente en la industria global de desarrollo, como lo menciona el autor. Sería interesante tomar el reto, y hacer los ejercicios que propone.

Me llamó la atención también que los primeros ejercicios menciona que son más fáciles en Lisp, Ruby o Perl que en C/C++, pero que los siguientes se implementan mejor en C/C++. La tercera parte de ejercicios son de OOP.

5 de junio de 2006

Es Minix!

Bueno, ya es oficial que el próximo semestre estaré cambiando los compiladores por los sistemas operativos. Estuve investigando acerca de qué proyecto sería lo mejor y que tuviera un buen nivel de reto, y me recordé del viejo Minix...alguien tiene por allí prestado mi libro de la primera edición de Tanembaum, y no me lo ha devuelto en al menos unos 10 años, creo que ya sé quién lo tiene...

En fin, ahora ya existe la versión 3 de Minix, etc. y se ha vuelto a renovar el debate entre Linus y Tanembaum que viene desde hace varios años, y recientemente ha salido la 3ra. edición del libro de Operating Systems: Design and Implementation.

Encontré varios papers sobre el uso de Minix en la educación, y me ha parecido una buena opción. En realidad, también estoy de acuerdo que estar revisando 176 MB de líneas de código (Linux) como que no nos daría tiempo en el semestre, así que mejor nos vamos a 4.5 MB (Minix).

Entonces, con la ayuda de los amigos de ICOMS he creado un sitio dedicado a Minix, pero con contenido en español. El URL es: http://www.es-minix.org y ya tenemos los foros instalados.

En el transcurso de estas vacaciones de UNITEC estaré actualizando el sitio y dejándolo listo para el curso.

Video: Firefly y Star Trek: The Next Generation Season 1
Música: Red Hot Chili Peppers - Stadium Arcadium
Libros: The world is flat
Juegos: Nintendo DS Brain Age y PSP Burnout Legends

20 de abril de 2006

Arqueología de código

Hace poco me econtré en mi disco duro con un programati que había hecho para divertirme hace algunos años. Lo posteo aquí para recordar la forma "real" de programar directamente el Windows API en C++, sin usar visual tools.

La idea es que ahora acabo de instalar Visual Studio 2005 y estoy comenzando a hacer una aplicación que por medio del los web services de Amazon traiga los nombres de las canciones de un CD (no estoy seguro siquiera que Amazon provea esta info, pero bueno hay q investigar) para renombrar archivos MP3...a ver que tal...

Libro: Masters of Deception
Video: Lost Season 1
Música: Show your bones - The Yeah Yeah Yeahs

---------------------- AQUI VA EL CÓDIGO VIEJO -------------------------
------------------- FALTAN RESOURCES E ICONOS PARA QUE FUNCIONE

// basura.cpp - Programa para actuar como el basurero de Macintosh. Acepta Drag & Drop bajo
// Windows 3.1 unicamente.
// Escrito por Egdares Futch H. 14-Jun-93
// Compilador : Borland C++ 3.1

#include
#include
#include
#include
#include

const UINT CM_ABOUT = 42;
const UINT CM_RECUPERAR = 43;
const UINT CM_BORRAR = 44;

// ****************************************************************************************
// **************************** LISTAS.CPP ************************************************
// ****************************************************************************************

// list.cpp - Manejo de listas encadenadas genericas en C++
// Escrito por Egdares Futch H. para el curso de Programacion III, 1992

// Clase abstracta para descender de ella todos los nodos que se desean
// encadenar

class Node
{
protected:
Node *next;
public:
Node(void) { next = NULL; }
virtual ~Node(void) { }
virtual char *getname(void) const = 0;
Node *getnext(void) { return next; }
void setnext(Node *n) { next = n; }
};

class List
{
protected:
Node *top;
public:
List() { top = NULL; }
List(Node *node) { top = node; }
~List(void) { }
void insert(Node *node) { node->setnext(top); top = node; }
void append(Node *);
};

void List::append(Node *node)
{
Node *tmp = top;

if (top == NULL)
top = node;
else
{
while (tmp->getnext() != NULL)
tmp = tmp->getnext();
tmp->setnext(node);
}
node->setnext(NULL);
}

class IterationList : public List
{
Node *iterationpointer;
public:
IterationList() { }
IterationList(Node *node) : List(node) { }
void InitIteration(void) { iterationpointer = NULL; }
Node *iterate(void);
void iteratedelete(void);
};

// Protocolo : si llamo con itptr == NULL, implica inicializar las cosas

Node *IterationList::iterate(void)
{
if (iterationpointer == NULL)
iterationpointer = top;
else
iterationpointer = iterationpointer->getnext();
return iterationpointer;
}

void IterationList::iteratedelete(void)
{
if (iterationpointer == NULL)
iterationpointer = top;
while (iterationpointer != NULL)
{
Node *next = iterationpointer->getnext();
delete iterationpointer;
iterationpointer = next;
}
top = NULL;
}

// Definicion de clases concretas, basadas en herencia para sacar de ellas la lista de
// archivos para el programa de Basura

class TrashFile : public Node
{
char *name;
public:
// Constructor default, no hace mucho
TrashFile(void) { name = NULL; }
// Constructor con un nombre de archivo
TrashFile(const char *);
virtual ~TrashFile(void);
char *getname(void) const { return name; }
};

// Implementacion del constructor

TrashFile::TrashFile(const char *n)
{
if (n != NULL)
{
name = new char[strlen(n)+1];
strcpy(name,n);
}
else
name = NULL;
}

// Implementacion del destructor

TrashFile::~TrashFile(void)
{
unlink(name);
delete [] name;
}

// *****************************************************************************************
// ********************************** FIN DE LISTAS.CPP ************************************
// *****************************************************************************************

// ********************** Definicion de clase para la aplicacion *************************

class TBasuraApp: public TApplication
{
public:
TBasuraApp(LPSTR AppName,HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow) : TApplication(AppName,hInstance,hPrevInstance,lpCmdLine,nCmdShow) { };
virtual void InitMainWindow(void);
virtual void InitInstance(void);
};

// *********************** Definicion de clase para la ventana **************************

_CLASSDEF(TBasuraWindow)
class TBasuraWindow : public TWindow
{
public:
TBasuraWindow(PTWindowsObject Parent,LPSTR Title) : TWindow(Parent,Title) { };
virtual void SetupWindow(void);
virtual void GetWindowClass(WNDCLASS &WndClass);
virtual void Paint(HDC hDC,PAINTSTRUCT _FAR & PaintInfo);
virtual BOOL CanClose(void);
// Funciones virtuales de respuesta de mensajes
virtual void WMSysCommand(RTMessage Msg) = [WM_FIRST + WM_SYSCOMMAND];
virtual void WMDropFiles(RTMessage Msg) = [WM_FIRST + WM_DROPFILES];
// Componentes de datos
HDROP hDrop;
int nFiles;
HICON hVacio,hLleno;
IterationList FileList;
};

// ******************** TBasuraWindow::SetupWindow() *****************************

void TBasuraWindow::SetupWindow(void)
{
nFiles = 0;
hVacio = LoadIcon(GetApplication()->hInstance,"VACIO");
hLleno = LoadIcon(GetApplication()->hInstance,"LLENO");
}

// ******************** TBasuraWindow::GetWindowClass() **************************

void TBasuraWindow::GetWindowClass(WNDCLASS &WndClass)
{
TWindow::GetWindowClass(WndClass);
WndClass.hIcon = LoadIcon(GetApplication()->hInstance,"VACIO");
}

// ********************* TBasuraWindow::Paint() ***********************************

#pragma argsused

void TBasuraWindow::Paint(HDC hDC,PAINTSTRUCT _FAR & PaintInfo)
{
Node *it;
char buffer[50];

int ypos = 0;
FileList.InitIteration();
while ((it = FileList.iterate()) != NULL)
{
TextOut(hDC,0,ypos,it->getname(),strlen(it->getname()));
ypos += 20;
}
TextOut(hDC,0,ypos,buffer,sprintf(buffer,"Número de archivos = %d",nFiles));
}

// *********************** TBasuraWindow::CanClose() *********************************

BOOL TBasuraWindow::CanClose(void)
{
if (nFiles > 0)
{
if (MessageBox(HWindow,"El basurero tiene archivos. Desea terminar?\n (Los archivos no se borrarán)",
"Hay basura!",MB_ICONINFORMATION | MB_YESNO) == IDYES)
{
DestroyIcon(hVacio);
DestroyIcon(hLleno);
DragAcceptFiles(HWindow,FALSE);
return TRUE;
}
else
return FALSE;
}
DestroyIcon(hVacio);
DestroyIcon(hLleno);
DragAcceptFiles(HWindow,FALSE);
return TRUE;
}

// ************************* TBasuraWindow::WMSysCommand() ********************************

void TBasuraWindow::WMSysCommand(RTMessage Msg)
{
switch(Msg.WParam)
{
case CM_ABOUT:
MessageBox(HWindow,"Basura fue escrito por Egdares Futch\n usando Borland C++ 3.1",
"Acerca de Basura",MB_ICONINFORMATION | MB_OK);
break;
case CM_BORRAR:
nFiles = 0;
FileList.InitIteration();
FileList.iteratedelete();
InvalidateRect(HWindow,NULL,TRUE);
SetClassWord(HWindow,GCW_HICON,(WORD)hVacio);
FlashWindow(HWindow,FALSE);
break;
default:
DefWndProc(Msg);
}
}

// ************************* TBasuraWindow::WMDropFiles **********************************

void TBasuraWindow::WMDropFiles(RTMessage Msg)
{
char buffer[80];

hDrop = (HDROP)Msg.WParam;
int NewFiles = DragQueryFile(hDrop,-1,(LPSTR)NULL,0);
if (nFiles == 0)
{
SetClassWord(HWindow,GCW_HICON,(WORD)hLleno);
FlashWindow(HWindow,FALSE);
}
nFiles += NewFiles;
for (int i = 0 ; i < NewFiles ; i++)
{
DragQueryFile(hDrop,i,buffer,80);
FileList.append(new TrashFile(buffer));
}
DragFinish(hDrop);
if (!IsIconic(HWindow))
InvalidateRect(HWindow,NULL,TRUE);
Msg.Result = 0;
}

// **************************** TBasuraApp::InitMainWindow() *******************************

void TBasuraApp::InitMainWindow(void)
{
MainWindow = new TBasuraWindow(NULL,Name);
}

// **************************** TBasuraApp::InitInstance() ********************************

void TBasuraApp::InitInstance(void)
{
TApplication::InitInstance();
HMENU SystemMenu = GetSystemMenu(MainWindow->HWindow,FALSE);
AppendMenu(SystemMenu,MF_SEPARATOR,0,NULL);
AppendMenu(SystemMenu,MF_STRING,CM_BORRAR,"&Eliminar basura");
AppendMenu(SystemMenu,MF_STRING,CM_RECUPERAR,"Recu&perar basura");
AppendMenu(SystemMenu,MF_STRING,CM_ABOUT,"&Acerca de Basura ...");
DragAcceptFiles(MainWindow->HWindow,TRUE);
}

// ************************* WinMain (programa principal) **********************************

#pragma argsused

int PASCAL _export WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
TBasuraApp Basura("Basura", hInstance, hPrevInstance,lpCmdLine, SW_SHOWMINNOACTIVE);

Basura.Run();
return Basura.Status;
}

2 de abril de 2006

El misterioso caso del DVD writer que sólo escribe a 1x (PARTE 1)

Este es uno de los misterios más recientes que me han tocado resolver, y precisamente fue sobre mi computadora nueva, que no tiene más que tres meses de estar en uso.

Hace poco comenzé a tener problemas al quemar archivos en DVD: probé cambiando de marca de media, de formato DVD-R, DVD+R, DVD-RW, DVD+RW, etc. Luego me dí cuenta que también los CDs de audio salían con ruidos, fallas, canciones sin sonido!

Intenté ahora quemar sin carga de procesos en el sistema, sin antivirus, sin antispyware, desconectado de la red, etc. El problema que veía es que la computadora quemaba a una velocidad bajísima. Luego de muchas consultas a Gugle, no encontraba nada, tal vez era la licencia del Nero, etc.

También sospeche que la media que estaba usando era de procedencia dudosa...

El Nero incluye una herramienta llamada Nero Infotool, que permite obtener información muy completa sobre el drive, la media (aquí verifiqué que si era original), y otras características del caso.

Como seguía con las fallas y había agotado mis opciones, lo declaré fallido. Con la excelente garantía que me dieron, de tres años, entonces lo llevé donde el representante autorizado para que revisaran la computadora.

Al final, la empresa decidió cambiar la unidad DVD-writer completa, y poner una nueva. El tiempo fue rapidísimo, no más de dos días. Por motivos de viaje tuve que ir a recogerla cinco días después.

La volví a colocar en el escritorio, reconecté los cables, potencia, monitor, etc. y me puse a hacer una prueba. Se veía que la unidad era nueva, se sintió mucho más silenciosa.

(ALAGRAN! PERDI LO QUE SEGUIA...A ESPERAR LA PARTE 2)

27 de marzo de 2006

Generador de lexer y parser para C#

Una larga ausencia, pero bueno, al menos algo de carnita: una persona me preguntó por correo que si existía Lex/Yacc o similares para Visual Basic .Net. Lo más cercano que encontré fue una versión que hicieron en la Universidad de Viena para C#, y que está disponible en esta dirección. Puede servir para hacer pequeños parsers o tokenizers en proyectos de VB, aunque no estoy seguro cómo linkear C# con VB.Net.

Libros: Genius, una biografía de Richard Feynman, que es una de las personas que más admiro.
Música: Robbie Williams - por la presentación que hizo en Live 8.
Video: Live 8 y el concierto de reunión de Cream 2005.

2 de febrero de 2006

Membresía reducida para países en vías de desarrollo

Bueno, inauguramos el blog para este año ya que me dí cuenta que la ACM (Association for Computer Machinery) ha puesto a la disposición de los estudiantes y profesionales que residen en países en vías de desarrollo (como los nuestros), tarifas especiales para suscribirse a esta importante asociación profesional, con precios alcanzables y que permiten el acceso a importantes recursos de información.

El link es para los precios especiales está aquí. Espero que esto sea de utilidad.