source: trunk/LMDZ.TITAN/libf/muphytitan/csystem.c @ 3026

Last change on this file since 3026 was 1897, checked in by jvatant, 7 years ago

Making Titan's hazy again - part II
+ Major updates of J.Burgalat YAMMS library and optical coupling, including :
++ Added the routines for haze optics inside YAMMS
++ Calling rad. transf. with interactive haze is plugged
in but should stay unactive as long as the microphysics is
in test phase : cf "uncoupl_optic_haze" flag : true for now !
++ Also some sanity checks for negative tendencies and
some others upkeep of YAMMS model
+ Also added a temporary CPP key USE_QTEST in physiq_mod
that enables to have microphysical tendencies separated
from dynamics for debugging and test phases
-- JVO and JB

File size: 19.9 KB
Line 
1/* Copyright Jérémie Burgalat (2010-2015,2017)
2 *
3 * jeremie.burgalat@univ-reims.fr
4 *
5 * This software is a computer program whose purpose is to provide configuration
6 * file and command line arguments parsing features to Fortran programs.
7 *
8 * This software is governed by the CeCILL-B license under French law and
9 * abiding by the rules of distribution of free software.  You can  use,
10 * modify and/ or redistribute the software under the terms of the CeCILL-B
11 * license as circulated by CEA, CNRS and INRIA at the following URL
12 * "http://www.cecill.info".
13 *
14 * As a counterpart to the access to the source code and  rights to copy,
15 * modify and redistribute granted by the license, users are provided only
16 * with a limited warranty  and the software's author,  the holder of the
17 * economic rights,  and the successive licensors  have only  limited
18 * liability.
19 *
20 * In this respect, the user's attention is drawn to the risks associated
21 * with loading,  using,  modifying and/or developing or reproducing the
22 * software by the user in light of its specific status of free software,
23 * that may mean  that it is complicated to manipulate,  and  that  also
24 * therefore means  that it is reserved for developers  and  experienced
25 * professionals having in-depth computer knowledge. Users are therefore
26 * encouraged to load and test the software's suitability as regards their
27 * requirements in conditions enabling the security of their systems and/or
28 * data to be ensured and,  more generally, to use and operate it in the
29 * same conditions as regards security.
30 *
31 * The fact that you are presently reading this means that you have had
32 * knowledge of the CeCILL-B license and that you accept its terms.
33 */
34
35#include <errno.h>
36#include <string.h>
37#include <stdlib.h>
38#include <stdio.h>
39#include <limits.h>
40#include <string.h>
41#include <libgen.h>
42#include <sys/param.h>  // MAXPATHLEN
43#include <sys/types.h>
44#include <sys/stat.h>
45#include <sys/ioctl.h>
46#include <pwd.h>
47#include <grp.h>
48#include <dirent.h>
49#include <fcntl.h>
50#include <time.h>
51#include <unistd.h>
52#include "csystem.h"
53
54// Hack to get MAXPATHLEN
55#ifndef MAXPATHLEN
56#define MAXPATHLEN 4096
57#endif
58
59/* Get errno */
60int c_get_errno(){
61  int ret = errno;
62  return ret;
63}
64
65/* Get the current working directory */
66char* c_getcwd(){
67  char *tmp;
68  tmp = (char *) malloc((MAXPATHLEN+1)*sizeof(char));
69  memset(tmp,'\0',MAXPATHLEN+1);
70  if (getcwd(tmp,MAXPATHLEN) == NULL) {
71    free(tmp);
72    tmp = NULL;
73  } 
74  return tmp;
75}
76
77
78/* Get the realpath of input path and saves it in output path */ 
79char* c_realpath(const char *input){
80  if (!strlen(input)) {
81    return c_getcwd();
82  }
83  return realpath(input,NULL);
84}
85
86
87/* Get directory name of input path */
88char* c_dirname(const char *in){
89  char *tmp = strdup(in);
90  char *ou = strdup(dirname(tmp));
91  free(tmp);
92  return ou;
93}
94
95/* Get base name of input path */
96char* c_basename(const char *in){
97  char* tmp = strdup(in);
98  char *ou = strdup(basename(tmp));
99  free(tmp);
100  return ou;
101}
102
103/* Get the corresponding name of the given user id */
104char* c_uname(int uid){
105  struct passwd  *pwd;
106  char *name;
107  name = NULL;
108  if ((pwd = getpwuid(uid)) !=  NULL){
109    name = strdup(pwd->pw_name);
110  }
111  return name;
112}
113
114/* Get the corresponding name of the given group id */
115char* c_gname(int gid){
116  struct group *grp;
117  char *name;
118  name = NULL;
119  if ((grp = getgrgid(gid)) != NULL){
120    name = strdup(grp->gr_name);
121  }
122  return name;
123}
124
125/* Get the error message of the given error id */
126char* c_strerror(int err){
127  char *tmp = strdup(strerror(err));
128  if (errno != 0)
129    tmp = "Unknown error\0";
130  return tmp;
131}
132
133
134/* Remove a directory and its contents recursively */
135int c_rmdir_f(const char *path) {
136  DIR *d = opendir(path);
137  size_t path_len = strlen(path);
138  int r = -1;
139  if (d) {
140    struct dirent *p;
141    r = 0;
142    while (!r && (p=readdir(d))) {
143      int r2 = -1;
144      char *buf;
145      size_t len;
146      /* Skip the names "." and ".." as we don't want to recurse on them. */
147      if (!strcmp(p->d_name, ".") || !strcmp(p->d_name, "..")) {
148        continue;
149      }
150      len = path_len + strlen(p->d_name) + 2; 
151      buf = malloc(len);
152      if (buf) {
153        struct stat statbuf;
154        snprintf(buf, len, "%s/%s", path, p->d_name);
155        if (!stat(buf, &statbuf)) {
156          if (S_ISDIR(statbuf.st_mode)) {
157            r2 = c_rmdir_f(buf);
158          } else {
159            r2 = unlink(buf);
160          }
161        }
162        free(buf);
163      }
164      r = r2;
165    }
166    closedir(d);
167  }
168  if (!r) {
169    r = rmdir(path);
170        return r?errno:0;
171  }
172  return r;
173}
174
175/* Get some file informations */
176int c_fstat(const char *p, int *pe, int *nl, int *ty, int *ui, int *gi, 
177            long *si, char a[20], char m[20], char c[20]){
178  struct stat stb;
179  struct tm *t;
180  int ret ;
181  //char *tmp;
182  char tmp[20];
183  *pe = *ty = *ui = *gi = *si = -1 ;
184  if (stat(p, &stb) != -1) {
185    *pe = (int)(stb.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO));
186    *nl = (int)(stb.st_nlink);
187    if (S_ISREG(stb.st_mode)) *ty = 0 + S_ISLNK(stb.st_mode);
188    else if (S_ISDIR(stb.st_mode)) *ty = 2 + S_ISLNK(stb.st_mode) ;
189    else *ty = 4;
190    *ui = (int)stb.st_uid ; *gi = (int)stb.st_gid ; *si = (long)stb.st_size ;
191    t = localtime(&stb.st_atime) ; ret = strftime(tmp, 20, "%F,%T", t); 
192    if(ret != 0) {strncpy(a,tmp,20); a[19] = '\0';}else{a[0] = '\0';}
193    t = localtime(&stb.st_mtime) ; ret = strftime(tmp, 20, "%F,%T", t);
194    if(ret != 0) {strncpy(m,tmp,20); m[19] = '\0';}else{m[0] = '\0';}
195    t = localtime(&stb.st_ctime) ; ret = strftime(tmp, 20, "%F,%T", t);
196    if(ret != 0) {strncpy(c,tmp,20); c[19] = '\0';}else{c[0] = '\0';}
197    return 0;
198  }
199  return errno;
200}
201
202/* Create a directory or a file in given path */
203int c_create(const char* path, mode_t mode, int astype, int forced){
204  char *p, *d;
205  mode_t perm, cmask;
206  int eval;
207  // we build a directory
208  if (!astype){
209    if(forced){eval=c_mkdirp(path,mode);}else{eval=c_mkdir(path,mode);}
210  }else{
211    // we build a file
212    if (forced){
213      p = strdup(path) ; if(p == NULL) {return errno;}
214      d = dirname(p) ; free(p) ; 
215      if(d == NULL) {return -9;}
216      // we attempts to create parent directory first
217      cmask = umask(0);
218      perm =((S_IRWXU | S_IRWXG | S_IRWXO) & ~(cmask & ~(S_IWUSR | S_IXUSR)));
219      (void)umask(cmask) ;
220      eval = c_mkdirp(d,perm); 
221      if(eval){return eval;}
222    }
223    eval = open(path,O_CREAT|O_EXCL,mode);
224    if (eval == -1) {eval=errno;}else{close(eval);eval=0;}
225  } 
226  return eval ;
227}
228
229/* Change current working directory */
230int c_chdir(const char *path){
231  if (chdir(path) != 0) return errno ;
232  return 0;
233}
234
235/* Remove a directory */
236int c_rmdir(const char *path){
237 if ( rmdir(path) != 0) return errno;
238  return 0;
239}
240
241/* Check if path is accessible */
242int c_access(const char *path, int perm) {
243  int ret;
244  if (perm<0 && perm >7) perm=0;
245  ret = access(path,perm);
246  if (ret) return errno;
247  return 0;
248}
249
250/* Rename a path */
251int c_rename(const char *old, const char *new){
252  if (rename(old,new) != 0) return errno ;
253  return 0;
254}
255
256/* Change path permissions */
257int c_chmod(const char *path, mode_t mode){
258  if (chmod(path,mode) != 0) return errno ;
259  return 0;
260}
261
262/* Create directory */
263int c_mkdir(const char *path, mode_t mode){
264  if(mkdir(path,mode) == 0) {
265    if (chmod(path, mode) == -1) return errno ;
266    return 0;
267  }else{
268    return errno;
269  }
270}
271
272
273int c_copy(const char *to, const char *from) {
274  int fd_to, fd_from;
275  char buf[4096];
276  ssize_t nread;
277  int saved_errno;
278
279  fd_from = open(from, O_RDONLY);
280  if (fd_from < 0)
281    return -1;
282
283  fd_to = open(to, O_WRONLY | O_CREAT | O_EXCL, 0666);
284  if (fd_to < 0)
285    goto out_error;
286
287  while (nread = read(fd_from, buf, sizeof buf), nread > 0) {
288    char *out_ptr = buf;
289    ssize_t nwritten;
290
291    do {
292      nwritten = write(fd_to, out_ptr, nread);
293
294      if (nwritten >= 0) {
295        nread -= nwritten;
296        out_ptr += nwritten;
297      } else if (errno != EINTR) {
298        goto out_error;
299      }
300    } while (nread > 0);
301  }
302
303  if (nread == 0) {
304    if (close(fd_to) < 0) {
305      fd_to = -1;
306      goto out_error;
307    }
308    close(fd_from);
309    /* Success! */
310    return 0;
311  }
312
313out_error:
314  saved_errno = errno;
315
316  close(fd_from);
317  if (fd_to >= 0)
318    close(fd_to);
319
320  errno = saved_errno;
321  return 1;
322}
323
324/* Remove file from filesytem */
325int c_remove(const char *path){
326  if (remove(path) != 0) return errno ;
327  return 0;
328}
329
330/* Get terminal size */
331int c_termsize(int *rows,int *cols){
332  struct winsize max;
333  int retval ;
334  retval = ioctl(0, TIOCGWINSZ , &max);
335  if (retval != 0) {
336    retval = errno ;
337    *rows = 20 ; *cols = 80 ;
338  }else{
339    *rows = max.ws_row ;
340    *cols = max.ws_col ;
341  }
342  return retval;
343}
344
345/* Get the current umask (in decimal system) */
346int c_umask(){
347  mode_t mask ;
348  mask = umask(S_IRWXU | S_IRWXG | S_IRWXO); (void) umask(mask) ;
349  return (int)mask;
350}
351
352/* ------------------ THIRD PARTY ------------------ */
353
354/*
355 *  Copyright (c) 1983, 1992, 1993
356 *   The Regents of the University of California.  All rights reserved.
357 *
358 *  Redistribution and use in source and binary forms, with or without
359 *  modification, are permitted provided that the following conditions
360 *  are met:
361 *  1. Redistributions of source code must retain the above copyright
362 *     notice, this list of conditions and the following disclaimer.
363 *  2. Redistributions in binary form must reproduce the above copyright
364 *     notice, this list of conditions and the following disclaimer in the
365 *     documentation and/or other materials provided with the distribution.
366 *  3. All advertising materials mentioning features or use of this software
367 *     must display the following acknowledgement:
368 *   This product includes software developed by the University of
369 *  California, Berkeley and its contributors.
370 *  4. Neither the name of the University nor the names of its contributors
371 *     may be used to endorse or promote products derived from this software
372 *     without specific prior written permission.
373 *
374 *  THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
375 *  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
376 *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
377 *  ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
378 *  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
379 *  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
380 *  OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
381 *  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
382 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
383 *  OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
384 *  SUCH DAMAGE.
385 */
386/* Creates directories recursively */
387int c_mkdirp(const char *path, mode_t mode) {
388  struct stat sb;
389  mode_t numask, oumask;
390  int first, last, retval;
391  char *cpath, *p;
392  cpath=strdup(path); if (cpath == NULL) return -1;
393  p = cpath; oumask = 0; retval = 0;
394  if (p[0] == '/') ++p;    /* Skip leading '/'. */
395  for (first = 1, last = 0; !last ; ++p) {
396    if (p[0] == '\0') last = 1;
397    else if (p[0] != '/') continue;
398    *p = '\0';
399    //if (! strlen(p) && p[1] == '\0') last = 1;
400    if (first) {
401      oumask = umask(0);
402      numask = oumask & ~(S_IWUSR | S_IXUSR);
403      (void)umask(numask);
404      first = 0;
405    }
406    if (last) (void)umask(oumask);
407    if (mkdir(cpath, last ? mode : S_IRWXU | S_IRWXG | S_IRWXO) < 0) {
408      if (errno == EEXIST || errno == EISDIR) {
409        if (stat(cpath, &sb) < 0) {
410          retval = 1; break;
411        } else if (!S_ISDIR(sb.st_mode)) {
412          if (last) errno = EEXIST; else errno = ENOTDIR;
413          retval = 1; break;
414        }
415      } else {
416        retval = 1; break;
417      }
418    } 
419    if (!last) *p = '/';
420  }
421  if (!first && !last) (void)umask(oumask);
422  if (!retval){
423    if (chmod(path, mode) == -1)  retval = errno ;
424  } else {
425   retval = errno;
426  }
427  free(cpath);
428  return retval ;
429}
430
431/*
432 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
433 *
434 * @APPLE_LICENSE_HEADER_START@
435 *
436 * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
437 * Reserved.  This file contains Original Code and/or Modifications of
438 * Original Code as defined in and that are subject to the Apple Public
439 * Source License Version 1.0 (the 'License').  You may not use this file
440 * except in compliance with the License.  Please obtain a copy of the
441 * License at http://www.apple.com/publicsource and read it before using
442 * this file.
443 *
444 * The Original Code and all software distributed under the License are
445 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
446 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
447 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
448 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
449 * License for the specific language governing rights and limitations
450 * under the License."
451 *
452 * @APPLE_LICENSE_HEADER_END@
453 *
454 * Modified version: J. Burgalat (2015)
455 *
456 */
457
458char* c_relpath(const char *path, const char *reldir) {
459  char start_path[MAXPATHLEN+1];
460  char end_path[MAXPATHLEN+1];
461  char *buf;
462  struct stat st;
463  int i,mc;
464  int last_elem;
465  int prev_path;
466  char *tmp,*cur;
467  buf = NULL;
468
469  if (realpath(reldir,start_path) == NULL) 
470    return buf;
471 
472  if (realpath(path,end_path) == NULL) 
473    return buf;
474
475  // stat the starting path
476  if (stat(start_path, &st) < 0) 
477    return buf;
478 
479  if ((st.st_mode & S_IFMT) != S_IFDIR) {
480    errno = ENOTDIR;
481    return buf;
482  } 
483  if (start_path[strlen(start_path) - 1] != '/')
484    strcat(start_path, "/");
485
486  // stat the ending path path
487  if (stat(end_path, &st) < 0) 
488    return buf;
489 
490  if ((st.st_mode & S_IFMT) == S_IFDIR
491      && end_path[strlen(end_path) - 1] != '/')
492    strcat(end_path, "/");
493
494  tmp = (char *) malloc((2*MAXPATHLEN+1)*sizeof(char));
495  memset(tmp,'\0',2*MAXPATHLEN+1);
496  cur = tmp;
497  /* strip common prefix */
498  i = 0;
499  last_elem = 0;
500  while (start_path[i] && start_path[i] == end_path[i]) {
501    if (start_path[i] == '/')
502      last_elem = i + 1;
503    i += 1;
504  }
505  prev_path = 0;
506  for (i = last_elem; start_path[i]; i += 1) {
507    if (start_path[i] == '/') {
508      if (prev_path){
509        *cur = '/'; cur++;
510      }
511      strncpy(cur,"..",2) ; cur +=2;
512      prev_path = 1;
513    }
514  }
515  if (end_path[last_elem]) {
516    if (prev_path) {
517      *cur = '/'; cur++;
518    }
519    prev_path = 1;
520    while (end_path[strlen(end_path) - 1] == '/')
521      end_path[strlen(end_path) - 1] = '\0';
522    strcpy(cur,&end_path[last_elem]) ;
523    cur += strlen(&end_path[last_elem]);
524  }
525  if (! prev_path){
526    *cur = '.' ; cur++ ;
527  }
528  // Normally here tmp contains our path. We just need to copy it in buf
529  mc = strlen(tmp)+1;
530  buf = (char *)malloc(mc*sizeof(char));
531  memset(buf,'\0',mc);
532  strncpy(buf,tmp,strlen(tmp));
533  cur = buf;
534  i=0;
535  while (*cur != '\0' && i < mc){
536    cur++;
537    i++;
538  }
539  free(tmp);
540  errno = 0;
541  return buf;
542}
543
544/*
545 * Author:  David Robert Nadeau
546 * Site:    http://NadeauSoftware.com/
547 * License: Creative Commons Attribution 3.0 Unported License
548 *          http://creativecommons.org/licenses/by/3.0/deed.en_US
549 *
550 * Cross-plateform way to get memory usage at a given time in fucking bytes !!
551 *
552 * Usage:
553 *
554 * size_t currentSize = getCurrentRSS( );
555 * size_t peakSize    = getPeakRSS( );
556 */
557
558#if defined(_WIN32)
559#include <windows.h>
560#include <psapi.h>
561#elif defined(__unix__) || defined(__unix) || defined(unix) || (defined(__APPLE__) && defined(__MACH__))
562#include <sys/resource.h>
563#if defined(__APPLE__) && defined(__MACH__)
564#include <mach/mach.h>
565#elif(defined(_AIX) || defined(__TOS__AIX__)) ||                                                                               \
566    (defined(__sun__) || defined(__sun) || defined(sun) && (defined(__SVR4) || defined(__svr4__)))
567#include <procfs.h>
568#endif
569#endif
570
571/**
572 * Returns the peak (maximum so far) resident set size (physical
573 * memory use) measured in bytes, or zero if the value cannot be
574 * determined on this OS.
575 */
576size_t c_getPeakRSS() {
577#if defined(_WIN32)
578    /* Windows -------------------------------------------------- */
579    PROCESS_MEMORY_COUNTERS info;
580    GetProcessMemoryInfo(GetCurrentProcess(), &info, sizeof(info));
581    return (size_t)info.PeakWorkingSetSize;
582
583#elif(defined(_AIX) || defined(__TOS__AIX__)) ||                                                                               \
584    (defined(__sun__) || defined(__sun) || defined(sun) && (defined(__SVR4) || defined(__svr4__)))
585    /* AIX and Solaris ------------------------------------------ */
586    struct psinfo psinfo;
587    int fd = -1;
588    if ((fd = open("/proc/self/psinfo", O_RDONLY)) == -1)
589        return (size_t)0L; /* Can't open? */
590    if (read(fd, &psinfo, sizeof(psinfo)) != sizeof(psinfo)) {
591        close(fd);
592        return (size_t)0L; /* Can't read? */
593    }
594    close(fd);
595    return (size_t)(psinfo.pr_rssize * 1024L);
596
597#elif defined(__unix__) || defined(__unix) || defined(unix) || (defined(__APPLE__) && defined(__MACH__))
598    /* BSD, Linux, and OSX -------------------------------------- */
599    struct rusage rusage;
600    getrusage(RUSAGE_SELF, &rusage);
601#if defined(__APPLE__) && defined(__MACH__)
602    return (size_t)rusage.ru_maxrss;
603#else
604    return (size_t)(rusage.ru_maxrss * 1024L);
605#endif
606
607#else
608    /* Unknown OS ----------------------------------------------- */
609    return (size_t)0L; /* Unsupported. */
610#endif
611}
612
613/**
614 * Returns the current resident set size (physical memory use) measured
615 * in bytes, or zero if the value cannot be determined on this OS.
616 */
617size_t c_getCurrentRSS() {
618#if defined(_WIN32)
619    /* Windows -------------------------------------------------- */
620    PROCESS_MEMORY_COUNTERS info;
621    GetProcessMemoryInfo(GetCurrentProcess(), &info, sizeof(info));
622    return (size_t)info.WorkingSetSize;
623
624#elif defined(__APPLE__) && defined(__MACH__)
625    /* OSX ------------------------------------------------------ */
626    struct mach_task_basic_info info;
627    mach_msg_type_number_t infoCount = MACH_TASK_BASIC_INFO_COUNT;
628    if (task_info(mach_task_self(), MACH_TASK_BASIC_INFO, (task_info_t)&info, &infoCount) != KERN_SUCCESS)
629        return (size_t)0L; /* Can't access? */
630    return (size_t)info.resident_size;
631
632#elif defined(__linux__) || defined(__linux) || defined(linux) || defined(__gnu_linux__)
633    /* Linux ---------------------------------------------------- */
634    long rss = 0L;
635    FILE *fp = NULL;
636    if ((fp = fopen("/proc/self/statm", "r")) == NULL)
637        return (size_t)0L; /* Can't open? */
638    if (fscanf(fp, "%*s%ld", &rss) != 1) {
639        fclose(fp);
640        return (size_t)0L; /* Can't read? */
641    }
642    fclose(fp);
643    return (size_t)rss * (size_t)sysconf(_SC_PAGESIZE);
644
645#else
646    /* AIX, BSD, Solaris, and Unknown OS ------------------------ */
647    return (size_t)0L; /* Unsupported. */
648#endif
649}
650
651
652 
653/* Get some informatiosn about the OS memory usage (from /proc/meminfo) */
654int c_getSystemMemory(long long int *m_total,long long int *m_available,long long int *m_free){
655    FILE* fp;
656    char buf[1024];
657    char *tmp,*p;
658    int ts;
659    long long int mem1 = 0L,mem2 = 0L,mem3 = 0L;
660    if (m_total) (*m_total) = mem1;
661    if (m_available) (*m_free) = mem2;
662    if (m_free) (*m_free) = mem3;
663    if ((fp = fopen("/proc/meminfo", "r")) == NULL) 
664        return 1;
665    while (fgets(buf, sizeof(buf), fp) != NULL){
666        ts = strlen(buf) - 1; buf[ts] = '\0'; 
667        tmp = strndup(&buf[0],ts);
668        // check our 3 cases
669        if (ts >= 9 && !strncmp(tmp,"MemTotal:",9)){
670            // extract the two first tokens.
671            p=strtok(tmp, " "); p=strtok(NULL, " ");
672            // convert the value.
673            mem1 = strtoll(p,NULL,10);
674        }
675        if (ts >= 13 && !strncmp(tmp,"MemAvailable:",13)){
676            p=strtok(tmp, " "); p=strtok(NULL, " "); 
677            mem2 = strtoll(p,NULL,10);
678        }   
679        if (ts >= 8 && !strncmp(tmp,"MemFree:",8)){
680            p=strtok(tmp, " "); p=strtok(NULL, " "); 
681            mem3 = strtoll(p,NULL,10);
682        }
683        free(tmp);
684    }
685    fclose(fp);
686    if (m_total) (*m_total) = mem1;
687    if (m_available) (*m_available) = mem2;
688    if (m_free) (*m_free) = mem3;
689    return 0;
690}
Note: See TracBrowser for help on using the repository browser.