'undefined reference to' [OpenBSD 3.5 system defined method] - c

I have been learning how to use Unix functions to program in C so that I can program Semaphore functionality by scratch (without pthreads), but I am currently stuck. The man pages told me to include particular header files to use functions of interest (such as malloc, tsleep, wakeup, etc.), but when I try to run my program with the headers and method calls, I receive the following errors:
/tmp//ccg29960.o: In function `allocate_semaphore':
/tmp//ccg29960.o(.text+0x28d): undefined reference to `simple_lock_init'
/tmp//ccg29960.o: In function `down_semaphore':
/tmp//ccg29960.o(.text+0x2fb): undefined reference to `tsleep'
/tmp//ccg29960.o: In function `up_semaphore':
/tmp//ccg29960.o(.text+0x3b5): undefined reference to `wakeup'
/tmp//ccg29960.o: In function `free_semaphore':
/tmp//ccg29960.o(.text+0x43b): undefined reference to `simple_lock'
/tmp//ccg29960.o(.text+0x4af): undefined reference to `simple_unlock'
collect2: ld returned 1 exit status
The relevant code is below:
//#include <stdio.h>
//#include <stdlib.h>
#include <sys/errno.h>
#include <sys/queue.h>
//#include <sys/time.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/proc.h>
#include <sys/malloc.h>
#include <sys/lock.h>
struct entry
{
pid_t id;
SIMPLEQ_ENTRY(entry) next;
} *np;
typedef struct
{
const char* name;
pid_t process;
pid_t p_process; //parent process
int count;
SIMPLEQ_HEAD(queuehead,entry) head;
struct simplelock *slock;
} named_semaphore;
named_semaphore* s_list[64];
int num_semaphores = 0;
int main()
{
//lockinit(0, 0, 0,0, 0);
printf("Hello world\n");
return 0;
}
//... irrelevant code elided
int allocate_semaphore( const char* name, int initial_count )
{
int num_elements, i;
named_semaphore *new_s;
//perform initial checks before creating a new semaphore
//make sure the given name is an acceptable length
num_elements = sizeof(name) / sizeof(*name);
if ( num_elements > 32 )
{
return ENAMETOOLONG;
}
//make sure the given name is unique to this process
for (i = 0; i < num_semaphores; i++)
{
if (s_list[i]->process == getpid() && strcmp(s_list[i]->name, name))
{
return EEXIST;
}
}
//make sure there are no more than 64 semaphores active
if (num_semaphores >= 64)
{
return ENOMEM;
}
//create a new semaphore and add it to the collection
new_s = (named_semaphore*) malloc(sizeof(named_semaphore), 0, 0);
new_s->name = name;
new_s->process = getpid();
new_s->p_process = getppid();
new_s->count = initial_count;
s_list[num_semaphores] = new_s;
++num_semaphores;
//initialize the waiting queue
SIMPLEQ_INIT( &(new_s->head) );
//initialize its lock
simple_lock_init( new_s->slock );
//need to handle negative initial_count somehow
return (0);
}
int down_semaphore( const char* name )
{
named_semaphore* s;
s = getSemaphore( name );
if (s == NULL)
{
return (ENOENT);
}
s->count = (s->count) - 1;
if (s->count < 0)
{
//put process to sleep
tsleep(getpid(), getpriority(), 0, 0);
//add process to waiting queue
np = (struct entry *) malloc(sizeof(struct entry ));
np->id = getpid();
SIMPLEQ_INSERT_TAIL( &(s->head), np, next );
}
return 0;
}
int up_semaphore ( const char* name )
{
named_semaphore* s;
s = getSemaphore( name );
if ( s == NULL )
{
return (ENOENT);
}
s->count = (s->count) + 1;
if (s->count <= 0)
{
//wakeup longest waiting process
wakeup( (SIMPLEQ_FIRST( &(s->head) ))->id );
//remove process from waiting queue
SIMPLEQ_REMOVE_HEAD( &(s->head), np, next );
free( np );
}
return 0;
}
int free_semaphore( const char* name )
{
named_semaphore* s;
s = getSemaphore( name );
if ( s == NULL )
{
return (ENOENT);
}
simple_lock( s->slock );
while ( (np = SIMPLEQ_FIRST( &(s->head) ) ) != NULL )
{
//wakeup the process and return ECONNABORTED
//wakeup( getSemaphore( np->id ) );
SIMPLEQ_REMOVE_HEAD( &(s->head), np, next );
free( np );
}
free( s );
simple_unlock( s->slock );
}
I am not done modifying/fixing the logic of my overall program (for example, the lock()ing only happens in 1/3 of the intended methods), but it would be wonderful to understand why I am getting my current error so that I know how to fix similar ones in the future.
To me it seems like the methods do not recognize their header files or that I am missing a required piece of information so that the two can communicate.
To fix the errors, I've tried rearranging and commenting out the listed header files and also renaming the method calls in uppercase letters like they were presented in the header file documentation.
Any help or insight is appreciated, and thank you in advance!

