So how does nginx changes process title? - c

This function implements the API to change process title:
http://lxr.evanmiller.org/http/source/os/unix/ngx_setproctitle.c
59 for (i = 0; environ[i]; i++) {
60 if (ngx_os_argv_last == environ[i]) {
61
62 size = ngx_strlen(environ[i]) + 1;
63 ngx_os_argv_last = environ[i] + size;
64
65 ngx_cpystrn(p, (u_char *) environ[i], size);
66 environ[i] = (char *) p;
67 p += size;
68 }
69 }
70
71 ngx_os_argv_last--;
72
73 return NGX_OK;
74 }
What I don't understand is ,after copy the environment variables to block allocated by ngx_alloc(size, log);,how is that block connected with argv[] block?
I don't see such logic there.
And there's one line I don't understand:
ngx_os_argv_last--;
What's it for, is this line that connects the allocated block with argv[]?

The comment at the beginning of the module seems to explain a lot, have you read it?
http://lxr.evanmiller.org/http/source/os/unix/ngx_setproctitle.c#L14
It appears the ngx_init_setproctitle() function simply sets up the memory for setting the process title and does no real changes to the title. The comment at the beginning of the module states that it needs to setup the memory for setting the process title because argv[0] may not have the space for the new title (which is what needs to be set in order to change the title).
The ngx_os_argv_last variable simply points to the end of the contiguous chunk for argv[] and environ[]. It's used later in the copy process in ngx_setproctitle(). The last ngx_os_argv_last-- is probably to account for the '\0' at the end of the string.
The ngx_init_setproctitle() create the space with ngx_alloc() then copies environ[] into the new space. The ngx_setproctitle() function simply copies over ngx_os_argv[0] with the new value title.

Related

How to convert a linking list to an dynamic array

