Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
document last changes
[simgrid.git] / src / nws_portability / osutil.c
1 /* $Id$ */
2
3
4 #include "config_portability.h"
5
6 #include <ctype.h>      /* isspace() */
7 #include <errno.h>      /* errno values */
8 #include <pwd.h>        /* endpwent() getpwuid() */
9 #include <signal.h>     /* sig{add,empty}set() sigprocmask() */
10 #include <stdio.h>      /* file functions */
11 #include <stdlib.h>     /* getenv() */
12 #include <string.h>     /* memset() strchr() strlen() */
13 #include <unistd.h>     /* alarm() getuid() sysconf() (where available) */
14 #include <sys/stat.h>   /* stat() */
15 #include <sys/time.h>   /* gettimeofday() */
16 #include <sys/types.h>  /* size_t time_t */
17 #include <time.h>       /* time() */
18
19 #include "osutil.h"
20
21 #ifdef HAVE_PTHREAD_H
22 #include <pthread.h>
23
24 /* this is the lock for this module. Every other module will use a void *
25  * as a variable as mutex. */
26 pthread_mutex_t nwsLock = PTHREAD_MUTEX_INITIALIZER;
27 #endif
28
29
30 /* 
31  * These are defined here only becasue they are not found (sometimes) in
32  * the headers but only in libraries. To avoid annoying compilation warnings
33  */
34 #ifdef HAVE_SIGHOLD
35 int sighold(int sig);
36 #endif
37 #ifdef HAVE_SIGRELSE
38 int sigrelse(int sig);
39 #endif
40
41
42 int
43 CPUCount( ) {
44 #ifdef HAVE_SYSCONF
45 #       ifdef _SC_CRAY_NCPU
46 #               define SYSCONF_PROCESSOR_COUNT_PARAMETER _SC_CRAY_NCPU
47 #       elif defined(_SC_NPROC_CONF)
48 #               define SYSCONF_PROCESSOR_COUNT_PARAMETER _SC_NPROC_CONF
49 #       elif defined(_SC_NPROCESSORS_CONF)
50 #               define SYSCONF_PROCESSOR_COUNT_PARAMETER _SC_NPROCESSORS_CONF
51 #       endif
52 #       ifdef SYSCONF_PROCESSOR_COUNT_PARAMETER 
53   /* Try to gracefully handle mis-configuration. */
54   int sysconfCount = sysconf(SYSCONF_PROCESSOR_COUNT_PARAMETER);
55   return (sysconfCount == 0) ? 1 : sysconfCount;
56 #       else
57   return 1;
58 #       endif
59 #else
60   return 1;
61 #endif
62 }
63
64
65 /* It should be thread safe (time should be thread safe) */
66 double
67 CurrentTime(void) {
68         return((double)time(NULL));
69 }
70
71
72 const char *
73 GetEnvironmentValue(const char *name,
74                     const char *rcDirs,
75                     const char *rcName,
76                     const char *defaultValue) {
77
78         const char *dirEnd;
79         const char *dirStart;
80         char *from;
81         const char *homeDir;
82         size_t nameLen;
83         FILE *rcFile;
84         static char rcLine[255 + 1];
85         char rcPath[255 + 1];
86         const char *returnValue;
87         char *to;
88
89         returnValue = getenv(name);
90         if(returnValue != NULL) {
91                 /* easy way out: we got the environmental variable */
92                 return returnValue;
93         }
94
95         if(*rcName != '\0') {
96                 nameLen = strlen(name);
97
98                 for(dirStart = rcDirs, dirEnd = dirStart; dirEnd != NULL; dirStart = dirEnd + 1) {
99                         /* Construct a file path from the next dir in
100                          * rcDirs and rcName. */
101                         dirEnd = strchr(dirStart, ':');
102                         memset(rcPath, '\0', sizeof(rcPath));
103                         strncpy(rcPath, dirStart, (dirEnd == NULL) ? strlen(dirStart) : (dirEnd - dirStart));
104                         if((strcmp(rcPath, "~") == 0) || (strcmp(rcPath, "~/") == 0)) {
105                                 homeDir = getenv("HOME");
106                                 if(homeDir != NULL) {
107                                         strcpy(rcPath, homeDir);
108                                 }
109                         }
110                         strcat(rcPath, "/");
111                         strcat(rcPath, rcName);
112                         rcFile = fopen(rcPath, "r");
113
114                         if(rcFile == NULL) {
115                                 /* no luck, try the next one */
116                                 continue;
117                         }
118
119                         while(fgets(rcLine, sizeof(rcLine), rcFile) != NULL) {
120                                 /* Test against pattern " *#name# =". */
121                                 for(from = rcLine; (*from != '\0') && isspace((int)*from); from++)
122                                         ; /* Nothing more to do. */
123                                 if(strncmp(from, name, nameLen) != 0) {
124                                         continue;
125                                 }
126                                 for(from += nameLen; (*from != '\0') && isspace((int)*from); from++)
127                                         ; /* Nothing more to do. */
128                                 if(*from != '=') {
129                                         continue;
130                                 }
131
132                                 /* We found a line that sets the variable. */
133                                 (void)fclose(rcFile);
134                                 for(from++; (*from != '\0') && isspace((int)*from); from++)
135                                         ; /* Nothing more to do. */
136
137                                 /* Return a single word to allow for
138                                  * future free-format input. */
139                                 if(*from == '"') {
140                                         returnValue = from + 1;
141                                         for(from++, to = from; (*from != '\0') && (*from != '"'); from++, to++) {
142                                                 if(*from == '\\') {
143                                                         from++;
144                                                         switch(*from) {
145                                                         case 'b':
146                                                                 *to = '\b';
147                                                                 break;
148                                                         case 'f':
149                                                                 *to = '\f';
150                                                                 break;
151                                                         case 'n':
152                                                                 *to = '\n';
153                                                                 break;
154                                                         case 'r':
155                                                                 *to = '\r';
156                                                                 break;
157                                                         case 't':
158                                                                 *to = '\t';
159                                                                 break;
160                                                         case 'v':
161                                                                 *to = '\v';
162                                                                 break;
163                                                         default:
164                                                                 *to = *from;
165                                                                 break;
166                                                         }
167                                                 } else {
168                                                         *to = *from;
169                                                 }
170                                         }
171                                 } else {
172                                         returnValue = from;
173                                         for(to = from; (*to != '\0') && !isspace((int)*to); to++)
174                                                 ; /* Nothing more to do. */
175                                 }
176                                 *to = '\0';
177
178                                 if (returnValue != NULL) 
179                                         return(returnValue);
180                                 else 
181                                         break;
182                         }
183                 (void)fclose(rcFile);
184                 }
185         }
186         return(defaultValue);
187 }
188
189
190 int
191 GetUserName(char *name,
192             size_t length) {
193   struct passwd *myPasswd;
194   myPasswd = getpwuid(getuid());
195   if(myPasswd != NULL) {
196     strncpy(name, myPasswd->pw_name, length);
197     name[length - 1] = '\0';
198   }
199   endpwent();
200   return(myPasswd != NULL);
201 }
202
203 void
204 HoldSignal(int sig) {
205 #ifdef HAVE_SIGHOLD
206   sighold(sig);
207 #else
208   sigset_t set, oset;
209   sigemptyset(&set);
210   sigaddset(&set, sig);\
211   sigprocmask(SIG_BLOCK, &set, &oset);
212 #endif
213 }
214
215
216 int
217 MakeDirectory(const char *path,
218               mode_t mode,
219               int makeEntirePath) {
220
221   const char *endSubPath;
222   struct stat pathStat;
223   char subPath[255 + 1];
224
225   if(makeEntirePath) {
226     endSubPath = path;  /* This will ignore leading '/' */
227     while((endSubPath = strchr(endSubPath + 1, '/')) != NULL) {
228       memset(subPath, '\0', sizeof(subPath));
229       strncpy(subPath, path, endSubPath - path);
230       if((stat(subPath, &pathStat) == -1) && (errno == ENOENT)) {
231         if(mkdir(subPath, mode) == -1) {
232           return 0;
233         }
234       }
235       else if(!S_ISDIR(pathStat.st_mode)) {
236         return 0;
237       }
238     }
239   }
240
241   if((stat(path, &pathStat) == -1) && (errno == ENOENT)) {
242     return(mkdir(path, mode) != -1);
243   }
244   else {
245     return(S_ISDIR(pathStat.st_mode));
246   }
247 }
248
249
250
251 int
252 GetNWSLock(void **lock) {
253 #ifdef HAVE_PTHREAD_H
254         int ret;
255
256         if (lock == NULL) {
257                 return 0;
258         }
259         if (*lock == NULL) {
260                 /* let's play it safe: let's do one mutex at the time (in
261                  * case multiple threads are running on the same lock */
262                 if (pthread_mutex_lock(&nwsLock) != 0) {
263                         return 0;
264                 }
265                 /* there is no mutex yet: let's create it. We double
266                  * check in the pretty rare condition of having 2 threads
267                  * creating lock at the same time */
268                 if (*lock == NULL) {
269                         *lock = (void *)MALLOC(sizeof(pthread_mutex_t));
270                         pthread_mutex_init((pthread_mutex_t *)(*lock), NULL);
271                 }
272                 if (*lock == NULL || pthread_mutex_unlock(&nwsLock) != 0) {
273                         return 0;
274                 }
275         }
276         ret = pthread_mutex_lock((pthread_mutex_t *)(*lock));
277         if  (ret != 0) {
278                 fprintf(stderr, "GetNWSLock: Unable to lock (errno = %d)!\n", ret);
279                 return 0;
280         }
281 #endif
282         return 1;
283 }
284
285 int 
286 ReleaseNWSLock(void **lock) {
287
288 #ifdef HAVE_PTHREAD_H
289         if (lock == NULL || pthread_mutex_unlock((pthread_mutex_t *)*lock) != 0) {
290                 return 0;
291         }
292 #endif
293         return 1;
294 }
295
296 long
297 MicroTime(void) {
298   struct timeval tv;
299   gettimeofday(&tv, NULL);
300   return(tv.tv_sec * 1000000 + tv.tv_usec);
301 }
302
303
304 void
305 ReleaseSignal(int sig) {
306 #ifdef HAVE_SIGRELSE
307   sigrelse(sig);
308 #else
309   sigset_t set, oset;
310   sigemptyset(&set);
311   sigaddset(&set, sig);
312   sigprocmask(SIG_UNBLOCK, &set, &oset);
313 #endif
314 }
315
316
317 int
318 SignalAlarm(    handler h, 
319                 handler *old) {
320 #ifdef USE_ALARM_SIGNAL
321         handler tmp;
322         
323         tmp = signal(SIGALRM, h);
324         if (tmp == SIG_ERR) {
325                 return 0;
326         }
327         if (old != NULL)
328                 *old = tmp;
329
330 #endif
331         return 1;
332 }
333
334 /* It should be thread safe (alarm is thread safe) */
335 void
336 SetRealTimer(unsigned int numberOfSecs) {
337 #ifdef USE_ALARM_SIGNAL
338 #ifdef HAVE_SIGINTERRUPT
339         if (numberOfSecs > 0) {
340                 /* just interrupt a system call upon receipt of interrupt */
341                 siginterrupt(SIGALRM, 1);
342         }
343 #endif
344
345         alarm(numberOfSecs);
346 #endif
347 }
348