Etiquetas

C (31) Cpp (28) Linux (14) asm (8) Telegram (5) bot (5) libreria (5) Algoritmo (3) Errores comunes (3) python (3) Opengl (2) kali (2) Android (1) Snippet (1) nano (1) recursividad (1)
Mostrando las entradas con la etiqueta C. Mostrar todas las entradas
Mostrando las entradas con la etiqueta C. Mostrar todas las entradas

domingo, 21 de junio de 2026

[C]Bruteforce Recursivo vs Iterativo


/*Me encontré este post en elhacker y lo comparto con uds... no es de mi autoría Hay casos en que es más conveniente usar la recursividad para solucionar un problema. Hay que cambiar system("PAUSE") y los scanf"*/

//////////////////////////////////////
/*BruteForce Iterativo en Lenguaje C*/
//////////////////////////////////////
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[]){
int contadores[50]={0}, len=0, cant=0, i=0;
char caracteres[200]={0}, pass[50]={0};
printf ("Ingrese los caracteres a usar para la contrasena: \n");
scanf ("%s", caracteres);
printf ("Ingrese la longitud de la contraseña: \n");
scanf ("%i", &len);
cant = strlen (caracteres);
/*contadores = (int *) malloc (sizeof (int) * (len+1) );
pass = (char *) malloc (len+1);*/
for (i=0 ; i<len;i++){
pass[i] = caracteres[0];contadores[i] = 0;}
contadores[i] = 0;pass [i] = '\0';
while (!contadores[len]){
printf ("%s\n", pass);
for (i=0;contadores[i]==cant-1;i++)
pass[i] = caracteres [contadores[i] = 0];
pass[i] = caracteres [++contadores[i]];}
/*free (contadores);free (pass);*/
system("PAUSE");return 0;} //end of main
vs Recursivo

//////////////////////////////////////
/*BruteForce Recursivo en Lenguaje C
*///////////////////////////////////////
#include <stdio.h>
#include <string.h>
void brute_force (char caracteres[], int cant, int pos, char *password){
if(pos==-1){printf ("%s\n", password);return;}
for(int i=0;i password[pos]=caracteres[i];
brute_force (caracteres, cant, pos-1, password);}
return;}