The man pages you read... those were section 9, weren't they? Section 9 is for kernel programming. You can't call those functions unless your code is in the kernel.

Related

Only one of multiple threads is writing

I have a task to make a StarCraft like program with multiple pthreads as workers.
So , I have multiple pthreads that run the following function:
void* scv(int num){
int minerals_carried = 0;
while(map_minerals_remaining>0){
minerals_carried = 0;
for(int i = 0; i<number_of_fields; i++){
if(fields[i].minerals != 0 && minerals_carried == 0){
if(pthread_mutex_trylock(&fields[i].mutex)==0){
sleep(1);
// mine returns int
minerals_carried = mine(&fields[i]);
printf("SCV%d is carrying %d minerals from field %d\n",num,minerals_carried,i);
if(pthread_mutex_unlock(&fields[i].mutex)!=0){
perror("pthread_mutex_unlock");
return NULL;
}
}else{
perror("pthread_mutex_trylock");
return NULL;
}
}
}
}
return NULL;
}
I create 5 pthreads and they all get created properly , but only the first one prints out like its supposed to do, and all the other ones dont seem to do anything. Any idea why that might be ?
EDIT :
I was asked to show how I initialized number_of_fields and fields and this is it:
I first declare them as global
typedef struct Mineral_Field_t{
pthread_mutex_t mutex;
int minerals;
}Mineral_Field;
Mineral_Field* fields;
int number_of_fields = 2;
And then I have the following piece of code at the start of the main function:
if(argv[1] != NULL){
number_of_fields = atoi(argv[1]);
}
fields = malloc(number_of_fields*sizeof(Mineral_Field));

Infinite Loop and time

I'm trying to compare when does a given date corresponds to current time, when that happens it's supposed to execute a program. I have used an infinite loop so that it waits for the given time to correspond to the current time, the problem is that when that happens it executes the program more than one time and I don't know how to solve this...
#include <unistd.h>
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int taskexecution()
{
char * path;
path = "/home/soraia/mieti/Proj/makefile";
pid_t fk = fork();
if (!fk) { /* in child */
chdir("/home/soraia/mieti/Proj");
execlp ("make", "make", "-f", path , NULL);
_exit(127);
}
else if (fk == -1)
{
perror("fork"); /* print an error message */
}
return 0;
}
void time()
{
struct tm data;
data.tm_year=2015-1900;
data.tm_mon=1-1;
data.tm_mday=03;
data.tm_hour=10;
data.tm_min=49;
data.tm_sec=10;
data.tm_isdst = -1;
if(mktime(&data) == time(NULL))
{
taskexecution();
}
}
int main ()
{
while(1)
{
time();
}
return 0;
}
Your problem is that the computer runs so fast that your time() function can be called several times in the same second. What you need is to ensure that either your function stops the while loop after having run the task, or forbids the execution of the task:
First:
int time()
{
struct tm data;
data.tm_year=2015-1900;
data.tm_mon=1-1;
data.tm_mday=03;
data.tm_hour=10;
data.tm_min=49;
data.tm_sec=10;
data.tm_isdst = -1;
if (mktime(&data) == time(NULL))
{
taskexecution();
return 0; // returns 0 to stop while
}
return 1; // returns 1 to let the while continue
}
int main ()
{
while(time());
return 0;
}
second:
void time()
{
static int ran = 0; // static variable: 0 is task not already executed, 1 else
struct tm data;
data.tm_year=2015-1900;
data.tm_mon=1-1;
data.tm_mday=03;
data.tm_hour=10;
data.tm_min=49;
data.tm_sec=10;
data.tm_isdst = -1;
if(ran==0 && mktime(&data) == time(NULL))
{
taskexecution();
ran = 1; // Ok execution took place
}
}

How to use fgetpwent()?

