I'm learning about process management and shared memory, and I was wondering if someone could help me out. I'm trying to read in a large-ish text file (2MB) with a forked parent process and feed it to the corresponding child process to be ... well ... processed. However, my proof of concept mini program cannot READ the data I write into the shared memory. Calling 'capacity()' and 'length()' work fine, but actually attempting to retrieve the data stored there returns an empty string. I even tried copying the contents from the pointer into an array of characters, but still nothing. Any thoughts?
Program code:
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
using namespace std;
#define SHM_SIZE 2000000 // 2 MB of shared memory
int main(int argc, char* argv[])
{
string* data = (string*) mmap(NULL, SHM_SIZE, PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_ANONYMOUS, -1, 0);
printf("Shared memory capacity before reserve: %ld\n", data->capacity());
data->reserve(SHM_SIZE); // make sure string can use all available space
printf("Shared memory capacity after reserve: %ld\n", data->capacity());
switch(fork())
{
case -1:
printf("Something went wrong ... exiting program\n");
break;
case 0:
usleep(1000 * 1000 * 2); // force child to wait for sanity purposes
printf("\nChild capacity: %ld\n", data->capacity());
printf("Child contents: %s\n", data->c_str());
break;
default:
// Sample input ... file reading logic omitted for brevity
*data = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean leo elit, aliquam "
"vitae aliquam sed, rhoncus et mi. Aliquam erat volutpat. Phasellus non urna sit amet "
"enim tincidunt aliquam quis sit amet orci. Maecenas velit turpis, venenatis eu diam "
"vel, varius volutpat nulla. Nam mi massa, tristique eget imperdiet id, dictum ut urna. "
"Nulla id massa placerat, finibus purus quis, ornare neque. Vivamus eget varius ante. "
"Aenean varius ac neque quis ultricies. Donec vitae bibendum dolor, vitae tempor augue.";
printf("\nParent capacity: %ld\n", data->capacity());
printf("Parent contents: %s\n", data->c_str());
wait(NULL);
munmap(data, sizeof *data);
printf("\nHello world\n");
break;
}
return 0;
}
Output:
MacBook-Pro:sharedmem-test slehr$ ./sharedmem-mapred
Shared memory capacity before reserve: 22
Shared memory capacity after reserve: 2000015
Parent capacity: 2000015
Parent contents: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean leo elit, aliquam vitae aliquam sed, rhoncus et mi. Aliquam erat volutpat. Phasellus non urna sit amet enim tincidunt aliquam quis sit amet orci. Maecenas velit turpis, venenatis eu diam vel, varius volutpat nulla. Nam mi massa, tristique eget imperdiet id, dictum ut urna. Nulla id massa placerat, finibus purus quis, ornare neque. Vivamus eget varius ante. Aenean varius ac neque quis ultricies. Donec vitae bibendum dolor, vitae tempor augue.
Child capacity: 2000015
Child contents:
Hello world
MacBook-Pro:sharedmem-test slehr$
A std::string is likely to be some data structure with a size, a length, a pointer (or something similar). You can't expect its internal pointer to point to shared memory
with mmap-ed memory you should use raw pointers, e.g.
auto data = (char*) mmap(NULL, SHM_SIZE, PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_ANONYMOUS, -1, 0);
Of course you should test against failure:
if (data==(char*)MAP_FAILED) { perror("mmap"); exit(EXIT_FAILURE); };
Read again mmap(2)
You might consider shm_overview(7) (and look at sem_oveview(7) for synchronization)
Read Advanced Linux Programming
Related
I am trying to encrypt a text message with wincrypt. My code is however unpredictable. It doesn't encrypt/decrypt the whole plaintext but only a part of it. If i change the length of password (for example to "password123") it encrypts/decrypts a different amount of characters. Here is my code.
#include <windows.h>
#include <wincrypt.h>
#include <stdio.h>
int main()
{
const char* passw = "password12";
const char* toencrypt = "consectetur adipiscing elit. In tellus nisl, sodales non arcu quis, sagittis maximus orci cras amet.";
HCRYPTPROV hProv;
HCRYPTHASH hHash;
HCRYPTKEY hKey;
DWORD todwSize = (DWORD)strlen(toencrypt);
PBYTE pBuffer;
CryptAcquireContext(&hProv, NULL, MS_DEF_PROV, PROV_RSA_FULL, CRYPT_DELETEKEYSET);
CryptAcquireContext(&hProv, NULL, MS_DEF_PROV, PROV_RSA_FULL, CRYPT_NEWKEYSET);
CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash);
CryptHashData(hHash, (BYTE*)passw, strlen(passw), 0);
CryptDeriveKey(hProv, CALG_RC4, hHash, 0, &hKey);
//--------------------------------------------------------------------
CryptEncrypt(hKey, 0, TRUE, 0, NULL, &todwSize, todwSize);
pBuffer = (BYTE *)malloc(todwSize);
strcpy((char*)pBuffer, toencrypt);
CryptEncrypt(hKey, 0, TRUE, 0, pBuffer, &todwSize, todwSize);
PBYTE pBreturn = pBuffer;
const char* message = (const char*)pBreturn;
printf("%s", message);
//--------------------------------------------------------------------
DWORD dwSize = (DWORD)strlen(message);
PBYTE depBuffer;
depBuffer = (BYTE *)malloc(1460);
strcpy((char*)depBuffer, message);
CryptDecrypt(hKey, 0, TRUE, 0, depBuffer, &dwSize);
CryptDestroyKey(hKey);
CryptDestroyHash(hHash);
CryptReleaseContext(hProv, 0);
if(GetLastError() != 0)
{
printf("%d", GetLastError());
}
PBYTE depBreturn = depBuffer;
printf("%s", (const char*)depBreturn);
printf("\n%d", strlen(message));
return 0;
}
Thanks in advance for help!
think your code encrypt ok, but fail decrypt whole message because you use wrong length in call CryptDecrypt
your main error is DWORD dwSize = (DWORD)strlen(message); and strcpy((char*)depBuffer, message); but message is encrypted buffer, not 0 terminate ansi string. so you can not use strlen or strcpy on encrypted data - you have the encrypted data length returned by CryptEncrypt : todwSize - so you and must use with memcpy if you need copy encrypted buffer and pass todwSize as is to CryptDecrypt
also how noted Harry Johnston you incorrect use plain data/buffer size in call CryptEncrypt.
must be CryptEncrypt(hKey, 0, TRUE, 0, NULL, &(needSize = todwSize), 0) on first call (last parameter to CryptEncrypt dwBufLen must be 0 because you use NULL as buffer, and need use another variable DWORD needSize for get size of encrypted buffer and not overwrite size of plain text buffer (todwSize) then allocated needSize buffer, copy to it todSize and call CryptEncrypt(hKey, 0, TRUE, 0, pBuffer, &todwSize, needSize). but however for RC4 the encrypted and plain text size always equal. so needSize == todSize always in case RC4
also you need call CryptAcquireContext only once with flag CRYPT_VERIFYCONTEXT in your case. and always need check function result. so test code can be like this
int main()
{
const char* passw = "password12";
const char* toencrypt = "consectetur adipiscing elit. In tellus nisl, sodales non arcu quis, sagittis maximus orci cras amet.";
HCRYPTPROV hProv;
HCRYPTHASH hHash;
HCRYPTKEY hKey;
DWORD todwSize = (DWORD)strlen(toencrypt), needSize;
PBYTE pBuffer;
if (CryptAcquireContext(&hProv, NULL, MS_DEF_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
{
if (CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash))
{
if (CryptHashData(hHash, (BYTE*)passw, (DWORD)strlen(passw), 0) &&
CryptDeriveKey(hProv, CALG_RC4, hHash, 0, &hKey))
{
if (CryptEncrypt(hKey, 0, TRUE, 0, NULL, &(needSize = todwSize), 0))
{
memcpy(pBuffer = (BYTE *)_alloca(needSize), toencrypt, todwSize);
if (CryptEncrypt(hKey, 0, TRUE, 0, pBuffer, &todwSize, needSize))
{
if (CryptDecrypt(hKey, 0, TRUE, 0, pBuffer, &todwSize))
{
if (memcmp(pBuffer, toencrypt, strlen(toencrypt)))
{
__debugbreak();
}
}
}
}
CryptDestroyKey(hKey);
}
CryptDestroyHash(hHash);
}
CryptReleaseContext(hProv, 0);
}
return 0;
}
How can I save the text that the user enters in a IPAddress Control so that the next time it opens the app it will be kept?What is the best way to do it?
Use CIPAddressCtrl::GetAddress to retrieve address given in control.
Use CIPAddressCtrl::SetAddress to set address into control.
EDIT
You may use something like:
HKEY hkey;
CString strIP ="127.0.0.1";
if (RegOpenKeyEx(HKEY_CURRENT_USER,"Software\\YourApp",0,KEY_WRITE,&hkey) == ERROR_SUCCESS)
{
RegSetValueEx(hkey,"IPAddress",0,REG_SZ,(unsigned char*)strIP .GetBuffer(0),strIP .GetLength());
RegCloseKey(hkey);
}
for example you can save the IP adress in a file on your drive :
void CIPAdressDialogDlg::OnBnClickedOk()
{
// TODO : ajoutez ici le code de votre gestionnaire de notification de contrôle
// OnOK();
BYTE field0, field1, field2, field3;
m_Ip.GetAddress(field0, field1, field2, field3);
CString strIp = _T("");
strIp.Format(_T("%u.%u.%u.%u"), field0, field1, field2, field3);
CString strFilePath = _T("C:\\test.txt");
CFile theFile(strFilePath, CFile::modeWrite | CFile::modeCreate);
theFile.Write(strIp, strIp.GetLength() * sizeof(TCHAR));
}
I'm trying to implement a timeout on the recvfrom() function.
To do so, I use the select() function. I take the code from the great Internet, but don't know why, my program crash when I use it.
I launch this server in athread if that coudl help.
Here's what I try to do :
...
// Setup timeval variable
timeval timeout;
timeout.tv_sec = 5;
timeout.tv_usec = 0;
// Setup fd_set structure
fd_set fds;
FD_ZERO(&fds);
FD_SET(id_de_la_socket, &fds);
// Return value:
// -1: error occurred
// 0: timed out
// > 0: data ready to be read
int retval = select(id_de_la_socket+1, &fds, NULL, NULL, &timeout);
if(retval == -1){
printf("Error");
return NULL;
}
else if(retval == 0){
printf("Timeout");
return NULL;
}
else{
nombre_de_caractere=recvfrom(id_de_la_socket,buffer,1515,/*MSG_PARTIAL*/0,(struct sockaddr*)&information_sur_la_source,&tempo);
...
Before trying to implement the timeout, everything works fine, my recvfrom() was in block mode. So I think the problem come from this code that I add. Maybe it's a parameter of a function that I don't understand well.
Thanks for your help.
EDIT : Full code :
#include "serveur.h"
#include <unistd.h>
#include <fcntl.h>
serveur::serveur()
{
}
StructureSupervision::T_StructureSupervision* serveur::receiveDataUDP(){
WSADATA initialisation_win32;
int erreur;
int tempo;
int nombre_de_caractere;
char buffer[65535];
SOCKET id_de_la_socket;
SOCKADDR_IN information_sur_la_source;
erreur=WSAStartup(MAKEWORD(2,2),&initialisation_win32);
if (erreur!=0)
printf("\nDesole, je ne peux pas initialiser Winsock du a l'erreur : %d %d",erreur,WSAGetLastError());
else
printf("\nWSAStartup : OK");
id_de_la_socket=socket(AF_INET,SOCK_DGRAM,0);
if (id_de_la_socket==INVALID_SOCKET)
printf("\nDesole, je ne peux pas creer la socket du a l'erreur : %d",WSAGetLastError());
else
printf("\nsocket : OK");
information_sur_la_source.sin_family=AF_INET;
information_sur_la_source.sin_addr.s_addr = inet_addr("10.100.13.129"); // Ecoute sur toutes les IP locales
information_sur_la_source.sin_port=htons(4000); // Ecoute sur le port 4000
erreur=bind(id_de_la_socket,(struct sockaddr*)&information_sur_la_source,sizeof(information_sur_la_source));
if (erreur!=0)
printf("\nDesole, je ne peux pas ecouter ce port : %d %d",erreur,WSAGetLastError());
else
printf("\nbind : OK \n");
tempo=sizeof(information_sur_la_source); // Passe par une variable afin d'utiliser un pointeur
// Setup timeval variable
timeval timeout;
timeout.tv_sec = 5;
timeout.tv_usec = 0;
// Setup fd_set structure
fd_set fds;
FD_ZERO(&fds);
FD_SET(id_de_la_socket, &fds);
// Return value:
// -1: error occurred
// 0: timed out
// > 0: data ready to be read
ULONG NonBlock = 1; ioctlsocket(id_de_la_socket, FIONBIO, &NonBlock);
int retval = select(id_de_la_socket+1, &fds, NULL, NULL, &timeout);
if(retval == -1){
printf("Error");
return NULL;
}
else if(retval == 0){
printf("Timeout");
return NULL;
}
else{
nombre_de_caractere=recvfrom(id_de_la_socket,buffer,1515,/*MSG_PARTIAL*/0,(struct sockaddr*)&information_sur_la_source,&tempo);
buffer[nombre_de_caractere]=0; // Permet de fermer le tableau apr�s le contenu des data, car la fonction recvfrom ne le fait pas
//printf("\nVoici les donnees : %s",buffer);
StructureSupervision::T_StructureSupervision *structureReception = (StructureSupervision::T_StructureSupervision *) buffer;
std::cout << "Voici le numero de Statut Ground Flight : " << structureReception->SystemData._statutGroundFlight;
erreur=closesocket(id_de_la_socket);
if (erreur!=0)
printf("\nDesole, je ne peux pas liberer la socket du a l'erreur : %d %d",erreur,WSAGetLastError());
else
printf("\nclosesocket : OK");
// ********************************************************
// Quitte proprement le winsock ouvert avec la commande WSAStartup
// ********************************************************
erreur=WSACleanup(); // A appeler autant de fois qu'il a �t� ouvert.
if (erreur!=0)
printf("\nDesole, je ne peux pas liberer winsock du a l'erreur : %d %d",erreur,WSAGetLastError());
else
printf("\nWSACleanup : OK");
return structureReception;
}
}
Thanks for your help, the problem was : This program runs in a loop, so I was opening and closing the socket at the wrong time.
I am learning OS development with C/C++ and i am using fork() method to experiment with process. I have the following code like this:
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv) {
fork(); //create a child process, currently total is 1 parent, 1 child
fork(); //create a child process,currently total is 2 parents, 2 child
pid_t pid;
if((pid=fork()) == 0) { //fork() and assign to pid, now has 4 parents, 4 childs
printf("I am the child: %u\n", getpid());
else {
printf("I am the parent: %u and my child is: %u\n", getpid(), pid);
}
}
When i compile it, and run it, it shows 4 parents and 4 children as i expected, however the output looks strange to me (notice the bolded line below where i get the output after user#slacker:~$).
user#slacker:~$ gcc forktest.c -o forktest
user#slacker:~$ ./forktest
I am the parent: 1183 and my child is: 1186
user#slacker:~$ I am the parent: 1184 and my child is: 1188
I am the parent: 1185 and my child is: 1189
I am the parent: 1187 and my child is: 1190
I am the child: 1186
I am the child: 1189
I am the child: 1190
I am the child: 1191
When i tried with 3 fork(), the output is even stranger. Can someone explain to me please?
fork fork fork
1183----+---------------+----------------+-------------------->
| | |
| | 1186 +-------------------->
| |
| 1185 +----------------+-------------------->
| |
| 1189 +-------------------->
|
1184 +---------------+----------------+-------------------->
| |
| 1188 +-------------------->
|
1187 +----------------+-------------------->
|
1190 +-------------------->
created with http://www.asciiflow.com/#Draw
I need to find out the name of the OU that the local computer (that is connected to the Active Directory) belongs to using WinAPI/C++. Any ideas?
In theory, this is fairly simple: connect to the server with ADsOpenObject, instantiate an IDirectorySearch and invoke its ExecuteSearch method, then use GetFirstRow and GetNextRow to walk through the result data (but for this query, you'll only expect one row).
In reality, however, all of this is COM -- so expect those half dozen (or so) function calls to be pretty much lost in at least a hundred lines of COM-cruftiness (and by the time the code is solid and robust, don't be surprised if it's closer to 1000 lines, most of which have no noticeable connection to Active Directory).
I should add that there are almost certainly other ways to do this -- as I recall, MS provides at least two or three different ways to access LDAP-type data. When I wrote some code for this, I initially tried to find which would be the cleanest, but gave up in frustration. There seemed to be no hope for cleanest -- at least at that time, I settled for "ugly but somewhat documented".
For a simple WINAPI (not COM) way to acces Active Directory in C or C++ see Lightweight Directory Access Protocol
void AfficheErreurLdap(char *fonction, ULONG rc);
/*
*
* Fonction d'entrée du programme
*
*/
void main(int argc, char* argv[])
{
LDAP *pSessionLdap; // Pointeur vers la session LDAP
char *pHote; // Pointeur vers la chaîne représentant le nom de l'hôte
char *pUtilisateur; // Pointeur vers la chaîne représentant l'utilisateur
char *pMotDePasse; // Pointeur vers la chaîne représentant le mot de passe
char *pRacineLdap; // Pointeur vers la racine Ldap
ULONG rc; // Récupération du code de retour des appels
LDAPMessage *pResultat; // Pointeur vers le message résultat de la réquête LDAP
LDAPMessage *pEntree; // Utilisée lors du parcours du résultat pour l'affichage
char *pDN; // Pointeur vers le DN d'une entrée du résultat
char *pAttribut; // Pointeur vers la chaîne représentant l'attribut
BerElement *pBer = NULL;// "curseur" interne à l'API LDAP pour le parcours des elts
char **pValeurs; // Valeurs de l'attribut lors de l'affichage du résultat
int i; // Indice pour la parcours des valeurs d'attribut
/* Analyse des Paramètres de lancement et affichage d’un message d’erreur si incorrect */
if (argc != 5)
{
fprintf(stderr,"Syntaxe :\n\tex_cldap_1 Hote Utilisateur MotDePasse RacineLdap\n");
exit (1);
}
/* Récupération des paramètres des lancement */
pHote = argv[1];
pUtilisateur = argv[2];
pMotDePasse = argv[3];
pRacineLdap = argv[4];
/* Ouverture de la session LDAP et récupération du handle de session */
pSessionLdap = ldap_open( pHote, 389); /* 389 est le numéro de port standard LDAP */
if ( pSessionLdap == NULL )
{
// En cas d'erreur : affichage du message d'erreur adéquat
perror( "ldap_open" );
exit( 2 );
}
printf("Ouverture de la session réalisée\n");
/* Authentification du client */
/* Pour l'exemple, l'authentification est faite en tant qu'anonyme */
rc = ldap_simple_bind_s(pSessionLdap, pUtilisateur, pMotDePasse);
if ( rc != LDAP_SUCCESS )
{
// Erreur lors de l'authentification, on termine après affichage d'un message
AfficheErreurLdap("ldap_simple_bind_s", rc);
exit( 3 );
}
printf("Authentification réalisée\n");
/* */
/* Recherche des données dans l'annuaire */
/* */
rc = ldap_search_s(pSessionLdap, // Session LDAP
pRacineLdap, // Base de la recherche
LDAP_SCOPE_SUBTREE, // Sccpe : LDAP_SCOPE_BASE, LDAP_SCOPE_ONELEVEL, LDAP_SCOPE_SUBTREE
"(objectClass=*)", // Filtre de recherche
NULL, // Attributs que l'on souhaite visualiser
0, // Indique si l'on souhaite uniquement les types (1) ou
// Les attributs et les valeurs (0)
&pResultat ) ; // Pointeur vers le résultat
if (rc != LDAP_SUCCESS )
{
// Erreur lors de la recherche, on termine après affichage du message d'erreur
AfficheErreurLdap("ldap_search_s", rc);
exit (4);
}
printf("Requête réalisée\n");
/* On va maintenant parcourir le résultat et afficher les couples */
/* attributs, valeurs */
pEntree = ldap_first_entry( pSessionLdap, pResultat );
while (pEntree != NULL)
{
// Récupération du DN, et affichage de celui-ci
pDN = ldap_get_dn( pSessionLdap, pEntree );
if ( pDN != NULL )
{
printf( "dn: %s\n", pDN );
// Libération de la mémoire allouée par l'API LDAP
ldap_memfree( pDN );
}
// Pour chaque attribut, on va lire le couple attribut, valeur
pAttribut = ldap_first_attribute( pSessionLdap, pEntree, &pBer );
while ( pAttribut != NULL)
{
// Récupération des valeurs associées à un attribut
pValeurs = ldap_get_values( pSessionLdap, pEntree, pAttribut);
if (pValeurs != NULL )
{
for ( i = 0; pValeurs[i] != NULL; i++ )
printf( "%s: %s\n", pAttribut, pValeurs[i]);
// Libération des valeurs lues
ldap_value_free( pValeurs );
}
// Libération de la mémoire utilisée par l'attribut
ldap_memfree( pAttribut );
// Lecture de l'attribut suivant
pAttribut = ldap_next_attribute( pSessionLdap, pEntree, pBer );
}
// Passage à la ligne dans l'affichage
printf( "\n\n" );
// Récupération de l'entrée suivante de l'annuaire
pEntree = ldap_next_entry( pSessionLdap, pEntree );
}
// Libération du message de résultat
ldap_msgfree( pResultat );
/* Fin de la session LDAP */
ldap_unbind( pSessionLdap );
}
/*
*
* Fonction permettant d'afficher les erreurs des opérations LDAP
*
*
*/
void AfficheErreurLdap(char *fonction, ULONG rc)
{
fprintf(stderr,"Erreur LDAP dans la fonction '%s', Code : %ld (0x%xld)\n", fonction, rc,rc);
}
///////////////IDirectorySearch///////////////////////////////////////////////////////////
CComPtr<IDirectorySearch> pDSSearch;
hr = ADsGetObject( L"LDAP://DC=forest,DC=internal",
IID_IDirectorySearch,
(void**) &pDSSearch );
if ( !SUCCEEDED(hr) )
{
return 0;
}
LPWSTR pszAttr[] = { L"description", L"Name", L"distinguishedname" };
ADS_SEARCH_HANDLE hSearch;
DWORD dwCount = 0;
ADS_SEARCH_COLUMN col;
DWORD dwAttrNameSize = sizeof(pszAttr)/sizeof(LPWSTR);
// Search for all objects with the 'cn' property TESTCOMP.
hr = pDSSearch->ExecuteSearch(L"(&(objectClass=computer)(cn=TESTCOMP))",pszAttr ,dwAttrNameSize,&hSearch );
LPWSTR pszColumn;
while( pDSSearch->GetNextRow( hSearch) != S_ADS_NOMORE_ROWS )
{
// Get the property.
hr = pDSSearch->GetColumn( hSearch, L"distinguishedname", &col );
// If this object supports this attribute, display it.
if ( SUCCEEDED(hr) )
{
if (col.dwADsType == ADSTYPE_CASE_IGNORE_STRING)
wprintf(L"The description property:%s\r\n", col.pADsValues->CaseIgnoreString);
pDSSearch->FreeColumn( &col );
}
else
puts("description property NOT available");
puts("------------------------------------------------");
dwCount++;
}
pDSSearch->CloseSearchHandle(hSearch);
///////////////IDirectorySearch///////////////////////////////////////////////////////////
In this search you'll get
(*((col).pADsValues)).DNString
"CN=TESTCOMP,OU=OUnit3,OU=OUnit,DC=forest,DC=internal"
So this is path to your TESTCOMP and I believe OUnit3 is what you want.