int main(int argc, char *argv[]){
char caracteres[256]={0}, *password=NULL;int longitud=0, cantidad=0;
double tiempo=0;time_t t1, t2;
printf ("Ingrese los caracteres a usar: ");
scanf ("%s", caracteres);
cantidad = strlen(caracteres); printf ("Ingrese la longitud maxima de la contraseña: "); scanf ("%i", &longitud); password = (char*) malloc (longitud*sizeof(char)); time (&t1);password[longitud]= '\0'; brute_force (caracteres, cantidad, longitud-1, password); time (&t2);tiempo = difftime (t2, t1); printf ("\tTiempo: %7.2f\n\n", tiempo); free (password); //importante:liberar memoria system("PAUSE");return 0;}

miércoles, 5 de junio de 2024

No encontrar las librerías .h en linux

Las librerías que usa gcc y g++ (y creo que clang) están en /usr/include/ ...a veces el comando locate no encuentra las librerías.

viernes, 31 de mayo de 2024

Los 11 fallos más comunes en Lenguaje C

(1)Mezclar enteros signed y unsigned.
(2)Sobrepasando límites de un arreglo.
(3)Perdiendo la condición base de una funcion recursiva.
(4)Usando constantes de caracteres en vez de literales de cadena y viceversa.
(5)Literales de tipo float son por defecto de tipo double.
(6)Olvidando liberar la memoria.
(7)Añadiendo un semicolon a #define.
(8)No ser cuidadoso con el semicolon.
(9)Erroneamente escribir = o ==.
(10)Copiando demasiado.
(11)Las macros son solo reeemplazo de cadenas.
1.- Mezclar enteros signed y unsigned en operaciones aritmeticas
#include stdio.h
int main(void){
unsigned int a = 1000;signed int b = -1;
if (a > b) puts("a is more than b");
else puts("a is less or equal than b");
return 0;}
Como 1000 es mayor que -1 uno esperaría que a es mayor que b. Antes de hacer la comparación, b es convertida a unsigned int. Cuando es convertido a unsigned int toma el valor máximo de unsigned int... el cual es mayor que 1000. Por esto se puede apreciar que a > b es una falso.
2.- Sobrepasando los límites de un arreglo.

Los arreglos siempre empiezan en 0 y terminan en la longitud del arreglo - 1.
#include stdio.h
int main(){
int x = 0;int myArray[5] = {1,2,3,4,5};
for(x=1; x<=5; x++){printf("%d\t",myArray[x]);}
printf("\n");return 0;} //Output: 2 3 4 5 GarbageValue
La forma correcta:
#include stdio.h
int main(){
int x = 0;int myArray[5] = {1,2,3,4,5};
for(x=0; x<5; x++){printf("%d\t",myArray[x]);}
printf("\n");return 0;} //Output: 1 2 3 4 5
Entonces, hay que conocer el límite de nuestros arreglos porque osino podemos corromper el buffer o provocar un fallo de segmentacion por acceder a un área de memoria distinta.
3.- Perdiendo la condición base en una función recursiva.
Calcular la factorización de un número es un ejemplo clásico de recursividad:
#include stdio.h
int factorial(int n){return n * factorial(n - 1);}

int main(){
printf("Factorial %d = %d\n", 3, factorial(3));return 0;}
//Typical output: Segmentation fault
El problema con esta función es que va a estar en un ciclo infinito, lo que causará fallo de segmentación. Necesita una condición base para detener la recursividad. La forma correcta:
#include stdio.h
int factorial(int n){
// Base Condition, very crucial in designing the recursive functions.
if (n == 1){return 1;}else{return n * factorial(n - 1);}}

int main(){
printf("Factorial %d = %d\n", 3, factorial(3));return 0;}
//Esta función va a terminar tan pronto alcance 1.
//Output : Factorial 3 = 6
Reglas a seguir:
1 Iniciar el algoritmo.
Las funciones recursivas necesitan con frecuencia un valor inicial con el que empezar. Esto es acompañado sea por un parametro de la función o una función puerta que no es recursiva pero pone los valores iniciales para la recursión.

2 Revisar para ver si los valores actuales que se están procesando coinciden con el caso base.Si es asi, entonces procesa y devuelve un valor


3 Redefine la respuesta en terminos de un problema pequeño o simple subproblema o subproblemas.

4 Ejecuta el algoritmo en un subproblema.
5 Combina los resultados en la formulación de la respuesta.
6 Retorna los resultados.

4.- Usando constantes de caracteres en vez de literales de cadena y viceversa.

En lenguaje C, las cadenas de caracteres y literales de cadena son cosas distintas. 'a' ..esto es una cadena de caracter. Una cadena de caracter es de tipo entero que tiene asignado un número para ese caracter. "asdf"... es un literal de caracteres. Un literal de caracteres un arreglo inmodificable cuyos elementos son de tipo char. "asdf" tiene 5 caracteres, porque el caracter final es un \0. Este caracter final es conocido como carácter nulo. {a,s,d,f,\0}.
//ejemplo 1: una cadena de caracteres es usada donde debería ir una literal de cadena. Esto da un comportamiento indefinido.
#include stdio.h
int main(void){
const char *hello = 'hello, world'; /* bad */puts(hello);return 0;}
//ejemplo 2:
un literal de cadena se usa donde se debería usar una cadena de caracteres. El resultado es una cosa sin sentido.
#include stdio.h
int main(void) { char c = "a"; /* bad */ printf("%c\n", c); return 0;}
En ambos casos el compilador se va a quejar de la mezcla. Si no pasa esto, necesita usar más advertencias para la compilación, o derechamente usar un mejor compilador.

5.- Literales de tipo float son por defecto de tipo double.

Hay que tener cuidado al inicializar una variable float a valores literales o compararlas con estos. Esto es debido a que literales float de valor 0.1 por lo regular son de tipo double. Este tipo de cosas nos puede conducir a sorpresas:

#include stdio.h

int main(){
float n = 0.1; if (n > 0.1) printf("Wierd\n");return 0;}
// Prints "Wierd" when n is float
n fue inicializada y redondeada por precisión, resultando en 0.10000000149011612. Entonces, n es vuelto a convertir en double para ser comparado con el valor literal 0.1 (lo cual es igual a 0.10000000000000001) lo que da una discordancia. Mezclar variables float con literales dobles puede resultar en pobre desempeño en plataformas donde no hay soporte de hardware para doble precisión.

6.- Olvidando liberar la memoria.

Uno siempre debe recordar liberar la memoria alojada, sea una función hecha por tí o por una función de librería llamada por tu función.
#include stdlib.h #include stdio.h

int main(void){
char *line = NULL;size_t size = 0;
/* memory implicitly allocated in getline */
getline(&line, &size, stdin);
/* uncomment the line below to correct the code */
/* free(line); */return 0;}
Es un error inocente en este ejemplo específico,porque cuando un proceso termina,la mayoría de los sistemas operativos libera la memoria alojada en vez de tí.
7.- Añadiendo un semicolon a #define

Muchas veces me pasó a mí!!! Es fácil confundirse con el preprocesador de C, y tratarlo como parte del lenguaje. Pero es un error, porque el preprocesador es sólo un mecanismo de reemplazo de texto.
// WRONG
#define MAX 100; int arr[MAX]={0};
//lo cual se traduce como
int arr[100]={0}; //Que se traduce como error de sintaxis.

8.- Ser cuidadoso con el semicolon
//Esto: if (x > a); a = x;
//Significa esto:
if (x > a) {} a = x;
Aveces, perder un semicolon puede provocar problemas inesperados:
if (i < 0) return day = date[0]; hour = date[1]; minute = date[2];
/*El semicolon antes de return está perdido, por lo que day =date[0]; va a ser regresado. El compilador lee hasta que encuentra ; como el fin de línea.*/

9.- Erroneamente escribir = en vez de ==.
El = es para asignar.
El == es para COMPARAR.
A veces hacemos:
/* assign y to x */ if (x = y) {/* logic */}
//cuando lo que uno queria era:
/* compare if x is equal to y */ if (x == y) {/* logic */}

//lo cual es equivalente a:
/* compare if x is equal to y */ if (x == y) != 0{/* logic */}

10.- Copiando demasiado.
char buf[8]={0}; /* tiny buffer, easy to overflow */
printf("What is your name?\n");
scanf("%s", buf); /* WRONG */
scanf("%7s", buf); /* RIGHT */
Si uno pone más caracteres que los requeridos por scanf, van a empezar a sobreescribirse zonas de memorias aledañas al buffer. Esto puede derivar en comportamiento indefinido. Los hackers maliciosos con frecuencia usan esto para sobreeescribir la dirección de return, y cambiar la dirección por la del código malicioso creado por este.
11.- Las Macros son solo reemplazo de cadenas
#include stdio.h
#define SQUARE(x) x*x
//este es el error.
int main(void){
printf("%d\n", SQUARE(1+2));return 0;}
Esperarías que este código devolviese 9, pero devolverá 5 porque la macro será expandida a 1+2*1+2. Para evadir este problema debe encerrar entre () las fichas para evadir este problema.
#include stdio.h
#define SQUARE(x) ((x)*(x))
int main(void){
printf("%d\n", SQUARE(1+2));return 0;}

Diferencias entre const int y int const

Una respuesta simple: leer hacia atrás. Los punteros como sabréis son variables especiales que apuntan a otras variables, y las constantes son variables que no cambian durante la ejecución de un programa. int * ptr = ptr es un puntero hacia int. int const * ptr = ptr es un puntero hacia constante int. int * const ptr = ptr es un puntero constante hacia int. const int * const ptr = ptr es una constante puntero a una constante int. const int * ptr es igual a int const * ptr const int * const ptr es igual a int const * const ptr véase que lo que cambia es lo que esta antes de *ptr o *const ptr. int ** ptr = is a pointer to pointer(p2p) to int. Un puntero que apunta hacia otro puntero. int ** const ptr = ptr es un puntero constante de un puntero hacia int. int * const * ptr = ptr es un puntero a una constante puntero hacia int. int const **ptr = ptr es un puntero de un puntero hacia una constante int. int * const * const ptr = ptr es un puntero constante de otro puntero constante hacia int. ¿Como saber si const se refiere al puntero o lo apuntado? Si está del lado derecho del asterico, entonces se refiere a lo apuntado. Si está del lado izquierdo del asterico, del puntero. Fuente: What is the difference between const int and int const.

miércoles, 22 de mayo de 2024

Colores c.nanorc

## Syntax highlighting for C and C++ files. syntax c "\.([ch](pp|xx)?|C|cc|c\+\+|cu|H|hh|ii?)$" header "-\*-.*\" # Labels. color brightmagenta "^[[:blank:]]*[A-Z_a-z][0-9A-Z_a-z]*:[[:blank:]]*$" color normal ":[[:blank:]]*$" # Types and related keywords. color green "\<(auto|bool|char|const|double|enum|extern|float|inline|int|long|restrict|short|signed|sizeof|static|struct|typedef|union|unsigned|void)\>" color green "\<([[:lower:]][[:lower:]_]*|(u_?)?int(8|16|32|64))_t\>" color green "\<(_(Alignas|Alignof|Atomic|Bool|Complex|Generic|Imaginary|Noreturn|Static_assert|Thread_local))\>" color green "\<(class|explicit|friend|mutable|namespace|override|private|protected|public|register|template|this|typename|using|virtual|volatile)\>" # Flow control. color brightyellow "\<(if|else|for|while|do|switch|case|default)\>" color brightyellow "\<(try|throw|catch|operator|new|delete)\>" color magenta "\<(break|continue|goto|return)\>" # Single-quoted stuff (characters, backslash escapes, hex and octal byte codes). color brightmagenta "'([^'\]|\\(["'\abfnrtv]|x[[:xdigit:]]{1,2}|[0-3]?[0-7]{1,2}))'" # GCC builtins. color cyan "__attribute__[[:blank:]]*\(\([^)]*\)\)|__(aligned|asm|builtin|hidden|inline|packed|restrict|section|typeof|weak)__" # Strings and names of included files. color brightyellow ""([^"]|\\")*"|#[[:blank:]]*include[[:blank:]]*<[^>]+>" # Preprocessor directives. color brightcyan start="^[[:blank:]]*#[[:blank:]]*(if(n?def)?|elif|warning|error|pragma)\>" end="(\`|[^\])$" color brightcyan "^[[:blank:]]*#[[:blank:]]*((define|else|endif|include(_next)?|line|undef)\>|$)" # Comments. color brightblue "//.*" color brightblue start="/\*" end="\*/" # Reminders. color brightwhite,yellow "\<(FIXME|TODO|XXX)\>" # Trailing whitespace. color ,green "[[:space:]]+$"

viernes, 12 de abril de 2024

ELF Basics Internal: Elf Basics.

/*Este material no lo hice yo. Source: oxhat.blogspot.com*/ In this post I will share details on ELF binary basics.

So let is begin with a very simple hello world program in C

#include stdio.h

int main(){printf("\nHello World\n");return 0;}

As I am on a 64 bit Linux system I will compile the binary for both 32bit and 64bit mode.

We will compile this code with gcc by issuing the command
for 64 bit -> gcc hello.c -o hello64
for 32 bit -> gcc hello.c -m32 -o hello32

, ( in case we get error we can install gcc multilib by issuing command sudo apt-get install gcc-multilib ) If we issue file command on the binary we created we would see the following output

pentest@ubuntu:~/Desktop$ file hello64 hello64: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=797fa6ea8a92b773eb5106c822a76788441ceac1, not stripped
pentest@ubuntu:~/Desktop$ file hello32 hello32: ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=ba188ad09ee9ff9ac774833b8a7c87d8afbc443a, not stripped

So let us try to understand what all these mean (we will analyze the result of 64 bit binary)
hello64: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=797fa6ea8a92b773eb5106c822a76788441ceac1, not stripped

hello64: This is the filename of the binary on which we are executing the file command
ELF - Executable and Linking Format or Executable and Linkable Format - This mean that the binary type is associated with mainly UNIX type operating system , like Linux, Solaris but also supports certain non UNIX operating system.
64bit - This gives us information tells about the architecture of the binary that it is 64 bit. So if it is a 32 bit binary it will be shown as 32 If we are in a 64bit machine and if we want to create a 32 bit binary we can pass the -m32 option
LSB - Least Significant Byte - It means the binary is in little endian format. In Intel architecture you will often find this as LSB. However in architectures like PowerPC , SPARC and so on it is possible to get this in big endian format i.e MSB ( Most Significant Byte )
Shared object - This result can either be Shared Object or Relocatable or Executable.
Let us see how these are different from each other and how we can generate them using gcc. The two terms which we are going to use here are PIC ( Position Independent Code ) and PIE ( Position Independent Executable) .
When we are planning to create a library that can be called by many process, we need to make it a PIC so that they can be loaded in the memory at any virtual address and just because they are position independent it can be accessed with relative offsets without worrying about the clashes of fixed locations in memory. We can create a PIE when Shared Object - By default the gcc compiler compiles the source code with -fPIC which makes address of the sections in the program relative to each other.
Executable - This mean this is not a PIE application. This loads with absolute address and thus we can find no reference of .plt.got sections here as the program is loaded in memory with fixed address .We can disable PIE with -no-pie option in gcc and thus we will get a executable object file.
Relocatable - This means this is just an object code without any linking of libraries or files that are necessary for the execution.
There are some steps involved when we make a program that can be executable ( Please Note: The term executable here means here is to make it run or execute and should not be confused with the above executable object type ).
To make an executable from source program the following process is involved.
Preprocessing -> Compilation -> Object File Creation -> Linking.

Normally in gcc we do in one step like gcc hello.c -o hello.out
but however we can do in 2 steps like gcc -c hello.c ; this will create an object file called hello.o This is how the disassembly of main looks like in object code.
0000000000000000 <main>:
0: 55 push rbp
1: 48 89 e5 mov rbp,rsp
4: 48 8d 3d 00 00 00 00 lea rdi,[rip+0x0] # b <main+0xb>
b: e8 00 00 00 00 call 10 <main+0x10>
10: 90 nop
11: 5d pop rbp
12: c3 ret

This program cannot run or do anything because the object code doesn't have the necessary linked objects or libraries required for execution. We can generate an executable binary from object code using the command
gcc hello.o -o hello-executable Now if we run objdump on the binary we can see lots of sections getting created with the location to the linkers.
This is how the disassembly of main looks like after linking
000000000000063a <main>:
63a: 55 push rbp
63b: 48 89 e5 mov rbp,rsp
63e: 48 8d 3d 8f 00 00 00 lea rdi,[rip+0x8f] # 6d4
<_IO_stdin_used+0x4>
645: e8 c6 fe ff ff call 510
<puts@plt>
64a: 90 nop
64b: 5d pop rbp
64c: c3 ret
64d: 0f 1f 00 nop DWORD PTR [rax]

Nota: Lo marcado con fondo rojo va al final de la línea anterior.
version 1 (SYSV) - This means that it uses version 1 and the target operating system for the binary is SYSTEM V. There can be other possible values for this for example FreeBSD, HP-UX , etc,. I didn't get enough resource from where I can find more details on the version 1 result and how it can affect something.

Dynamically linked, interpreter /lib/ld-linux.so.2, - It means that the binary uses some dynamically linked libraries. There is 2 possible values possible for this.Dynamically linked and Statically Linked.

Dynamically Linked - It means the linker actually uses a reference to load dynamically linked libraries in memory during execution of the program from the location /lib/ld-linux.so.2
We can verify it by running the ldd on the binary
pentest@ubuntu:~/Desktop$ ldd hello64
linux-vdso.so.1 (0x00007fff96bc2000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f425eb2a000)
/lib64/ld-linux-x86-64.so.2 (0x00007f425f11d000)

Statically Linked - It means that the binary has been packed along with the libraries. So there is no dynamically linked libraries inside it. So if a binary is compiled with -shared option in gcc it will create a statically linked binary. So if we run ldd command on the binary it will tell that there is not a dynamic executable.
pentest@ubuntu:~/Desktop$ ldd helloStatic
not a dynamic executable
There is a huge difference in sizes of the binary when compiled with -shared option ( i.e statically )
-rwxrwxr-x 1 pentest pentest 8296 Feb 6 08:55 hello64
-rwxrwxr-x 1 pentest pentest 844704 Feb 7 09:28 helloStatic
At this point you might feel confused between the relocation of the binary that we discussed before and the linking which we are discussing now. Well when we talk about shared object or executable or relocatable object type, then we are actually dealing how the program will be loaded in memory but when we talk about linking, then it is all about how the external libraries will be linked to binaries - either dynamically via some shared resources or statically by packing it with the actual binary. So we can make this statement , an executable object type may have dynamic linked libraries. Than means even if we disable PIE we can still get an executable with dynamically linked libraries.
pentest@ubuntu:~/Desktop$ file helloNOPIE
helloNOPIE: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=2d986bca273f541af7a48ffb51f4d5fd22177c22, not stripped

pentest@ubuntu:~/Desktop$ ldd helloNOPIE
linux-vdso.so.1 (0x00007ffffe990000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fcb5e8c0000) /lib64/ld-linux-x86-64.so.2 (0x00007fcb5ecb1000)
for GNU/Linux 3.2.0 - The minimum kernel version required to execute the binary BuildID[sha1]=ba188ad09ee9ff9ac774833b8a7c87d8afbc443a - This ID is assigned to the binary during the build phase. Possibly during the linking phase as this is not visible in object code after compilation.
not stripped - This means that the certain but not all debugging information are available. It can also have a value stripped in case we remove the debug symbols. A stripped binary is smaller in size than an not stripped binary. When we strip a binary we remove some extra sections from a binary that is not relevant or required for execution but was added for making debugging easy. We can verify using gdb and we can keep debug symbols in a binary by compiling with -g option
pentest@ubuntu:~/Desktop$ gcc hello.c -g -o helloDebugSymbols pentest@ubuntu:~/Desktop$ gdb -q ./helloDebugSymbols
Reading symbols from ./helloDebugSymbols...done.
(gdb) info functions
All defined functions: File hello.c:
void main();
Non-debugging symbols:
0x00000000000004e8 _init
0x0000000000000510 puts@plt
0x0000000000000520 __cxa_finalize@plt
0x0000000000000530 _start
0x0000000000000560 deregister_tm_clones
0x00000000000005a0 register_tm_clones
0x00000000000005f0 __do_global_dtors_aux
0x0000000000000630 frame_dummy
0x0000000000000650 __libc_csu_init
0x00000000000006c0 __libc_csu_fini
0x00000000000006c4 _fini
Now we will try the same with Stripped Binary and we can see that as there there is no debug symbols there is no reference to the function void main() as per source code. However there are still certain debug information available. For example I can find the address of main function.
pentest@ubuntu:~/Desktop$ gcc hello.c -o helloNoDebugSymbols pentest@ubuntu:~/Desktop$ gdb -q ./helloNoDebugSymbols
Reading symbols from ./helloNoDebugSymbols...(no debugging symbols found)...done.
(gdb) info functions
All defined functions:
Non-debugging symbols:
0x00000000000004e8 _init
0x0000000000000510 puts@plt
0x0000000000000520 __cxa_finalize@plt
0x0000000000000530 _start
0x0000000000000560 deregister_tm_clones
0x00000000000005a0 register_tm_clones
0x00000000000005f0 __do_global_dtors_aux
0x0000000000000630 frame_dummy
0x000000000000063a main
0x0000000000000650 __libc_csu_init
0x00000000000006c0 __libc_csu_fini
0x00000000000006c4 _fini
We can strip it down further using strip function
pentest@ubuntu:~/Desktop$ strip -s helloNoDebugSymbols -o helloNoDebugSymbolsStripped
pentest@ubuntu:~/Desktop$ gdb -q ./helloNoDebugSymbolsStripped
Reading symbols from ./helloNoDebugSymbolsStripped...(no debugging symbols found)...done.
(gdb) info functions
All defined functions:
Non-debugging symbols:
0x0000000000000510 puts@plt
0x0000000000000520 __cxa_finalize@plt
So that's all for this blog post. In my further posts I will talk in more details about each of the part of elf binary in more details

lunes, 25 de marzo de 2024

Algoritmos Recursivos vs Iterativos

Algoritmos Recursivos vs Iterativos En esta entrada, veremos, en lenguaje de programación C++, diferencias y ejemplos entre estos dos tipos de algoritmos: Los algoritmos recursivos, y los algoritmos iterativos. Veremos esto tomando como ejemplo la Sucesión de Fibonacci (0,1,1,2,3,5,8...). Para hayar un término n de la sucesión, tenemos esta función: F(n) = 0 si n= 0. F(n) = 1 si n= 1. y para cada numero se cunple que: F(n-1)+F(n-2) si n > 1 En resumen: cada término, es la suma de los dos anteriores. Salvo el término 0 y el 1, que son 0 y 1, respectivamente. Una función recursiva, es la que se llama a si misma. Para que una función recursiva tenga fin, ha de tener una condición, como en este ejemplo: "si n=0" o "si n=1". Veamos la función Fibonacci recursiva en C++: uint64_t fib_recursivo(uint64_t n){ if(n==0) return 0; if(n==1) return 1; return fib_recursivo(n-1) + fib_recursivo(n-2); } PD: uint64_t es lo mismo que unsigned long long int. En esta sencilla función, vemos claramente la definición de la serie de Fibonacci. N es el término de la serie que queremos conseguir. Ahora veamos la forma iterativa: uint64_t fib_iterativo(uint64_t n){ if(n==0) return 0; if(n==1) return 1; uint64_t a=0, b=1, c=0;; for(int i=2; i<=n; i++){ c = a + b; a = b; b = c; } return c; } En la iterativa, vamos generando los términos en orden hasta llegar al que buscamos. en la variable 'a', guardamos lo que sería f(n-2), y en 'b', f(n-1). Luego, con el ciclo, igualamos 'c' a 'a' + 'b' ( f(n-2) + f(n-1) ). Entre los algoritmos iterativos y los recursivos, suele haber estas diferencias básicas: La forma recursiva, es mucho más lenta que la forma iterativa, especialmente para números "grandes" (Ej. Para N=100, fib_recursivo() tardará mucho en terminar) La forma recursiva suele ser más sencilla de realizar que la iterativa. Aunque esto depende de la sucesión/algoritmo que busquemos. A parte, os muestro otra función, parecida a la iterativa, pero con algunos cambios: uint64_t fib_mezcla(uint64_t n){ static vector v; if(!v.size()){ v.push_back(0); v.push_back(1); } if(v.size()<=n) for(uint64_t i=v.size(); i<=n; i++) v.push_back(v[i-1] + v[i-2]); return v[n]; } Esta, lo que hace es guardar los valores que obtiene (por el método iterativo) en un vector static. Al ser una variable static, no será borrada al acabar la función, lo que significa que guardará los valores que tiene cada vez q llamemos a la función. De esta manera, ahorramos tiempo, ya que no tenemos que calcular (salvo la primera vez), cada término de fibbonaci. A cambio, tiene un mayor gasto de memoria. Pero en este caso, dado que apenas guardará más de 87 términos (a partir de ahí se sale del tamaño de una variable de 64 bits), apenas notaremos su gasto de memoria. Aquí he hecho unas pruebas comparativas de las 3 funciones: En la primera prueba, se mide el tiempo que tarda en llamar 1 vez a la función para el término 40. Como podemos observar, el método recursivo tarda más de 4 segundos, mientras que los demás, apenas tardan unos milisegundos. En la segunda prueba, omito la función recursiva, ya que tardaría un tiempo o años en acabar. Aquí podemos ver lo que tardan los otros métodos al ser llamados 1.000.000 veces, para el término 85. Aquí es donde podremos apreciar la diferencia entre el método iterativo tradicional, y el método donde se guardan los valores. El método iterativo, se llama 1.000.000 veces, y las 999.999 veces hace todo el ciclo desde el 1 hasta el 85. En cambio, el otro método hace solo 1 vez el ciclo, y las otras 999.999 veces, simplemente retorna el valor guardado en el vector. Y hasta aquí este resumen sobre los pros y contras de las funciones recursivas e iterativas. En vuestros programas, os recomiendo poner un límite para las funciones recursivas que podrían tardar mucho, como la de fibonacci, para así evitar que el programa se detenga.

miércoles, 24 de enero de 2024

Ahorcado

/*Codigo posteado por satu en elhacker.net thread: fgets para enteros?*/

#include <stdio.h>
#include <string.h>

int main (){
char palabra [7]; char final [7];char car;
int cont;
memset (&final, '-', 6);final [6] = '\0';
printf ("Escribe una palabra (lenght <7 chars): ");
fgets (palabra, 7, stdin);palabra [6] = '\0';

while (strcmp (palabra, final) != 0){
while(getchar() != '\n')
printf ("\nEscribe una letra: ");
car = fgetc (stdin);

for (cont=0; cont<6; cont++)
if (car == palabra [cont])
final [cont] = car;printf ("%s\n", final);car = 0;}

printf ("Well done! ;)\n\n");
while(getchar() != '\n') getchar();
    return 0;
}

jueves, 21 de diciembre de 2023

Hay que evitar el uso de scanf()


/*Este texto no es de mi autoria*/

Hola Gente!!

BUENO ESTO ES UNA EXPLICACIÓN DE PORQUE AVECES EL SCANF SE COMPORTA DE MANERA EXTRAÑA. ESPERO QUE SE ENTIENDA,

voy explico porque el uso de scanf no es recomendable..
para empezar es un error decir que un programa lee del teclado en verdad lo que hace es leer de un area de memoria llamado "buffer de teclado" (no siempre es así, esto se puede manipular mediante la función  setvbuf y el modo _IOFBF, que especifica que lea hasta que el buffer esté lleno.) y el buffer del teclado es "buffer de linea" esto quiere decir que los datos que provienen del teclado se insertan linea por linea y no caracter a caracter . Es por eso que cuando leemos de ahí, por más que ingresemos muchos caracteres, hasta que no ingresamos el fin de línea (enter) el programa no lee nada y se queda trabado esperando que haya algo en el buffer.

si el buffer no está vacío, sí o sí hay al menos un fin de línea;
el buffer siempre tiene un carácter de fin de línea al final.

El gran problema con scanf es que no siempre leerá el fin de linea lo que nos lleva a que el buffer quede con basura, osea con caracteres no leídos los cuales la próxima vez que invoquemos a scanf los leerá e intentara limpiar el buffer ocasionando un salto de linea e impediendonos ingresar el dato requerido.  de mas esta decir que esto podría causar algunos problemas al programador.
scanf solo lee hasta que encuentre el formato que le especificamos, esto conlleva a otro gran problema ya que si nosotros le decimos que lea un entero (%i") y se le ingresan 2 enteros separados por un espacio scanf solo leerá hasta encontrar el formato especificado dejando al buffer sucio con ese entero de mas.
Otro problema que tenemos es que no hace casi ningún tipo de chequeo a la hora de verificar los datos ingresados si se le indica que se ingresara un entero y el usuario ingresa una letra esté hace una conversión a entero lo cual genera un problema.

en el siguiente segmento de programa intenten lo siguiente cuando les piede ingresar los datos pongan algo así como "50 10" (sin las comillas) y veran como el buffer quedara  sucio  con con el entero 10 entonces cuando se llama de nuevo a scanf "asimila" que 10 es lo que se ingreso y por eso no nos deja ingresar el dato e imprime el nuevo valor de i

#include <stdio.h>

int main(){
int i=0;
//pongan algo como 50 10
scanf("%d",&i); printf("%d\n",i);
scanf("%d",&i); printf("%d\n");//este numero sera 10 sin preguntar
return 0;}
scanf("%d",&i);printf("%d\n);


Siempre se puede usar

setbuf(stdin,NULL);

Aunque se recomienda usar fgets y sscanf:

fgets(buffer o variable donde se guarda,cantidad de caracteres,stdin); 

stdin significa entrada por teclado.buffer es un campo para reservar temporalmente algo, como puede ser una cadena.

fgets(buffer, 11,stdin); y fgets leera 11-1 caracteres siendo mas seguro que scanf. Scanf no comprueba lo que se ingresa, lo cual le hace vulnerable al buffer overflow. Se puede cambiar 11 por sizeof(buffer). 

De igual manera hay que ser cauteloso con strcat y strcopy,debe usarse strncat y strncpy con el 3er parametro que controla el ingreso de caracteres.

//con sscanf introducimos lo que tenemos en el buffer tanto en nombre como en edad    

PARA LEER ENTERO

#include <stdio.h>
#include <string.h>
int main(){
char buffer[13]={0};short int edad=0;
setbuf(stdin,NULL);
printf("Ingrese un numero: \n");
fgets(buffer,sizeof(buffer),stdin);
sscanf(buffer , %u", &edad );
printf("El numero es: %d\n",edad);
return 0;}

sábado, 16 de diciembre de 2023

Estructura con Switch

#include <stdio.h>     
struct Ficha {   
char Nombre[80];
int  Num_unidades;  
int Precio_unidad;  
int Estado;  // 0 = moroso; 1 = atrasado; 2 = pagado };     

typedef struct Ficha Fichas;     

int main(int argc, char** argv) { 
Fichas Cliente[100]; 
int i; 
char nombre[80];

for (i = 0; i < 99; i++)  {
if (nombre == Cliente[i].Nombre) {
printf ("%s", Cliente[i].Nombre);   
printf ("%i",Cliente[i].Num_unidades);   
printf ("%i", Cliente[i].Precio_unidad);   

 switch  (Cliente[i].Estado)     {    
case 0 : printf ("Moroso");         break;    
case 1 : printf ("Atrasado");         break;
case 2 : printf ("Pagado");         break;    };     
  }   }      return 0; } 

copiar matriz a otra(sin resolver)

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

void gen_matriz (int** nuevo, int matriz[20] [20]){
int j, k, y;int dup;int num_elem[20];
nuevo = (int**) calloc(20, sizeof(int*));

for (y = 0; y < 20; y++){
num_elem[y] = 0;

for (k = 0; k < 20; k++){
dup = 0;j = 0;

while ((j < 20) && !dup){
if (k != j){
dup = matriz[y][k] == matriz[y][j];
printf ("y=%i %i %i\n",y, j, dup);}
j++;}

printf ("dup %i\n", dup);

if (!dup){
num_elem[y]++;
if (nuevo[y] == NULL) nuevo[y] = (int*) malloc(sizeof (int));
else
nuevo[y] = (int*) realloc(nuevo[y], num_elem[y] * sizeof (int));
int indice = num_elem[y] - 1;
nuevo[y][indice] = matriz[y][k];
printf (" posicion %i %i : %i\n", y, k, nuevo [y] [indice]);}
                }

        }

for(y = 0; y < 20; y++)
for(k = 0; k < num_elem[y]; k++)
printf("nuevo[%i][%i] = %i\n", y, k, nuevo[y][k]);
}

Tres en raya

 #include <stdio.h> int main(){ char c1,c2,c3,c4,c5,c6,c7,c8,c9,movimiento,marcajugador; char jugar_otra; int turno_jugador; c1='1';c2='2';c3='3';c4='4';c5='5';c6='6';c7='7';c8='8';c9='9'; turno_jugador=1; bool juegoterminado(true),juego_ganado(true),movalido; do{ printf("\t\t\t\t||%c||%c||%c||\n",c1,c2,c3); printf("\t\t\t\t||+||+||+||\n"); printf("\t\t\t\t||%c||%c||%c||\n",c4,c5,c6); printf("\t\t\t\t||+||+||+||\n"); printf("\t\t\t\t||%c||%c||%c||\n",c7,c8,c9); printf("\t\t\t\t||+||+||+||\n\n");  if(turno_jugador==1)//Marca Jugador {marcajugador= 'X';} else{marcajugador= 'O';} printf("Jugador: %d Movimiento: ",turno_jugador);  do{ scanf("%c",&movimiento); movalido=true; //Checar movimientos if (movimiento == '1' && c1 == '1') {c1 = marcajugador;} 

else if (movimiento == '2' && c2 == '2'){c2 = marcajugador;} else if (movimiento == '3' && c3 == '3'){c3 = marcajugador;} else if (movimiento == '4' && c4 == '4'){c4 = marcajugador;} else if (movimiento == '5' && c5 == '5'){c5 = marcajugador;} else if (movimiento == '6' && c6 == '6'){c6 = marcajugador;} else if (movimiento == '7' && c7 == '7'){c7 = marcajugador;} else if (movimiento == '8' && c8 == '8'){c8 = marcajugador;} else if (movimiento == '9' && c9 == '9'){c9 = marcajugador;} else {printf("Movimiento Invalido, Intenta Otra Vez\n");} movalido = false;}while(!movalido);  juegoterminado=false; juego_ganado=true;  if (c1 != '1') { if (c2 == c1 && c3 == c1){juegoterminado = true;} if (c4 == c1 && c7 == c1) {juegoterminado = true;}}  if (c5 != '5'){ if (c1 == c5 && c9 == 5) {juegoterminado = true;} if (c2 == c5 && c8 == c5) {juegoterminado = true;} if (c4 == c5 && c6 == c5) {juegoterminado = true;} if (c3 == c5 && c7 == c5){juegoterminado = true;}}  if (c9 != '9') { if (c3 == c9 && c6 == c9){juegoterminado = true;} if (c7 == c9 && c8 == c9){juegoterminado = true;}}  if (c1 != '1' && c2 != '2' && c3 != '3' && c4 != '4' && c5 != '5' && c6 != '6' && c7 != '7' && c8 != '8' && c9 != '9' && !juegoterminado){ juegoterminado = true; juego_ganado = false;}  if (juegoterminado){ if (juego_ganado) {printf("Juagador: %d Gana!",turno_jugador);}                         // Imprimir Tablero printf("\t\t\t\t||%c||%c||%c||\n",c1,c2,c3); printf("\t\t\t\t||+||+||+||\n"); printf("\t\t\t\t||%c||%c||%c||\n",c4,c5,c6); printf("\t\t\t\t||+||+||+||\n"); printf("\t\t\t\t||%c||%c||%c||\n",c7,c8,c9); printf("\t\t\t\t||+||+||+||\n\n"); printf("Juego Terminado!"); printf("Jugar De Nuevo (Y/N)?"); scanf("%d",&jugar_otra);  if (jugar_otra == 'y'||jugar_otra == 'Y'){ juegoterminado = false; c1='1';c2='2';c3='3';c4='4';c5='5';c6='6';c7='7';c8='8';c9='9'; } turno_jugador=1;                 } else { if (turno_jugador == 1){turno_jugador = 2;} else {turno_jugador = 1;}                           }         } while (!juegoterminado); }

Simulador Sistema Operativo

 /***********************************************

 Nombre: Simulador Descripción: Primera parte de la creación de un simulador                          de sistema operativo RR. Fecha:13-01-09 Autor:Bruno Kröller da Silva ************************************************/  

// Cabecera de librerías 

#include <stdio.h>              // Uso de printf,... 

#include <stdlib.h>             //Uso de atoi,... 

#include <unistd.h>             //Uso de waitpid,... 

#include <sys/types.h>  // Uso de rand,... 

#include <string.h>             // Uso de  //VARIABLES GLOBALES #define N_MAX 15

 #define T_MAX 30 

#define T_MIN 5 

 //FUNCIONES int hijos(int n_maximo,int quantum,int tiempo); 

 // Función main que recive parametros de entrada int main (int argc, char *argv[]){

  // Variables de entorno. int resultado; // 0 error 1 correcto int tiempo;int n_maximo;int quantum;  //Valores predefinidos de las variables. n_maximo=5;quantum=80;resultado=0;  /* Controlamos que el número de argumentos sea correcto, en caso contrario no empezamos a ejecutar las funciones principales.*/ if(argc==1 || argc==3 || argc==5 || argc>6){ printf("\t\n Error, el formato es n p m q t");} else{ /*Si entran dos argumentos, nombre + tiempo*/ if(argc==2){ tiempo=atoi(argv[2]); if(1<=tiempo<=120){resultado=1;}}  /*Si entran 4 argumentos, nombre+ numero+ p + tiempo o nombre+ quantum+ q + tiempo*/ else if(argc==4){ tiempo=atoi(argv[4]); if(*argv[2]=='p' && 1<=tiempo<=120) { n_maximo=atoi(argv[1]); resultado=1; } if(*argv[2]=='q' && 1<=tiempo<=120){ quantum=atoi(argv[1]); resultado=1; }}  /*Si entran argumentos, nombre+ numero+ p+ quantum+ q + tiempo*/ else if(argc==6){ tiempo=atoi(argv[6]); if(*argv[2]=='p' && *argv[4]=='q' && 1<=tiempo<=120){ n_maximo=atoi(argv[1]); quantum=atoi(argv[3]); resultado=1;}}  // SAlIDA DEl PROGRAMA if(resultado==1){ printf("\t\n Simulador: "); printf("\t\n       Numero maximo de programas: %d ",n_maximo); printf("\t\n       Quantum : %d",quantum); printf("\t\n       Tiempo de ejecución: %d ",tiempo); } else{ printf("\t\n Error al introducir los parametros:"); printf("\t\n [numero_prog] [p] [quantum] [q] [tiempo] ");} } return 0;}  int hijos(int n_maximo,int quantum,int tiempo){ int error; // 1 correcto, 0 error. pid_t pid_h; // Variable donde almacenaremos el pid del hijo int numero;int i;int tiempo_max;  //INICIALIZACIÓN DE VALORES i=0;error=1;  /*LANZAMIENTO DEL SISTEMA OPERATIVO*/ //Creamos un hijo pid_t fork(); //Pedimos que nos diga su pid pid_h=getpid(); //Comprobamos que el hijo se ha creado if(pid_h==-1){error=0;} else{ //Ejecutado por el padre if(pid_h!=0){waitpid(pid_h,NULL,0);} //Ejecutado por el hijo else{ //Ejecutar el S.O. //Aquí termina el hijo exit(0);}         }  /*LANZAMIENTO DE LA TEMPORIZACIÓN.*/ //Creamos un hijo pid_t fork(); //Pedimos que nos diga su pid pid_h=getpid(); //Comprobamos que el hijo se ha creado if(pid_h==-1){error=0;} else{ //Ejecutado por el padre if(pid_h!=0){waitpid(pid_h,NULL,0);} //Ejecutado por el hijo else{ sleep(tiempo); printf("\t\n Temporizador: "\ "Finalizado el tiempo de simulación "); //Aquí termina el hijo exit(0);}         }  /*LANZAMIENTO DE LA TEMPORIZACIÓN.*/ //CREARCIÓN DE LOS 10 HIJOS while(i<10){ srand(time(0)); //Generamos un numero no mayor que N_MAX //Le sumamos 1 para que empiece en 1. numero=1+rand()%(N_MAX); //Generamos el tiempo de espera de cada hijo. //Crea números en un intervalo de 5 a 30. tiempo_max=5+rand()%21; //Tiempo de espera para crear el siguiente hijo. sleep(numero); //CREAR HIJO pid_t fork(); } pid_h=getpid(); if(pid_h==0){ sleep(tiempo_max); printf("\n\t Simulador: "\ "Lanzando programa- Tiempo ejecución %d ",tiempo_max); exit(0);} //El padre espera a que todos los hijos mueran. wait(); return(error);}  /*CHULETA DE VARIABLES Valores mínimos y máximos de:                                   mínimo  máximo Tiempo          :               1               120 Quantum         :               20              200 Programas       :               1                5  numero esta entre [1,30]*/

domingo, 10 de diciembre de 2023

OpenGL en Dev++

/*Escrito el 6-agosto-2006*/
/*Este tutorial aborda la creación de una ventana en Windows
con un contexto gráfico OpenGL, pero a diferencia de los
tutoriales basados en GLUT o AUX, esta aplicación se
desarrollará a partir de las librerías de Windows, haciendo
todo “manualmente”. Surge la inquietud de ¿por qué hacer este
tutorial, si podría hacerse más fácilmente con GLUT, AUX o
cualquier otra librería?, la respuesta es porque este
tutorial permite conocer mejor la estructura de un programa de
Windows, que es útil si se necesita algo mas de control (y
problemas) sobre la aplicación.
Además, es divertido “ensuciarse” un poco las manos con el API
de Windows de bajo nivel.

PROGRAMANDO ORIENTADO A EVENTOS
Windows y en general los sistemas operativos GUI utilizan una
arquitectura orientada a eventos para manejar la interacción
usuario – sistema – aplicación de manera organizada y
eficiente. El modelo es bastante simple, cada vez que el
usuario realiza una acción, el sistema determina sobre que
aplicación se realizó y le envía un mensaje describiendo la
acción, el programa lee y procesa el mensaje, si es que este
le interesa (un clic sobre el menú por ejemplo) y realiza los
cambios pertinentes.
Un ejemplo con un clic podría ser como este*/

IMAGEN

/*En este caso la aplicación, por ejemplo un juego de
estrategia, averiguaría la posición en la que en la que se
encontraba el puntero cuando se hizo el clic y movería una
unidad a esta posición. Es importante anotar que este modelo
fue creado para ser eficiente en uso de recursos cuando
varias aplicaciones corren “simultáneamente”, un videojuego
por el contrario es una aplicación destinada a consumir
recursos por su naturaleza de aplicación en “tiempo real”, la
razón de esto es que aunque el usuario se tome una siesta, el
videojuego está realizando cálculos, reproduciendo sonidos,
dibujando la pantalla, la IA esta intentando conquistar el
mundo, etc.

LA APLICACION
Las siguientes estructuras y tipos de datos serán usados en
el desarrollo de la aplicación:

HDC: Handle to Device context. Es el identificador de un
Device Context. Un Device Context es una aplicación a través
de la cual tienen que pasar las operaciones de dibujo, para
que estas puedan ser mostradas en un dispositivo físico, en
este caso particular un monitor.

PFD: Píxel Format Descriptor. Estructura que describe las
propiedades de los píxeles en una superficie de dibujado.

HWND: Handle to Window. Es el identificador de una ventana.

WNDCLASS: Estructura que contiene los datos necesarios para
el registro de una clase ventana, como son su nombre, estilo,
función de paso de mensajes, icono, cursor, entre otros.

HGLRC: Handle to GL Render Context. Es el identificador de un
Render Context, similar al HDC, solo que este no es usado por
GDI sino por OpenGL para realizar el dibujado sobre la pantalla.

Es posible dividir esta aplicación en 4 tareas principales:

Crear la ventana win32.
Preparar la ventana y ligarla a OpenGL.
Inicializar OpenGL.
Hacer el ciclo de mensajes y dibujado.

Las macros y variables del programa son:*/

#define VENTANA_ANCHO 640
#define VENTANA_ALTO  480
HDC     hdc=NULL;
HGLRC  hglrc=NULL;
HWND  hWnd=NULL;
HINSTANCE hInstance

/*CREAR LA VENTANA WIN32
Para crear la ventana es necesario llenar el WNDCLASS,
registrarlo y finalmente crear la ventana. El WNDCLASS */
    WNDCLASS    Cwnd;
    hInstance      = GetModuleHandle(NULL);
    Cwnd.style    = CS_OWNDC;
    Cwnd.lpfnWndProc    = (WNDPROC) WndProc;
    Cwnd.cbClsExtra       = 0;
    Cwnd.cbWndExtra     = 0;
    Cwnd.hInstance        = hInstance;
    Cwnd.hIcon    = NULL;
    Cwnd.hCursor            = LoadCursor(NULL, IDC_ARROW);
    Cwnd.hbrBackground   = NULL;
    Cwnd.lpszMenuName   = NULL;
    Cwnd.lpszClassName   = "OpenGL";
    RegisterClass(&Cwnd);

hWnd=CreateWindow("OpenGL","Hola Mundo",
WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,100,
100,VENTANA_ANCHO,VENTANA_ALTO,NULL,NULL,hInstance,NULL);

/*
La función GetModuleHandle() obtiene un identificador para la
aplicación actual. Los datos de la estructura WNDCLASS son
los siguientes:

WNDCLASSS{
UINT style : Estilo de la aplicación, en este caso se quiere
un DC propio (CS_OWNDC)

WNDPROC lpfnWndProc : Manejador de mensajes
int cbClsExtra : Bytes extra para la estructura
int cbWndExtra : Bytes extra para la clase

HINSTANCE hInstance : Instancia de la aplicación que crea la
ventana

HICON hIcon : Icono de la ventana, al ser NULL, windows
provee el icono por defecto.

HCURSOR hCursor : Cursor usado al pasar sobre la ventana,
LoadCursor(NULL,IDI_ARROW) es el icono por defecto

HBRUSH hbrBackground : Color del fondo de la ventana,debido a
que todo el espacio de la ventana va a estar ocupado por la
ventana, este valor se provee como NULL

LPCTSTR lpszMenuName : Nombre del recurso que identifica el
menú de la aplicación, es NULL ya que no se utiliza menú.

LPCTSTR lpszClassName : Nombre de la clase que se usara al
registrarla.}

El manejador de mensajes al que hace referencia es en este
caso uno muy simple:*/

LRESULT CALLBACK WndProc
(HWND   hWnd,UINT uMsg,WPARAM wParam,LPARAM    lParam){
switch (uMsg){
case WM_CLOSE:
{PostQuitMessage(0);return 0;}}
return DefWindowProc(hWnd,uMsg,wParam,lParam);}

/*Las entradas de esta función son:

HWND hWnd : Identificador de la ventana que recibe el mensaje
UINT uMsg : El mensaje
WPARAM wParam : Información adicional sobre el mensaje
LPARAM lParam : Información adicional sobre el mensaje

Esta función solo intercepta un mensaje, aquel que es
enviado por el sistema para indicar a la aplicación que debe
cerrarse (WM_CLOSE) y si es cualquier otro mensaje lo envía
al DefWindowProc().
RegisterClass() registra una clase ventana, con los
parámetros dados por un WNDCLASS, en este caso CWnd.
Es hora de crear una ventana a partir de la clase creada con
el RegisterClass(), para esto se utiliza la función
CreateWindow() cuyos parámetros son los siguientes:

HWND CreateWindow(
LPCTSTR lpClassName : Nombre de la clase a partir de la cual
se crea la ventana
LPCTSTR lpWindowName : Titulo de la ventana.
DWORD dwStyle : Estilo de la ventana, en este caso con
titulo y borde (WS_OVERLAPED)
int x, : Posición x de la ventana
int y : Posición y de la ventana
int nWidth : Ancho de la ventana
int nHeight : Alto de la ventana
HWND hWndParent : Identificador de la ventana “padre”, en
este caso NULL, ya que no tiene HMENU menú : Identificador
del menú de la ventana, en este caso NULL, ya que no tiene
HINSTANCE hInstance : Identificador de la aplicación
poseedora de la ventana, en NT/2000/XP este valor es ignorado
LPVOID lpParam : Cadena con el parámetro a pasar al llamar
el mensaje WM_CREATE. En este NULL, ya que no hay ningun
parámetro a pasar)

 PREPARAR LA VENTANA Y LIGARLA A OPENGL.
Ahora es necesario:*/
GLuint  PixelFormat;
static  PIXELFORMATDESCRIPTOR pfd=
{sizeof(PIXELFORMATDESCRIPTOR),1,
PFD_DRAW_TO_WINDOW |PFD_SUPPORT_OPENGL |PFD_DOUBLEBUFFER,
PFD_TYPE_RGBA,32,0,0,0,0,0,0,0,0,0,0,0,0,0,32,0,0,0,0,0,0,0};

    hdc=GetDC(hWnd);
    PixelFormat=ChoosePixelFormat(hdc,&pfd);
    SetPixelFormat(hdc,PixelFormat,&pfd);
    hglrc=wglCreateContext(hdc);
    wglMakeCurrent(hdc,hglrc);
/*
El PIXELFORMATDESCRIPTOR tiene los siguientes datos:

PIXELFORMATDESCRIPTOR {
WORD nSize : Tamaño de la estructura
WORD nVersion : Versión de la estructura, siempre es 1

DWORD dwFlags : Propiedades del buffer de píxeles, en este
caso dibujar sobre una ventana (PFD_DRAW_TO_WINDOW), soporte
a OpenGL (PFD_SUPPORT_OPENGL) y doble buffer (PFD_DOUBLEBUFFER)

BYTE iPixelType : La forma de describir los píxeles, en este
caso como RGBA (PFD_TYPE_RGBA)

BYTE cColorBits : Tamaño de un píxel individual en bits, en
este caso 32 que es el mas común
BYTE cRedBits : Ignorado
BYTE cRedShift : Ignorado
BYTE cGreenBits : Ignorado
BYTE cGreenShift : Ignorado
BYTE cBlueBits : Ignorado
BYTE cBlueShift : Ignorado
BYTE cAlphaBits : Ignorado
BYTE cAlphaShift : Ignorado
BYTE cAccumBits : Ignorado
BYTE cAccumRedBits : Ignorado
BYTE cAccumGreenBits : Ignorado
BYTE cAccumBlueBits : Ignorado
BYTE cAccumAlphaBits : Ignorado

BYTE cDepthBits : Bits para el buffer de profundidad, pueden
ser 16 o 32 como en este caso.

BYTE cStencilBits : Ignorado
BYTE cAuxBuffers : Ignorado
BYTE iLayerType : Ignorado
BYTE bReserved : Ignorado
DWORD dwLayerMask : Ignorado
DWORD dwVisibleMask : Ignorado
DWORD dwDamageMask : Ignorado
}

GetDC() obtiene el Device Context asociado a la ventana
identificada por hWnd.

ChoosePixelFormat() utiliza dos parámetros, el hdc sobre el
cual se buscara un formato de píxeles compatible y el pfd que
especifica el formato deseado por la aplicación. Esta función
devuelve el formato de píxeles mas cercano encontrado, con
respecto al pfd.

SetPixelFormat() utilizar tres parámetros, el hdc sobre el
cual se va a establecer el formato de píxeles, un entero, el
PixelFormat, donde esta guardado el índice a dicho formato de
píxeles y el pfd de referencia que se uso para encontrar el
formato, el ultimo valor no afecta el funcionamiento de esta
función, ya que se utiliza solamente como registro.

wglCreateContext() crea un contexto de dibujo para OpenGL, a
partir de un contexto de dibujo de GDI.

wglMakeCurrent() elige un HGLRC sobre el cual se va a dibujar
los OpenGL, esto es debido a que una aplicación puede tener
varios contextos de dibujo, pero solo puede operar un proceso
sobre un contexto a la vez.

INICIALIZAR OPENGL
La inicialización de OpenGL es en este caso bastante simple y
más bien utilitaria, es realizada por las siguientes líneas de
código:*/

glClearColor(0.0f, 0.0f, 0.0f, 0.5f);
glMatrixMode (GL_PROJECTION);
glViewport (0, 0, VENTANA_ANCHO , VENTANA_ALTO);
gluPerspective(45.0f,VENTANA_ANCHO/VENTANA_ALTO,0.1f,100.0f);
gluLookAt( 0,0,16,  0,0,0, 0,1,0);
glMatrixMode (GL_MODELVIEW);
glLoadIdentity();

/*
glClearColor() establece el color de fondo
glMatrixMode() escoge una matriz para operar sobre ella.
Primero se elige la de proyección (GL_PROJECTION)

glViewport() establece el tamaño del marco de dibujo de OpenGL

gluPerspective() establece el frustrum, en este caso apertura
de 45, aspecto de 640/480, plano mas visible a 0.1 de
distancia y mas lejano a 100.

gluLookAt() posiciona la "cámara" (en realidad hace
transformaciones sobre la matriz proyección. Los parámetros
están agrupado de a 3 (x, y, z) y representan la posición de
la camara, el punto al que mira y que vector es considerado
"hacia arriba"

Finalmente se vuelve al modo de matriz GL_MODELVIEW que es
el utilizado para dibujar las primitivas.

HACER EL CICLO DE MENSAJES Y DIBUJADO
El ciclo de mensajes se encarga de revisar constantemente los
mensajes, en busca de alguno de interés para la aplicación,
de no haber mensajes, se dibuja la escena de OpenGL. El
código es así
*/

MSG mensaje;
BOOL continuar=TRUE;
while(continuar){

if (PeekMessage(&mensaje,NULL,0,0,PM_REMOVE)){
if (mensaje.message==WM_QUIT){continuar=FALSE;}
else{
TranslateMessage(&mensaje);
DispatchMessage(&mensaje);
}}
else{
render();
SwapBuffers(hdc);
}}

/*
La variable continuar indica cuando el ciclo debe detenerse,
cuando el usuario o el sistema decidan cerrar la aplicación,
bien sea con la X sobre la barra de la ventana, con el método
abreviado, mediante el administrador de aplicaciones, etc.
En algunos ejemplos se obvia esta variable al hacer un ciclo
while(1) y utilizando un break; en caso de recibir el mensaje.

PeekMessage() busca y almacena un mensaje de la pila de
mensajes de la aplicación. Si tal mensaje existe lo almacena
en el primer parámetro y devuelve TRUE, de lo contrario
devuelve FALSE. El ultimo parámetro (PM_REMOVE) le indica a la
función al leer un mensaje debe borrarlo de la pila de mensajes.

En este caso solo estamos observando el mensaje WM_QUIT, que
indica que el WndProc llamo la función PostQuitMessage(), es
decir que intercepto algún mensaje de salida de la aplicación.

Si no es este mensaje, se vuelve a colocar en la pila de
mensajes mediante las funciones TranslateMessage() y
DispatchMessage, para que este pueda ser leído por el
wndProc() creado anteriormente o por el manejador de mensajes
por defecto (DefWindowProc()).

Finalmente si no hay ningún mensaje por leer en la pila de
mensajes, se hace el dibujado(render()) y se cambia de buffer
(SwapBuffers()). El código del render() es bastante simple y
pinta un triangulo
*/

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBegin(GL_TRIANGLES);
glColor3f(0.0f,0.0f,1.0f);
glVertex3f(3.0f,-2.0f,0.0f);
glVertex3f(0.0f,1.0f,0.0f);
glVertex3f(-3.0f,-2.0f,0.0f);
glEnd();

/*
glClear() limpia los buffers pasados como parámetro de acuerdo
al color de limpiado (negro) y entre las funciones glBegin() y
glEnd() esta la especificación de un triangulo de color azul

El codigo entero*/
#include <windows.h>
#include <gl\gl.h>
#include <gl\glu.h>
#pragma comment(lib,"opengl32.lib")
#pragma comment(lib,"glu32.lib")
#define VENTANA_ANCHO 640
#define VENTANA_ALTO  480

HDC   hdc=NULL;
HGLRC      hglrc=NULL;
HWND        hWnd=NULL;
HINSTANCE   hInstance;

void inicializarGL(void){
glClearColor(0.0f, 0.0f, 0.0f, 0.5f);
glMatrixMode (GL_PROJECTION);
glViewport (0, 0, VENTANA_ANCHO , VENTANA_ALTO);
gluPerspective(45.0f,VENTANA_ANCHO/VENTANA_ALTO,0.1f,100.0f);
gluLookAt( 0,0,16,  0,0,0, 0,1,0);
glMatrixMode (GL_MODELVIEW);
glLoadIdentity();
    }

void render(void){
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBegin(GL_TRIANGLES);
glColor3f(0.0f,0.0f,1.0f);
glVertex3f(3.0f,-2.0f,0.0f);
glVertex3f(0.0f,1.0f,0.0f);
glVertex3f(-3.0f,-2.0f,0.0f);
glEnd();
    }

void deInicializar(void){
wglMakeCurrent(NULL,NULL);
wglDeleteContext(hglrc);
ReleaseDC(hWnd,hdc);
DestroyWindow(hWnd);
UnregisterClass("OpenGL",hInstance);
    }

LRESULT CALLBACK WndProc
(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam){
switch (uMsg){
case WM_CLOSE:
{
PostQuitMessage(0);
return 0;
}}
return DefWindowProc(hWnd,uMsg,wParam,lParam);}

int WINAPI WinMain
(HINSTANCE hinst,HINSTANCE hinstAnterior,
LPSTR cadenaDeComandos,int parametroVentana){
        MSG  mensaje;
        BOOL    continuar=TRUE;
        GLuint  PixelFormat;
        WNDCLASS    Cwnd;

        hInstance         = GetModuleHandle(NULL);
   Cwnd.style      = CS_OWNDC;
   Cwnd.lpfnWndProc    = (WNDPROC) WndProc;
   Cwnd.cbClsExtra  = 0;
   Cwnd.cbWndExtra  = 0;
   Cwnd.hInstance    = hInstance;
   Cwnd.hIcon      = NULL;
   Cwnd.hCursor        = LoadCursor(NULL, IDC_ARROW);
   Cwnd.hbrBackground  = NULL;
   Cwnd.lpszMenuName   = NULL;
   Cwnd.lpszClassName  = "OpenGL";
   RegisterClass(&Cwnd);

hWnd=CreateWindow("OpenGL","Hola Mundo",WS_OVERLAPPEDWINDOW
,100,100,VENTANA_ANCHO,VENTANA_ALTO,NULL,NULL,hInstance,NULL);

static  PIXELFORMATDESCRIPTOR pfd={
sizeof(PIXELFORMATDESCRIPTOR),1,
PFD_DRAW_TO_WINDOW |PFD_SUPPORT_OPENGL |PFD_DOUBLEBUFFER,
PFD_TYPE_RGBA,32,0,0,0,0,0,0,0,0,0,0,0,0,0,32,0,0,0,0,0,0,0};

hdc=GetDC(hWnd);
PixelFormat=ChoosePixelFormat(hdc,&pfd);
SetPixelFormat(hdc,PixelFormat,&pfd);
hglrc=wglCreateContext(hdc);
wglMakeCurrent(hdc,hglrc);
ShowWindow(hWnd,SW_SHOW);
SetForegroundWindow(hWnd);
SetFocus(hWnd);
inicializarGL();

while(continuar){

if (PeekMessage(&mensaje,NULL,0,0,PM_REMOVE)){
if (mensaje.message==WM_QUIT){continuar=FALSE;}
else{
TranslateMessage(&mensaje);
DispatchMessage(&mensaje);
}}

else{
render();
SwapBuffers(hdc);
}}

deInicializar();
return (mensaje.wParam);}

/*Por ultimo:
La aplicación luce así:

Captura

Aun este programa tiene que abarcar bastantes prestaciones no
contempladas, por dar simpleza (de ser posible eso) al
Hola Mundo. Entre estas prestaciones están:

Solicitar modo pantalla completa, que es muy común entre los
videojuegos.

Atender a los errores en todo el proceso de creación de la
ventana y asociación a OpenGL. Muchas de las funciones
utilizadas en la aplicación tienen un retorno que indica si
la función pudo llevarse a cabo o no.

Cambiar de tamaño la escena de OpenGL al cambiar el tamaño de
la ventana. Esto se hace añadiendo los estilos CS_VREDRAW y
CS_HREDRAW al WNDCLASS e interceptando el mensaje
WM_SYSCOMMAND, Wparam SC_SIZE.

Pausar la aplicación cuando la ventana es puesta detrás de
otra o minimizada.

También es importante aclarar que este ejemplo utiliza el
driver de software de OpenGL creado por Microsoft en la
década del 90 y que actualmente dicho driver no es mantenido y
es muy ineficiente. Para utilizar el driver de OpenGL que
proporciona la tarjeta gráfica, que tiene la ventaja de ser
acelerado por hardware y mantenido constantemente
(dependiendo de la tarjeta) se pueden usar las funciones
WGL-ARB aprobadas en el año 2000 y que hacen actualmente
parte del estándar, aunque siempre que se quieran usar, se
debe comprobar su disponibilidad, ya que dependen de la
implementación del estándar.

Finalmente es necesario señalar que esta es una de las maneras
mas complicadas de hacer una aplicación con OpenGL para
Windows, ya que se trabaja el API de win32 a muy bajo nivel y
las funciones para ligar OpenGL con GDI no han sido
actualizada en muchos años, de hecho el articulo relevante mas
reciente que se puede encontrar en MSDN acerca de OpenGL data
del año 1995.*/

miércoles, 6 de diciembre de 2023

Candado para Carpetas

/*
El Código no fue escrito por mí...

*/

#include <stdio.h>
#include <stdlib.h>

void fn_creditos()
{
printf("Escrito originalmente por 3hy y Mrobles\n"\
"Remasterizado por Sadistski.");
}

int main(){
int opcion;
printf("___Locker en C por 3hy! Basado en el Locker en Batch por Mrobles___\n"\
"> Solo funciona en Windows.Reeditado por Sadistski.\n\n"\
"Elija la opción:"\
"\n1. Crear la carpeta de locker (mismo directorio actual)"\
"\n2. Lockear una carpeta"\
"\n3. Desbloquear la carpeta"\
"\n4. Borrar la carpeta del locker"\
"\n5. Creditos"\
"\n6. Salir\n");
scanf("%i", &opcion);

switch(opcion){
case 1: printf(CUR CEL"La carpeta se creará donde está el programa....\n");
system("mkdir locker-folder");break;

case 2:
system("attrib +h +s locker-folder\n\n");break;fn_creditos();

case 3:
system("attrib -h -s locker-folder\n\n");break;fn_creditos();

case 4:
system("del locker-folder");break;fn_creditos();

case 5: fn_creditos();exit(0);break;
default: printf("Shit, has puesto algo mal...\n\n");break;}
return 0;}

miércoles, 29 de noviembre de 2023

Matriz dinamica

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define FILAS 2
#define COLS 2
int mayor0();
void rellenar(int **,int,int);

int main(void){
signed int **matriz={0};unsigned int i=0;
/*En caso de haber error al alojar:*/
if((matriz = malloc(sizeof *matriz * FILAS)) == NULL){perror("Malloc error.Filas. \n ");exit(EXIT_FAILURE);}
for(i = 0; i < FILAS; i++){
if((matriz[i] = malloc(sizeof *matriz[i] * COLS)) == NULL){
perror("Malloc error. Columnas.\n");
exit(EXIT_FAILURE);}
return EXIT_SUCCESS;}}

void rellenar(int **matriz,int fila, int columna){
int i; max=fila*columna;
for(i=0;i<max;i++){
*(*(matriz+i))=mayor0();}}

int mayor(){
int temp=-1;
do{
setbuf(stdin,NULL);
fgets(buffer,sizeof(buffer),stdin);
buffer[strcspn(buffer,"\n")]=0;
sscanf(buffer,"%d",&temp);
}while(temp<=0);

return temp;}

Arreglo rellenado

Algoritmo diferente del Arreglo rellenado escrito en CPP, esta vez en C.

/*************************************************
* Fichero: matrizPoC.c *
* Descripcion: Crea una matriz del tipo *
* 11111 *
* 12221 *
* 12321 *
* 12221 *
* 11111 *
* *
* Probado en Ubuntu 10.04. *
* Compilado en G++ *
* g++ -std=c99 matrizPoC.c *
* ***********************************************/

#include <stdio.h>

int main(){
int matriz[5][5];
for(int i=0;i<5;i++){
for(int j=0;j<5;j++){
//Condicion que se cumple para todo el borde pero tambien a la casilla central.
if(i*j==0||j%4==0||i%4==0)matriz[i][j]=1;

//Las demas casillas no cumplen con la condicion anterior.
else matriz[i][j]=2;
//En caso de ser la casilla central el valor debe ser 3.
if(i==2 && j==2) matriz[i][j]=3;
printf("%i",matriz[i][j]); //Imprimimos el valor por pantalla
}

//Saltamos la linea al terminar de trabajar la fila.
printf("\n");}
return 0;}

viernes, 24 de noviembre de 2023

bot telegram (5) telegram.h

 /*
 * Luis Alberto
 * Twitter @albertobsd
 */


#ifndef __TBOT_H_
#define __TBOT_H_
#include"jsmn.h"

enum chat_type{
chat_private = 0,
chat_group = 1,
chat_supergroup = 2,
chat_channel = 3};

typedef struct{
char *phone_number;
char *first_name;
char *last_name;
int user_id;
}Contact;

typedef struct{
char *file_id;
int duration;
char *mime_type;
int file_size;
}Voice;

typedef struct{
char *file_id;
int width;
int height;
int file_size;
} PhotoSize;

typedef struct{
int length;
PhotoSize **item;
}Photos;

typedef struct{
char *file_id;
PhotoSize *thumb;
char *file_name;
char *mime_type;
int file_size;
}Document;

typedef struct{
char *file_id;
int width;
int height;
PhotoSize *thumb;
int file_size;
}Sticker;

typedef struct{
int id;
enum chat_type type;
char *title;
char *username;
char *first_name;
char *last_name;
}Chat;

typedef struct{
int id;
char *first_name;
char *last_name;
char *username;
}User;

typedef struct{
float longitude;
float latitude;
}Location;

typedef struct{
char *file_id;
int width;
int height;
int duration;
PhotoSize *thumb;
char *mime_type;
int file_size;
}Video;

typedef struct Message {
        int message_id;
        User *from;
        int date;
        Chat *chat;
        User *forward_from;
        int forward_date;
        struct Message *reply_to_message;
        char *text;
        void *audio;
        Document *document;
        Photos *photo;
        Sticker *sticker;
        Video *video;
        Voice *voice;
        char *caption;
        Contact *contact;
        Location *location;
        User *new_chat_participant;
        User *left_chat_participant;
        char *new_chat_title;
        Photos *new_chat_photo;
        int delete_chat_photo;
        int group_chat_created;
        int supergroup_chat_created;
        int channel_chat_created;
        int migrate_to_chat_id;
        int migrate_from_chat_id;
}Message;

typedef struct  {
        char *ok;
        char *result;
        int error_code;
        char *description;
}Response;

typedef struct {
        int update_id;
        int type;
        union  {
                Message *message;
        }item;
}Update;

typedef struct  {
        int length;
        Update **list;
}Updates;

typedef struct  {
        char *file_id;
        int file_size;
        char *file_path;
}File;

typedef struct {
        char *file_id;
        int duration;
        char *performer;
        char *title;
        char *mime_type;
        int file_size;
}Audio;

typedef enum {
        TELEGRAM_ERROR_CURL_= 1,
        TELEGRAM_ERROR_API_RESPONSE = -10,
        TELEGRAM_ERROR_DEVELOPER = -20,
        TELEGRAM_ERROR_UNEXPECTED_TOKEN_TYPE  = -30,
        TELEGRAM_ERROR_UNEXPECTED_TOKEN_VALUE = -40,
        TELEGRAM_ERROR_API_404 = 404
}telegram_error_t;




/*
 * free telegram variables funtions
 */

Response* telegram_free_response(Response *res);
User* telegram_free_user(User *user);
Update* telegram_free_update(Update *update);
Updates* telegram_free_updates(Updates *updates);
Message* telegram_free_message(Message *message);
Document* telegram_free_document(Document *document);
Video* telegram_free_video(Video *video);
Voice* telegram_free_voice(Voice *voice);
Audio* telegram_free_audio(Audio *audio);
Sticker* telegram_free_sticker(Sticker *sticker);
Chat* telegram_free_chat(Chat *chat);
Photos* telegram_free_photos(Photos *photos);
Contact* telegram_free_contact(Contact *contact);
Location* telegram_free_location(Location *location);
PhotoSize* telegram_free_photosize(PhotoSize *photosize);



int telegram_init(char *);
int indexOf(char *str,char **ptr_strings);
int telegram_jsmn_init(jsmn_parser *parser,jsmntok_t **t,char *buffer,int *n);
int telegram_set_error(char *error_str,int error_code);
char * telegram_jsmn_get_token(jsmntok_t token,char *full);
void telegram_dump_token(jsmntok_t token,char *str);
char *telegram_makeurl(char *telegram_method);
char *telegram_get_error();
int telegram_is_error();
char* telegram_build_post(char **variables,char **values);


int telegram_reset_buffer();
size_t write_callback(void *ptr, size_t size, size_t nmemb, void *userdata );
off_t fsize(const char *filename);

/*
 * Telegram API methods
 */

User * telegram_getMe();
Updates * telegram_getUpdates();
Message* telegram_sendMessage(char *postdata);
File* telegram_getFile(char *file_id);
Message* telegram_sendDocument(char *filename,char **variables, char **valores);


/*
 * Telegram parse
 */

User * telegram_parse_user(char *str,int *count);
Response* telegram_parse_response(char *str,int *count);
Updates* telegram_parse_updates(char *str,int *count);
Update* telegram_parse_update(char *str,int *count);
Message* telegram_parse_message(char *str,int *count);
Chat* telegram_parse_chat(char *str,int *count);
PhotoSize* telegram_parse_photosize(char *str,int *count);
Photos* telegram_parse_photos(char *str,int *count);
Sticker* telegram_parse_sticker(char *str,int *count);
Voice* telegram_parse_voice(char *str,int *count);
Location* telegram_parse_location(char *str,int *count);
Contact* telegram_parse_contact(char *str,int *count);
Document* telegram_parse_document(char *str,int *count);
Video* telegram_parse_video(char *str,int *count);
File* telegram_parse_file(char *str,int *count);
char* telegram_downloadFile(File *file,char *name);
char* telegram_process_slash(char *str);
CURL* telegram_curl_init();


#endif /* __TBOT_H_ */

bot telegram (4) jsmn.h

 #ifndef __JSMN_H_
#define __JSMN_H_

#include <stddef.h>

#ifdef __cplusplus
extern "C" {
#endif

/**
 * JSON type identifier. Basic types are:
 *      o Object
 *      o Array
 *      o String
 *      o Other primitive: number, boolean (true/false) or null
 */
typedef enum {
        JSMN_UNDEFINED = 0,
        JSMN_OBJECT = 1,
        JSMN_ARRAY = 2,
        JSMN_STRING = 3,
        JSMN_PRIMITIVE = 4
} jsmntype_t;

enum jsmnerr {
        /* Not enough tokens were provided */
        JSMN_ERROR_NOMEM = -1,
        /* Invalid character inside JSON string */
        JSMN_ERROR_INVAL = -2,
        /* The string is not a full JSON packet, more bytes expected */
        JSMN_ERROR_PART = -3
};

/**
 * JSON token description.
 * @param               type    type (object, array, string etc.)
 * @param               start   start position in JSON data string
 * @param               end             end position in JSON data string
 */
typedef struct {
        jsmntype_t type;
        int start;
        int end;
        int size;
#ifdef JSMN_PARENT_LINKS
        int parent;
#endif
} jsmntok_t;

/**
 * JSON parser. Contains an array of token blocks available. Also stores
 * the string being parsed now and current position in that string
 */
typedef struct {
        unsigned int pos; /* offset in the JSON string */
        unsigned int toknext; /* next token to allocate */
        int toksuper; /* superior token node, e.g parent object or array */
} jsmn_parser;

/**
 * Create JSON parser over an array of tokens
 */
void jsmn_init(jsmn_parser *parser);

/**
 * Run JSON parser. It parses a JSON data string into and array of tokens, each describing
 * a single JSON object.
 */
int jsmn_parse(jsmn_parser *parser, const char *js, size_t len,
                jsmntok_t *tokens, unsigned int num_tokens);

#ifdef __cplusplus
}
#endif

#endif /* __JSMN_H_ */

Bot telegram (3) test_telegram.c

 #include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<curl/curl.h>
#include<sys/stat.h>
#include<errno.h>
#include"telegram.h"
#include"jsmn.h"

int main()      {
        Updates *updates;
        User *user;
        File *file;
        int i = 0;
        char *filename;
        telegram_init("1234567:fghjkl45678xcvbkcvbnzsxdcfvgbh");
        user = telegram_getMe();
        if(!telegram_is_error())        {
                printf("User: id: %i\nusername: %s\n",user->id,user->username);
                telegram_free_user(user);
        }
        else    {
                printf("%s\n",telegram_get_error());
        }
        updates = telegram_getUpdates();
        if(!telegram_is_error()){
                printf("updates: %i\n",updates->length);
                while(i < updates->length)      {
                        if(updates->list[i]->item.message->document)    {
                                printf("Document exits file_id : %s\n",updates->list[i]->item.message->document->file_id);
                                file = telegram_getFile(updates->list[i]->item.message->document->file_id);
                                if(!telegram_is_error())        {
                                        filename = telegram_downloadFile(file,updates->list[i]->item.message->document->file_name);
                                        printf("file name : %s\n",filename);
                                }
                                else    {
                                        printf("%s\n",telegram_get_error());
                                }
                        }
                        i++;
                }
                telegram_free_updates(updates);
        }
        else    {
                printf("%s\n",telegram_get_error());
        }
        return 0;
}