I am trying to get a list of all the users in the system (linux, fedora).
and i've heard that the function:fgetpwent is the one that i need to that mission.
the sad part is that i didnt find any documentation or example of how to use this function.
if someone would give me an example, that would be great, thanks in advance.
No idea why I ever could have used it:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <crypt.h>
#include <pwd.h>
#include <sys/types.h>
char *testentry = "testread";
static void read_etc_passwd (void) {
struct passwd *pwd_entry = NULL;
int found = 0;
setpwent(); // go to the top of /etc/passwd
while (!found && (pwd_entry = getpwent())){
if (0 == strcmp (testentry, pwd_entry->pw_name)){
found = 1;
}
}
if (found) {
printf ("name = %s\nhome = %s\n", pwd_entry->pw_name,
pwd_entry->pw_dir);
} else {
puts("could not find the entry you were looking for, or"
"some error occurred");
}
}
void change_etc_passwd (void){
struct passwd *pwd = NULL;
FILE *pwd_fd = NULL;
FILE *pwd_new = NULL;
int result = 0;
pwd_fd = fopen ("/etc/passwd", "r");
pwd_new = fopen ("/tmp/passwd.neu", "a");
// assuming everthing went fine (bad idea)
while (pwd = fgetpwent (pwd_fd)){
if (0 == strcmp (pwd->pw_name, testentry)){
pwd->pw_passwd = crypt ("new_pwd", "aa");
}
result = putpwent(pwd, pwd_new);
if (result < 0){
fprintf (stderr, "Failed to write entry, giving up\n");
exit (EXIT_FAILURE);
}
}
}
int main (void) {
/* handling of /etc/passwd */
read_etc_passwd ();
change_etc_passwd();
return 0;
}
Add error handling and it may even work without breaking ;-)

OSX FSEventStreamEventFlags not working correctly

I am watching a directory for file system events. Everything seems to work fine with one exception. When I create a file the first time, it spits out that it was created. Then I can remove it and it says it was removed. When I go to create the same file again, I get both a created and removed flag at the same time. I obviously am misunderstanding how the flags are being set when the callback is being called. What is happening here?
//
// main.c
// GoFSEvents
//
// Created by Kyle Cook on 8/22/13.
// Copyright (c) 2013 Kyle Cook. All rights reserved.
//
#include <CoreServices/CoreServices.h>
#include <stdio.h>
#include <string.h>
void eventCallback(FSEventStreamRef stream, void* callbackInfo, size_t numEvents, void* paths, const FSEventStreamEventFlags eventFlags[], const FSEventStreamEventId eventIds[]) {
char **pathsList = paths;
for(int i = 0; i<numEvents; i++) {
uint32 flag = eventFlags[i];
uint32 created = kFSEventStreamEventFlagItemCreated;
uint32 removed = kFSEventStreamEventFlagItemRemoved;
if(flag & removed) {
printf("Item Removed: %s\n", pathsList[i]);
}
else if(flag & created) {
printf("Item Created: %s\n", pathsList[i]);
}
}
}
int main(int argc, const char * argv[])
{
CFStringRef mypath = CFSTR("/path/to/dir");
CFArrayRef paths = CFArrayCreate(NULL, (const void **)&mypath, 1, NULL);
CFRunLoopRef loop = CFRunLoopGetMain();
FSEventStreamRef stream = FSEventStreamCreate(NULL, (FSEventStreamCallback)eventCallback, NULL, paths, kFSEventStreamEventIdSinceNow, 1.0, kFSEventStreamCreateFlagFileEvents | kFSEventStreamCreateFlagNoDefer);
FSEventStreamScheduleWithRunLoop(stream, loop, kCFRunLoopDefaultMode);
FSEventStreamStart(stream);
CFRunLoopRun();
FSEventStreamStop(stream);
FSEventStreamInvalidate(stream);
FSEventStreamRelease(stream);
return 0;
}
As far as I can tell, you will have to look for either kFSEventStreamEventFlagItemRemoved or kFSEventStreamEventFlagItemCreated, and then use stat() or similar to check if the file was in fact added or deleted. The FSEvents documentation seems to hint as such.
It looks like the API is or'ing the events bits together... so really it's an OR of all the changes made since the FSEventsListener is created. Since that seems to be the case, another option might be to create a new FSEventListener each time (and use the coalesce timer option).
I did some Googling, but didn't find other examples of this problem or even apple sample code, but I didn't spend too long on it.
I have previously used the kqueue API: https://gist.github.com/nielsbot/5155671 (This gist is an obj-c wrapper around kqueue)
I changed your sample code to show all flags set for each FSEvent:
#include <CoreServices/CoreServices.h>
#include <stdio.h>
#include <string.h>
static int __count = 0 ;
void eventCallback(FSEventStreamRef stream, void* callbackInfo, size_t numEvents, void* paths, const FSEventStreamEventFlags eventFlags[], const FSEventStreamEventId eventIds[]) {
char **pathsList = paths;
printf("callback #%u\n", ++__count ) ;
const char * flags[] = {
"MustScanSubDirs",
"UserDropped",
"KernelDropped",
"EventIdsWrapped",
"HistoryDone",
"RootChanged",
"Mount",
"Unmount",
"ItemCreated",
"ItemRemoved",
"ItemInodeMetaMod",
"ItemRenamed",
"ItemModified",
"ItemFinderInfoMod",
"ItemChangeOwner",
"ItemXattrMod",
"ItemIsFile",
"ItemIsDir",
"ItemIsSymlink",
"OwnEvent"
} ;
for(int i = 0; i<numEvents; i++)
{
printf("%u\n", i ) ;
printf("\tpath %s\n", pathsList[i]) ;
printf("\tflags: ") ;
long bit = 1 ;
for( int index=0, count = sizeof( flags ) / sizeof( flags[0]); index < count; ++index )
{
if ( ( eventFlags[i] & bit ) != 0 )
{
printf("%s ", flags[ index ] ) ;
}
bit <<= 1 ;
}
printf("\n") ;
}
FSEventStreamFlushSync( stream ) ;
}
int main(int argc, const char * argv[])
{
CFStringRef path = CFStringCreateWithCString( kCFAllocatorDefault, argv[1], kCFStringEncodingUTF8 ) ;
CFArrayRef paths = CFArrayCreate(NULL, (const void **)&path, 1, &kCFTypeArrayCallBacks );
if ( path ) { CFRelease( path ) ; }
CFRunLoopRef loop = CFRunLoopGetCurrent() ;
FSEventStreamRef stream = FSEventStreamCreate(NULL, (FSEventStreamCallback)eventCallback, NULL, paths, kFSEventStreamEventIdSinceNow, 0, kFSEventStreamCreateFlagFileEvents );
if ( paths ) { CFRelease( paths ) ; }
FSEventStreamScheduleWithRunLoop(stream, loop, kCFRunLoopDefaultMode);
FSEventStreamStart(stream);
CFRunLoopRun() ;
FSEventStreamStop(stream);
FSEventStreamInvalidate(stream);
FSEventStreamRelease(stream);
return 0;
}