I created an function in c as a linked list but i can't understand how convert it to a linked list.
My Question is how to convert an linked list to an dynamic array. This function adds elements to an linked list i want to be able to add elements to an dynamic array. i don't know if the struct blockhead_node is right like i said i'm still learning c. I do not understand dynamic arrays so i'm trying to create an program that uses them so i may understand them better. i want to create an add function that adds elements to the front or end of the list. This is what i have:
//this struct i'm trying to use for dynamic array
struct blockhead_node
{
float x, y;
float dx, dy;
long color;
int size; // slots used so far
int capacity; // total available slots
int *data; // array of integers we're storing
};
//this struct is for the linked list
struct blockhead_node
{
float x,y;
float dx, dy;
long color;
int size;
struct blockhead_node * next;
};
void add(struct blockhead_node ** blockhead_list) // double pointer because we can't modify the list it self
{
while((*blockhead_list)!=NULL)
{
blockhead_list=&(*blockhead_list)->next;
}
(*blockhead_list) = (struct blockhead_node*) malloc(sizeof(struct blockhead_node));
(*blockhead_list)->x = rand()%screen_width + (*blockhead_list)->size;
//(*blockhead_list)->x = 400;
//
//look up how to create an random floating point number
//
(*blockhead_list)->dx = ((float)rand()/(float)(10000));
(*blockhead_list)->y = rand()%screen_height + (*blockhead_list)->size;
(*blockhead_list)->dy = ((float)rand()/(float)(10000));
(*blockhead_list)->size = rand()%100;
(*blockhead_list)->next = NULL;
if((*blockhead_list)->x + (*blockhead_list)->size > screen_width)
{
(*blockhead_list)->x = screen_width - (*blockhead_list)->size;
}
if((*blockhead_list)->y + (*blockhead_list)->size > screen_height)
{
(*blockhead_list)->y = screen_height - (*blockhead_list)->size;
}
}
Using a dynamic array is not much different than using a linked-list. The primary difference is you are responsible for keeping track of size and realloc your data array when size == capacity (or when capacity == 0 for a new stuct).
Other than that you are either allocating per-node with a linked-list, whereas with a dynamic array you can allocate in a more efficient manner by allocating by some multiple of the current capacity when size == capacity. For arrays of completely unknown size you can either start with capacity = 2 or 8 and then either increase by some multiple (e.g. 3/2 or 2, etc..) or some fixed amount (8, 16, etc..) each time a reallocation is needed. I generally just double the current capacity, e.g. starting a 2, reallocating storage in data for 4, 8, 16, 32, ... integers as more numbers are added to data. You can do it any way you like -- as long as you keep track of your size and capacity.
A short example may help. Let's start with just a simple struct where data is the only dynamic member we are concerned about. For example:
#define CAP 2 /* initial capacity for new struct */
typedef struct {
size_t size,
capacity;
int *data;
} blkhd_node;
Where size is your "slots used so far" and capacity is your "total available slots" and data your "array of integers we're storing".
The add function is fairly trivial. All you need to do is check whether you need to realloc (e.g. this is a struct not used yet where capacity == 0 or all the slots are used and size == capacity). Since realloc can be used for both new and resizing the allocation, it is all you need. The scheme is simple, if this is a new struct, we will allocate for CAP number of int, otherwise if size == capacity we will allocated 2 * capacity number of int.
Whenever we realloc we do so with a temporary pointer! Why? When realloc fails it returns NULL. If you realloc with the original pointer (e.g. data = realloc (data, newsize); and NULL is returned, you overwrite your original pointer address for data with NULL and your ability to reach (or free) the original block of memory is lost -- creating a memory leak. By using a temporary pointer, we can validate whether realloc succeeds before we assign the new address to data. Importantly, if realloc does fail -- then our existing integers pointed to by data are still fine, so we are free to use our original allocation in the event of realloc failure. Important to remember.
We also need a way to indicate success/failure of or add function. Here, you are not adding a new node, so returning a pointer to a new node isn't an option. In this case a simple int return of 0 for failure of 1 for success is just as good as anything else.
With that, an add function could be as simple as:
int add (blkhd_node *b, int v)
{
/* realloc if (1) new struct or (2) size == capacity */
if (!b->capacity || b->size == b->capacity) {
size_t newsize;
if (!b->capacity) /* new stuct, set size = CAP */
newsize = CAP;
else if (b->size == b->capacity) /* otherwise double size */
newsize = b->capacity * 2;
/* alway realloc with a temporary pointer */
void *tmp = realloc (b->data, newsize * sizeof *b->data);
if (!tmp) { /* validate reallocation */
perror ("realloc_b->data");
return 0; /* return failure */
}
b->data = tmp; /* assign new block of mem to data */
b->capacity = newsize; /* set capacity to newsize */
}
b->data[b->size++] = v; /* set data value to v */
return 1; /* return success */
}
Note: since you are initializing your struct and both size and capacity will be 0, you can dispense with separate checks for capacity == 0 and size == capacity and use a ternary to set newsize. This is arguably the less-readable way to go and a good compiler will optimize both identically, but for sake of completeness, you could replace the code setting newsize with:
/* realloc if (1) new struct or (2) size == capacity */
if (b->size == b->capacity) {
/* set newsize */
size_t newsize = b->capacity ? b->capacity * 2 : CAP;
Given the option, your choice should always be for the more readable and maintainable code. You do your job, and let the compiler worry about the rest.
(you can do a dynamic array of struct blockhead_node in exactly the same way -- just account for the number of structs you have in the array in addition to the size, capacity for data in each -- that is left to you)
So, let's see if our scheme of originally allocating for 2-int will allow us to add 100-int to our data array with a short example putting it altogether:
#include <stdio.h>
#include <stdlib.h>
#define CAP 2 /* initial capacity for new struct */
typedef struct {
size_t size,
capacity;
int *data;
} blkhd_node;
int add (blkhd_node *b, int v)
{
/* realloc if (1) new struct or (2) size == capacity */
if (!b->capacity || b->size == b->capacity) {
size_t newsize;
if (!b->capacity) /* new stuct, set size = CAP */
newsize = CAP;
else if (b->size == b->capacity) /* otherwise double size */
newsize = b->capacity * 2;
/* alway realloc with a temporary pointer */
void *tmp = realloc (b->data, newsize * sizeof *b->data);
if (!tmp) { /* validate reallocation */
perror ("realloc_b->data");
return 0; /* return failure */
}
b->data = tmp; /* assign new block of mem to data */
b->capacity = newsize; /* set capacity to newsize */
}
b->data[b->size++] = v; /* set data value to v */
return 1; /* return success */
}
void prndata (blkhd_node *b)
{
for (size_t i = 0; i < b->size; i++) {
if (i && i % 10 == 0)
putchar ('\n');
printf (" %3d", b->data[i]);
}
putchar ('\n');
}
int main (void) {
blkhd_node b = { .size = 0 }; /* declare/initialize struct */
for (int i = 0; i < 100; i++) /* add 100 data values */
if (!add (&b, i + 1))
break; /* don't exit, all prior data still good */
/* output results */
printf ("\nsize : %zu\ncapacity : %zu\n\n", b.size, b.capacity);
prndata (&b);
free (b.data); /* don't forget to free what you allocate */
return 0;
}
Example Use/Output
$ ./bin/dynarrayint
size : 100
capacity : 128
1 2 3 4 5 6 7 8 9 10
11 12 13 14 15 16 17 18 19 20
21 22 23 24 25 26 27 28 29 30
31 32 33 34 35 36 37 38 39 40
41 42 43 44 45 46 47 48 49 50
51 52 53 54 55 56 57 58 59 60
61 62 63 64 65 66 67 68 69 70
71 72 73 74 75 76 77 78 79 80
81 82 83 84 85 86 87 88 89 90
91 92 93 94 95 96 97 98 99 100
Memory Use/Error Check
In any code you write that dynamically allocates memory, you have 2 responsibilities regarding any block of memory allocated: (1) always preserve a pointer to the starting address for the block of memory so, (2) it can be freed when it is no longer needed.
It is imperative that you use a memory error checking program to insure you do not attempt to access memory or write beyond/outside the bounds of your allocated block, attempt to read or base a conditional jump on an uninitialized value, and finally, to confirm that you free all the memory you have allocated.
For Linux valgrind is the normal choice. There are similar memory checkers for every platform. They are all simple to use, just run your program through it.
$ valgrind ./bin/dynarrayint
==12589== Memcheck, a memory error detector
==12589== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==12589== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info
==12589== Command: ./bin/dynarrayint
==12589==
size : 100
capacity : 128
1 2 3 4 5 6 7 8 9 10
11 12 13 14 15 16 17 18 19 20
21 22 23 24 25 26 27 28 29 30
31 32 33 34 35 36 37 38 39 40
41 42 43 44 45 46 47 48 49 50
51 52 53 54 55 56 57 58 59 60
61 62 63 64 65 66 67 68 69 70
71 72 73 74 75 76 77 78 79 80
81 82 83 84 85 86 87 88 89 90
91 92 93 94 95 96 97 98 99 100
==12589==
==12589== HEAP SUMMARY:
==12589== in use at exit: 0 bytes in 0 blocks
==12589== total heap usage: 7 allocs, 7 frees, 1,016 bytes allocated
==12589==
==12589== All heap blocks were freed -- no leaks are possible
==12589==
==12589== For counts of detected and suppressed errors, rerun with: -v
==12589== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
Always confirm that you have freed all memory you have allocated and that there are no memory errors.
Look things over and let me know if you have further questions.

extract coap query

I need your help in extracting the query value in a coap message.The coap message looks like
coap://[ff08:90:5001:0:0:0:0:1]:12345/c?a=4
decoded packet is 52 02 00 00 91 63 63 61 3d 34 . Here 63 61 3d 34 is the query part ?a=4 . There is a data after query. I have pointed my buffer pointer to 63(?), now I'm struck in getting the value 34(4). How do I go to the value and extract it?
coap_h *hdr = (coap_h *)(buf);
buf = (uint8_t *)(hdr + 1);
len = buf[0] & 0xf;
buf += len + 1;
buf points to 52 initially and then I move the buf to the options field 91 and check for length then increment the buf which points to 63 (?). hope i'm clear this time.
I don't have the time at the moment to parse your packet by hand, but you should know that the way options work has changed dramatically in CoAP-12. I have implemented some functions to encode and parse options, which you might find useful:
https://github.com/darconeous/smcp/blob/master/src/smcp/coap.c
https://github.com/darconeous/smcp/blob/master/src/smcp/coap.h

How fast is mprotect

My question is how fast is mprotect. What will be the difference between mprotecting say 1 MB of contiguous memory as compared to 1 GB of contiguous memory? Of course I can measure the time, but I want to know what goes under the hood.
A quick check on the source seems to indicate that it iterates over the process mappings in the selected region and change their flags. If you protect less than a whole mapping it'll split it into two or three.
So in short it's O(n) where n is the number of times you've called mmap.
You can see all the current maps in /proc/pid/maps
It is O(n) on page count in the region too, because it should change a access bits on all PTEs (Page translation Entries, which describes virtual->physical page mappings in PageTable). Calltree:
mprotect
->
mprotect_fixup
->
change_pte_range
http://lxr.free-electrons.com/source/mm/mprotect.c#L32
47 do {
48 oldpte = *pte;
49 if (pte_present(oldpte)) {
50 pte_t ptent;
51
52 ptent = ptep_modify_prot_start(mm, addr, pte);
53 ptent = pte_modify(ptent, newprot);
54
55 /*
56 * Avoid taking write faults for pages we know to be
57 * dirty.
58 */
59 if (dirty_accountable && pte_dirty(ptent))
60 ptent = pte_mkwrite(ptent);
61
62 ptep_modify_prot_commit(mm, addr, pte, ptent);
63 } else if (PAGE_MIGRATION && !pte_file(oldpte)) {
64 swp_entry_t entry = pte_to_swp_entry(oldpte);
65
66 if (is_write_migration_entry(entry)) {
67 /*
68 * A protection check is difficult so
69 * just be safe and disable write
70 */
71 make_migration_entry_read(&entry);
72 set_pte_at(mm, addr, pte,
73 swp_entry_to_pte(entry));
74 }
75 }
76 } while (pte++, addr += PAGE_SIZE, addr != end);
Note the increment: addr += PAGE_SIZE, addr != end);

Passing char * into fopen with C

I'm writing a program that passes data from a file into an array, but I'm having trouble with fopen (). It seems to work fine when I hardcode the file path into the parameters (eg fopen ("data/1.dat", "r");) but when I pass it as a pointer, it returns NULL.
Note that line 142 will print "data/1.dat" if entered from command line so parse_args () appears to be working.
132 int
133 main(int argc, char **argv)
134 {
135 FILE *in_file;
136 int *nextItem = (int *) malloc (sizeof (int));
137 set_t *dictionary;
138
139 /* Parse Arguments */
140 clo_t *iopts = parse_args(argc, argv);
141
142 printf ("INPUT FILE: %s.\n", iopts->input_file); /* This prints correct path */
143 /* Initialise dictionary */
144 dictionary = set_create (SET_INITAL_SIZE);
145
146 /* Use fscanf to read all data values into new set_t */
147 if ((in_file = fopen (iopts->input_file, "r")) == NULL)
148 {
149 printf ("File not found...\n");
150 return 0;
151 }
Thanks!
Rhys
MORE: If I try to print the string after I run set_create() (ln 144), the string doesn't print. (But there isn't any reference to the string in the function at all...)
47 set_t *
48 set_create(int size)
49 {
50 set_t *set;
51
52 /* set set_t members */
53 set->items = 0;
54 set->n_max = size;
55 set->lock = FALSE;
56
57 /* allocate memory for dictionary input */
58 set->data = (int *) malloc (size * sizeof (int));
59
60 return set;
61 }
It does work if I call this function after fopen ().
I can't see how this is affecting the filename though...
Thanks again.
Your new code shows that you are writing to invalid memory. set is a pointer but you never initialize it. You're overwriting some random memory and thereby destroying the pointer to the string that you're passing to fopen().
Are you sure parse_args works correctly? If it, for example, returns a pointer to a local variable (or a struct that contains such pointers), the values like iopts->input_file would easily be destroyed by subsequent function calls.
That second part is your problem. set is not initialized.
To clarify: you're modifying stuff that you don't mean to, causing the fopen() to fail.

Fread binary file dynamic size string

I've been working on this assignment, where I need to read in "records" and write them to a file, and then have the ability to read/find them later. On each run of the program, the user can decide to write a new record, or read an old record (either by Name or #)
The file is binary, here is its definition:
typedef struct{
char * name;
char * address;
short addressLength, nameLength;
int phoneNumber;
}employeeRecord;
employeeRecord record;
The way the program works, it will store the structure, then the name, then the address. Name and address are dynamically allocated, which is why it is necessary to read the structure first to find the size of the name and address, allocate memory for them, then read them into that memory.
For debugging purposes I have two programs at the moment. I have my file writing program, and file reading.
My actual problem is this, when I read a file I have written, i read in the structure, print out the phone # to make sure it works (which works fine), and then fread the name (now being able to use record.nameLength which reports the proper value too).
Fread however, does not return a usable name, it returns blank.
I see two problems, either I haven't written the name to the file correctly, or I haven't read it in correctly.
Here is how i write to the file: where fp is the file pointer. record.name is a proper value, so is record.nameLength. Also i am writing the name including the null terminator. (e.g. 'Jack\0')
fwrite(&record,sizeof record,1,fp);
fwrite(record.name,sizeof(char),record.nameLength,fp);
fwrite(record.address,sizeof(char),record.addressLength,fp);
And i then close the file.
here is how i read the file:
fp = fopen("employeeRecord","r");
fread(&record,sizeof record,1,fp);
printf("Number: %d\n",record.phoneNumber);
char *nameString = malloc(sizeof(char)*record.nameLength);
printf("\nName Length: %d",record.nameLength);
fread(nameString,sizeof(char),record.nameLength,fp);
printf("\nName: %s",nameString);
Notice there is some debug stuff in there (name length and number, both of which are correct). So i know the file opened properly, and I can use the name length fine. Why then is my output blank, or a newline, or something like that? (The output is just Name: with nothing after it, and program finishes just fine)
Thanks for the help.
I tried your code and it worked fine. In order, here is the output, a hexdump of the file, and your source made to compile.
Update: Updated code to read name and address from stdin or command-line arguments.
prompt$ g++ -g -Wall -o test_records test_records.cpp
prompt$ echo -e "Test User\nSomeplace, Somewhere" | ./test_records
sizeof(employeeRecord) = 24
Number: 5551212
Name Length: 9
Name: Test User
prompt$ hexdump -C employeeRecord
00000000 90 f7 bf 5f ff 7f 00 00 70 f7 bf 5f ff 7f 00 00 |..._....p.._....|
00000010 14 00 09 00 6c b4 54 00 54 65 73 74 20 55 73 65 |....l.T.Test Use|
00000020 72 53 6f 6d 65 70 6c 61 63 65 2c 20 53 6f 6d 65 |rSomeplace, Some|
00000030 77 68 65 72 65 |where|
00000035
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct{
char * name;
char * address;
short addressLength, nameLength;
int phoneNumber;
}employeeRecord;
int main(int argc, char *argv[])
{
employeeRecord record;
#if 0
// Commmand line arguments
if (argc < 3)
return 1;
record.nameLength = strlen(argv[1]);
record.name = (char *)malloc(sizeof(char)*(record.nameLength + 1));
strncpy(record.name, argv[1], record.nameLength + 1);
record.addressLength = strlen(argv[2]);
record.address = (char *)malloc(sizeof(char)*(record.addressLength + 1));
strncpy(record.address, argv[2], record.addressLength + 1);
#else
// stdin
char input[1024];
fgets(input, sizeof(input), stdin);
record.nameLength = strlen(input);
record.name = (char *)malloc(sizeof(char)*(record.nameLength + 1));
strncpy(record.name, input, record.nameLength + 1);
fgets(input, sizeof(input), stdin);
record.addressLength = strlen(input);
record.address = (char *)malloc(sizeof(char)*(record.addressLength + 1));
strncpy(record.address, input, record.addressLength + 1);
#endif
record.phoneNumber = 5551212;
FILE *fp = NULL;
printf("sizeof(employeeRecord) = %lu\n", sizeof(employeeRecord));
// Write
fp = fopen("employeeRecord","w");
fwrite(&record,sizeof(employeeRecord),1,fp);
// Note: we're not including terminating NULLs.
fwrite(record.name,sizeof(char),record.nameLength,fp);
fwrite(record.address,sizeof(char),record.addressLength,fp);
fclose(fp);
// Read
fp = fopen("employeeRecord","r");
fread(&record,sizeof(employeeRecord),1,fp);
printf("Number: %d\n",record.phoneNumber);
char *nameString = (char *)malloc(sizeof(char)*(record.nameLength + 1));
printf("\nName Length: %d",record.nameLength);
fread(nameString,sizeof(char),record.nameLength,fp);
nameString[record.nameLength] = '\0';
printf("\nName: %s",nameString);
printf("\n");
fclose(fp);
return 0;
}
I would like to add my input....since you are dumping the memory structure to disk, the pointer addresses used to hold the data would most certainly be valid prior to dumping, but when reading from them, the pointer addresses could be invalid....which would explain why the character pointer is not showing the name...
Firstly, a nitpick: you never need sizeof (char) - it's 1, always, by definition.
As for the blank name output: do you perhaps need a newline after the %s to flush the output? I've seen weird behaviour when you leave this out, and you don't state which platform you are using. If the platform's printf() is implemented bizarrely enough, you could have the format string printed and flushed, but the name itself stuck in the C library's buffers when your program exits.
And I'm never happy about reading or writing blobs of binary data like a struct to and from files. Realise that by doing so you're promising your program that it will only ever read what it wrote on the same platform. You couldn't write a file on, say, a 64-bit host and read the file back in on a 16-bit microwave oven controller.

Resources