SURFEX v8.1
General documentation of Surfex
cargs.c
Go to the documentation of this file.
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <sys/types.h>
5 #include <unistd.h>
6 #include <limits.h>
7 
8 #include "cargs.h"
9 
10 typedef struct {
11  char *name;
12  int len;
13 } arg_t;
14 
15 static arg_t *args = NULL;
16 static int numargs = -1;
17 static char *cl_terminate = NULL;
18 static char *a_out = NULL;
19 
20 #if !defined(PSCMD)
21 #define PSCMD "/bin/ps"
22 #endif /* !defined(PSCMD) */
23 
24 #if !defined(TAILCMD)
25 #define TAILCMD "/usr/bin/tail"
26 #endif /* !defined(TAILCMD) */
27 
28 static const char *get_a_out()
29 {
30  /* progname is a blank string;
31  this is most likely due to a Fortran-call to getarg
32  from program that has a C-main program, thus Fortran getarg
33  may return a blank string */
34 
35  /* Using an alternative method of getting a.out :
36 
37  ps -p<pid> | tail -1 | awk '{print $NF}'
38 
39  This can give false positives, as we search the path for the binary: we may have
40  executed ./MASTER rather than the first MASTER in the path.
41 
42  Naturally this cannot be the nicest method around ;-(
43  So, a competition is launched: make this better and
44  you may win a week in Bahamas!!
45 
46  */
47 
48 #if defined(LINUX)
49  /* On Linux, the following is more reliable, if /proc is available.
50  */
51  if (!a_out) {
52  int len;
53  char symlink[NAME_MAX], real_exe[NAME_MAX];
54  snprintf(symlink, NAME_MAX, "/proc/%d/exe", getpid());
55  if ((len = readlink(symlink, real_exe, NAME_MAX)) > 0) {
56  a_out = malloc((len+1)*sizeof(*a_out));
57  strncpy(a_out, real_exe, len);
58  a_out[len] = '\0';
59  }
60  }
61 #endif
62  if (!a_out && (access(PSCMD,X_OK) == 0)) {
63  char cmd[sizeof(PSCMD) + sizeof(TAILCMD) + 100];
64  FILE *fp = NULL;
65  pid_t pid = getpid();
66  sprintf(cmd,"%s -p%d | %s -1 | awk '{print $NF}'", PSCMD, (int)pid, TAILCMD);
67  fp = popen(cmd, "r");
68  if (fp) {
69  char c[65536];
70  if (fscanf(fp,"%s",c) == 1) {
71  if (!strchr(c,'/')) {
72  /* The file path was NOT embedded in the name
73  ==> Must search from $PATH f.ex. /bin:/usr/bin:/some/thing/else:/etc/bin */
74  char *path = getenv("PATH");
75  if (path) {
76  int lenc = strlen(c);
77  char *saved = strdup(path);
78  char *start = saved;
79  char *token = strtok(saved,":");
80  do {
81  int lenf = strlen(start) + 1 + lenc + 1;
82  char *fullpath = malloc(lenf * sizeof(*fullpath));
83  snprintf(fullpath,lenf,"%s/%s",start,c);
84  if (access(fullpath,X_OK) == 0) { /* It's this one!! */
85  a_out = fullpath;
86  break; /* do { ... } while (token) */
87  }
88  free(fullpath);
89  start = token;
90  token = strtok(NULL,":");
91  } while (token);
92  free(saved);
93  }
94  } /* if (!strchr(c,'/')) */
95  if (!a_out) a_out = strdup(c);
96  }
97  pclose(fp);
98  }
99  }
100  if (!a_out) a_out = strdup("/unknown/executable");
101  return a_out;
102 }
103 
104 
105 void ec_PutArgs(int argc, char *argv[])
106 {
107  if (numargs == -1 && !args) {
108  if (argc > 0) {
109  int j;
110  args = calloc(argc, sizeof(arg_t));
111  /* cl_terminate: see ifsaux/module/mpl_arg_mod.F90 */
112  if (!cl_terminate) {
113  char *env = getenv("MPL_CL_TERMINATE");
114  cl_terminate = env ? strdup(env) : strdup("-^");
115  }
116  numargs = 0;
117  for (j=0; j<argc; j++) {
118  if (!argv[j] || strcmp(argv[j],cl_terminate) == 0) break;
119  args[j].name = strdup(argv[j]);
120  args[j].len = strlen(argv[j]);
121  numargs++;
122  }
123  if (numargs == 0) {
124  const char *arg0 = get_a_out();
125  args[0].name = strdup(arg0);
126  args[0].len = strlen(arg0);
127  }
128  else {
129  if (a_out) free(a_out);
130  a_out = strdup(args[0].name);
131  numargs--; /* Fortran # of args == C # of args - 1 */
132  }
133  } /* if (argc > 0) */
134  } /* if (numargs == -1 && !args) */
135 }
136 
137 
138 const char *ec_GetArgs(int argno)
139 {
140  const char *arg = NULL;
141  if (argno == 0 && !args) {
142  arg = get_a_out();
143  }
144  else if (argno >= 0 && argno <= numargs && args) {
145  arg = args[argno].name;
146  }
147  return arg;
148 }
149 
150 
151 int ec_NumArgs(void) { return numargs; }
152 
153 int ec_argc(void) { return 1 + ec_NumArgs(); }
154 
155 char **ec_argv(void)
156 {
157  int j, argc = ec_argc();
158  char **argv = NULL;
159  argv = calloc((argc + 1), sizeof(*argv));
160  for (j=0; j<argc; j++) {
161  argv[j] = (char *)ec_GetArgs(j);
162  }
163  argv[argc] = NULL;
164  return argv;
165 }
166 
167 
168 /* Fortran interface */
169 
170 int iargc_c_(void) { return numargs; }
171 int iargc_c (void) { return numargs; }
172 
173 
174 void getarg_c_(const int *argno, char *arg
175  /* Hidden argument */
176  , const int arg_len)
177 {
178  int Argno = argno ? *argno : -1;
179  if (arg && arg_len > 0 &&
180  Argno >= 0 && Argno <= numargs && args && args[Argno].name) {
181  const char *s = args[Argno].name;
182  int len = args[Argno].len;
183  if (arg_len < len) len = arg_len;
184  strncpy(arg,s,len);
185  if (arg_len > len) memset(&arg[len],' ',arg_len-len);
186  }
187 }
188 
189 
190 void getarg_c (const int *argno, char *arg
191  /* Hidden argument */
192  , const int arg_len)
193 {
194  getarg_c_(argno, arg, arg_len);
195 }
196 
197 
198 void putarg_c_(const int *argno, const char *arg
199  /* Hidden argument */
200  , int arg_len)
201 {
202  int Argno = argno ? *argno : -1;
203  if (arg && arg_len >= 0 &&
204  Argno >= 0 && Argno <= numargs && args) {
205  char *s = calloc(arg_len+1,sizeof(*s));
206  strncpy(s,arg,arg_len);
207  s[arg_len] = '\0';
208  if (args[Argno].name) free(args[Argno].name);
209  args[Argno].name = s;
210  args[Argno].len = arg_len;
211  }
212 }
213 
214 
215 void putarg_c (const int *argno, const char *arg
216  /* Hidden argument */
217  , int arg_len)
218 {
219  putarg_c_(argno, arg, arg_len);
220 }
221 
222 
223 void putarg_info_(const int *argc, const char *cterm
224  /* Hidden argument */
225  , int cterm_len)
226 {
227  int Argc = argc ? *argc : 0;
228  if (cterm && cterm_len >= 0) {
229  if (cl_terminate) free(cl_terminate);
230  cl_terminate = calloc(cterm_len+1,sizeof(*cl_terminate));
231  strncpy(cl_terminate,cterm,cterm_len);
232  cl_terminate[cterm_len] = '\0';
233  }
234  if (numargs >= 0 || args) {
235  if (args) {
236  int j;
237  for (j=0; j<=numargs; j++) { /* note: "j<=", not "j<" */
238  if (args[j].name) free(args[j].name);
239  }
240  free(args);
241  args = NULL;
242  } /* if (args) */
243  numargs = -1;
244  }
245  /* Re-initialize args & numargs */
246  if (Argc < 0) Argc = 0;
247  numargs = Argc;
248  args = calloc(1 + numargs, sizeof(arg_t));
249 }
250 
251 void putarg_info (const int *argc, const char *cterm
252  /* Hidden argument */
253  , int cterm_len)
254 {
255  putarg_info_(argc, cterm, cterm_len);
256 }
const char * ec_GetArgs(int argno)
Definition: cargs.c:138
char ** ec_argv(void)
Definition: cargs.c:155
void getarg_c_(const int *argno, char *arg, const int arg_len)
Definition: cargs.c:174
void putarg_c(const int *argno, const char *arg, int arg_len)
Definition: cargs.c:215
int iargc_c(void)
Definition: cargs.c:171
void ec_PutArgs(int argc, char *argv[])
Definition: cargs.c:105
void getarg_c(const int *argno, char *arg, const int arg_len)
Definition: cargs.c:190
quick &counting sorts only inumt inumt name
int ec_argc(void)
Definition: cargs.c:153
int ec_NumArgs(void)
Definition: cargs.c:151
FILE * fp
Definition: opfla_perfmon.c:24
void putarg_c_(const int *argno, const char *arg, int arg_len)
Definition: cargs.c:198
void putarg_info_(const int *argc, const char *cterm, int cterm_len)
Definition: cargs.c:223
static arg_t * args
Definition: cargs.c:15
void putarg_info(const int *argc, const char *cterm, int cterm_len)
Definition: cargs.c:251
int snprintf(char *str, size_t size, const char *format,...)
Definition: endian.c:108
static char * cl_terminate
Definition: cargs.c:17
static const char * get_a_out()
Definition: cargs.c:28
int iargc_c_(void)
Definition: cargs.c:170
static int numargs
Definition: cargs.c:16
static char * a_out
Definition: cargs.c:18
pid_t pid
Definition: opfla_perfmon.c:22