multithreading function calls

i have an array of structures with fields of data and fields with pointers to functions.
what i'm doing now is cycling through array and calling each registered function.
what i need is for each of element in my structures array call registered function in a separate independent thread.
i can post an code example also if needed. sorry for my english :)
posting code:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <pthread.h>
#define NTHREAD 3
struct server_t {
char *name;
int (*triggered)(struct server_t *);
};
typedef struct server_t server_t;
int triggered1(struct server_t * server)
{
if (time(NULL) % 1 == 0) {
printf("%s\n", __FUNCTION__);
pthread_exit(0);
return 0;
} else {
return -1;
}
}
int triggered2(struct server_t * server)
{
if (time(NULL) % 2 == 0) {
printf("%s\n", __FUNCTION__);
pthread_exit(0);
return 0;
} else {
return -1;
}
}
int triggered3(struct server_t * server)
{
if (time(NULL) % 5 == 0) {
printf("%s\n", __FUNCTION__);
pthread_exit(0);
return 0;
} else {
return -1;
}
}
int main()
{
pthread_t threads[NTHREAD];
int iret[NTHREAD]; int i = 0;
server_t servers[] = {
{"server1", triggered1},
{"server2", triggered2},
{"server3", triggered3},
};
/*
So, i have an array of structures. AND i have a main loop.
i want to create thread for each element of array, pass
structure's "triggered" function as start routine for it.
AND i need this start routine to periodically check for something.
So below some kind of an em.. code, that supposed to be.
*/
<create_threads(&servers);> // this function must create thread for each element of array
//with structure's "triggered" function as a start routine
//argument
/* after what threads are running and checking what they needed in an infinite loop. */
// ?maybe some code here?
return 0;
}
Here is a very good, basic pthreads example, which should get you going:
https://computing.llnl.gov/tutorials/pthreads/#CreatingThreads
Basically all you need to do is loop through your function-pointer-array and execute the functions according to the said example.

Resources