Producer Consumer in C
When calling the function malloc():


The returned type is void*, so it can be assigned to any pointer, making the 'cast' totally unneeded. It just clutters the code, making it more difficult to understand, debug, maintain.
The expression sizeof(char) is defined in the standard at 1. Multiplying anything by 1 has no effect, so the expression just clutters the code.
When calling any of the memory allocation functions (malloc, calloc, realloc), always check (!=NULL) the returned value to assure the operation was successful.


When invoking the main() function and the code does not use the parameters, use the signature int main(void).

When compiling, always enable all the warnings, then fix those warnings. (For gcc, at a minimum use: -Wall -Wextra -pedantic I also use: -Wconversion -std=gnu99.) 

For ease of understanding and readability by the reader of the code:


Separate code blocks (for, if, else, while, do...while, switch, case, default) via a blank line.
Use meaningful variable names. A variable name should indicate usage or content (or better, both).


The code is using 'named' semaphores. 'named' semaphores are persistent, so calling sem_open() with the O_CREAT parameter will fail if the file has ever been run before.  I suggest first calling sem_unlink().

The calls to error() are not correct. The passed parameter is errno, a negative number, not a char and will not tell the user anything useful, especially if what is displayed is the contents of memory those address corresponds to the errno value. I suggest calling syserror() to get the error message that the OS thinks caused the error.

The call to pthread_create() returns 0 on success and -1 on failure. Passing that -1 to the function error() is meaningless.

I suggest passing a char* similar to error("pthread_create for producer failed") then modifying the error() function to expect a pointer to a char array.

The call to sem_open() returns a value SEM_FAILED which might be equal to -1 but that is an implementation detail, so do not use -1, use SEM_FAILED.

The second call to sem_open() returns busy, so the error check following that call should be checking busy, not free.

There are several other problems with the code, but the above comments should get you moving in the right direction.