1
/*___INFO__MARK_BEGIN__*/
2
/*************************************************************************
4
* The Contents of this file are made available subject to the terms of
5
* the Sun Industry Standards Source License Version 1.2
7
* Sun Microsystems Inc., March, 2001
10
* Sun Industry Standards Source License Version 1.2
11
* =================================================
12
* The contents of this file are subject to the Sun Industry Standards
13
* Source License Version 1.2 (the "License"); You may not use this file
14
* except in compliance with the License. You may obtain a copy of the
15
* License at http://gridengine.sunsource.net/Gridengine_SISSL_license.html
17
* Software provided under this License is provided on an "AS IS" basis,
18
* WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
19
* WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
20
* MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
21
* See the License for the specific provisions governing your rights and
22
* obligations concerning the Software.
24
* The Initial Developer of the Original Code is: Sun Microsystems, Inc.
26
* Copyright: 2001 by Sun Microsystems, Inc.
28
* All Rights Reserved.
30
************************************************************************/
31
/*___INFO__MARK_END__*/
41
#include "sge_answer.h"
43
#include "sge_string.h"
44
#include "sge_parse_num_par.h"
47
#include "msg_utilib.h"
51
/* to be independent from irix' compiler options */
53
# define RLIM_INFINITY 0x7fffffffffffffffLL
55
# define RLIM_INFINITY 0
56
#elif defined(WIN32NATIVE)
57
# define RLIM_INFINITY 0
60
#if !defined(CRAY) && !defined(SOLARIS64) && !defined(SOLARISAMD64)
61
# define RLIM_MAX RLIM_INFINITY
63
# define RLIM_MAX 0x7fffffffffffffff
67
# define strcasecmp( a, b) stricmp( a, b)
68
# define strncasecmp( a, b, n) strnicmp( a, b, n)
71
u_long32 sge_parse_num_val(sge_rlim_t *rlimp, double *dvalp,
72
const char *str, const char *where,
73
char *err_str, int err_len);
75
static double get_multiplier(sge_rlim_t *rlimp, char **dptr,
76
const char *where, char *err_str, int err_len);
78
static sge_rlim_t add_infinity(sge_rlim_t rlim, sge_rlim_t offset);
81
/* -----------------------------------------
87
is a wrapper around sge_parse_num_val()
88
for migration to code that returns an
89
error and does not exit()
91
parse_ulong_val() should be used instead
92
of sge_parse_num_val()
95
uvalp - where to write the parsed value
99
TYPE_MEM [mMkK] postfix
100
TYPE_BOO true or false
101
TYPE_ACC user access to queue
102
if type == 0 all above types will get accepted
107
1 - ok, value in *uvalp is valid
111
MT-NOTE: parse_ulong_val() is MT safe
113
int parse_ulong_val(double *dvalp, u_long32 *uvalp, u_long32 type,
114
const char *s, char *error_str, int error_len)
116
return extended_parse_ulong_val(dvalp, uvalp, type, s, error_str, error_len, 1, false);
119
/* enable_infinity enhancement: if 0 no infinity value is allowed */
120
/* MT-NOTE: extended_parse_ulong_val() is MT safe */
121
int extended_parse_ulong_val(double *dvalp, u_long32 *uvalp, u_long32 type,
122
const char *s, char *error_str, int error_len,
123
int enable_infinity, bool only_positive)
125
int retval = 0; /* error */
133
if (only_positive && (strchr(s, '-') != NULL)) {
135
sge_strlcpy(error_str, MSG_GDI_NUMERICALVALUENOTPOSITIVE, error_len);
140
if ((enable_infinity == 0) && (strcasecmp(s,"infinity") == 0)) {
142
sge_strlcpy(error_str, MSG_GDI_VALUETHATCANBESETTOINF, error_len);
152
here we have to convert from string
153
representation of the request value
158
retval = sge_parse_loglevel_val(uvalp, s);
160
if (error_str != NULL) {
161
sge_strlcpy(error_str, "loglevel value", error_len);
171
/* dirty but isolated .. */
172
if (error_str != NULL) {
173
*uvalp = sge_parse_num_val(NULL, dvalp, s, s, error_str, error_len);
174
if (!error_str[0]) /* err msg written ? */
175
retval = 1; /* no error */
178
sge_strlcpy(error_str, "integer value", error_len);
179
else if (type==TYPE_TIM)
180
sge_strlcpy(error_str, "time value", error_len);
181
else if (type==TYPE_BOO)
182
sge_strlcpy(error_str, "boolean value", error_len);
183
else if (type==TYPE_DOUBLE)
184
sge_strlcpy(error_str, "double value", error_len);
186
sge_strlcpy(error_str, "memory value", error_len);
190
*uvalp = sge_parse_num_val(NULL, dvalp, s, s, dummy, sizeof(dummy));
191
if (!dummy[0]) { /* err msg written ? */
192
retval = 1; /* no error */
203
/*----------------------------------------------------------------------*/
204
/* MT-NOTE: sge_parse_loglevel_val() is MT safe */
205
bool sge_parse_loglevel_val(u_long32 *uval, const char *s)
212
if (!strcasecmp("log_crit", s)) {
214
} else if (!strcasecmp("log_err", s)) {
216
} else if (!strcasecmp("log_warning", s)) {
218
} else if (!strcasecmp("log_notice", s)) {
220
} else if (!strcasecmp("log_info", s)) {
222
} else if (!strcasecmp("log_debug", s)) {
232
* return rlim multiplied with muli
234
* if the result would exceed sge_rlim_t
235
* the result is set to RLIM_INFINITY
238
* MT-NOTE: mul_infinity() is MT safe
240
sge_rlim_t mul_infinity(sge_rlim_t rlim, sge_rlim_t muli)
242
if (rlim == RLIM_INFINITY ||
243
muli == RLIM_INFINITY )
244
return RLIM_INFINITY;
246
if ((sge_rlim_t)(RLIM_MAX/muli)<rlim)
247
rlim = RLIM_INFINITY;
254
* return rlim added to offset
256
* if the result would exceed sge_rlim_t
257
* the result is set to RLIM_INFINITY
260
* MT-NOTE: add_infinity() is MT safe
262
static sge_rlim_t add_infinity(sge_rlim_t rlim, sge_rlim_t offset)
264
if (rlim == RLIM_INFINITY || offset == RLIM_INFINITY) {
265
return RLIM_INFINITY;
268
if ((sge_rlim_t)(RLIM_MAX-offset) < rlim) {
269
rlim = RLIM_INFINITY;
277
/***********************************************************************
279
* get a multiplier for number value attribute requests
281
* Attribute requests may look like -l sc=123x,...
282
* with x being one of
284
* k : Multiplier = 1000
285
* K : Multiplier = 1024
286
* m : Multiplier = 1000*1000
287
* M : Multiplier = 1024*1024
288
* g : Multiplier = 1000*1000*1000
289
* G : Multiplier = 1024*1024*1024
292
* MT-NOTE: get_multiplier() is MT safe
293
**********************************************************************/
295
static double get_multiplier(sge_rlim_t *rlimp, char **dptr,
296
const char *where, char *err_str, int err_len)
301
/* parse for k,K,m,M multipliers at the end of the value
302
* string; strtod returns dptr to point to this location
317
*rlimp = 1000 * 1000;
322
*rlimp = 1024 * 1024;
326
mul = 1000 * 1000 * 1000;
327
*rlimp = mul_infinity(mul_infinity(1000, 1000), 1000);
331
mul = 1024 * 1024 * 1024;
332
*rlimp = mul_infinity(mul_infinity(1024, 1024), 1024);
335
case ',': /* no multiplier */
336
case '\0': /* no multiplier */
337
case '/': /* no multiplier */
338
case ' ': /* no multiplier */
341
snprintf(err_str, err_len, MSG_GDI_UNRECOGNIZEDVALUETRAILER_SS , *dptr, where);
345
if ((**dptr != ',') && (**dptr != '\0') && (**dptr != '/')) {
346
snprintf(err_str, err_len, MSG_GDI_UNEXPECTEDENDOFNUMERICALVALUE_SC , where, **dptr);
353
/***********************************************************************
354
* sge_parse_num_val -
355
* parse numeric attribute values from command-line
357
* Numeric attribute values may look like -l <attr>=<num><m>,...
358
* with <num> being a decimal (both integer and fixed float),
359
* hex and octal constant. <m> is a multiplier (see get_multiplier
364
* call the good old parse_num_val() with a non null argument for err_str
365
* and it will ++NOT++ abort your daemon.
367
* in case of a parsing error the err_str gets filled with an error
371
* MT-NOTE: sge_parse_num_val() is MT safe
372
**********************************************************************/
375
sge_parse_num_val(sge_rlim_t *rlimp, double *dvalp,
376
const char *str, const char *where,
377
char *err_str, int err_len)
380
sge_rlim_t rlim, rlmuli;
394
if (!strcasecmp(str, "true")) {
395
/* C-language says bool is a numeric. For reasons of simplicity we
401
else if (!strcasecmp(str, "false")) {
406
else if (!strcasecmp(str, "infinity")) {
407
*dvalp = DBL_MAX; /* use this for comparing limits */
408
*rlimp = RLIM_INFINITY; /* use this for limit setting */
410
return 0xFFFFFFFF; /* return max ulong in 32 bit */
415
else if (strchr(str, ':')) {
416
/* This is a time value in the format hr:min:sec */
418
/* find the hours first */
419
double t = strtod(str, &dptr);
420
if (t > 0x7fffffff) {
421
snprintf(err_str, err_len, MSG_GDI_NUMERICALVALUEFORHOUREXCEEDED_SS , where, str);
424
ldummy = (u_long32)(3600 * t);
425
*rlimp = (sge_rlim_t)(long)mul_infinity(t, 3600.0);
428
if ((*dptr) != ':') {
429
snprintf(err_str, err_len, MSG_GDI_NUMERICALVALUEINVALID_SS , where, str);
432
/* now go for the minutes */
434
t = strtod(dptr, &dptr);
435
if (t > 0x7fffffff) {
436
snprintf(err_str, err_len, MSG_GDI_NUMERICALVALUEFORMINUTEEXCEEDED_SS , where, str);
439
ldummy += (u_long32)(60 * t);
440
*rlimp = add_infinity(*rlimp, (sge_rlim_t)(60*t));
443
if ((*dptr) != ':') {
444
snprintf(err_str, err_len, MSG_GDI_NUMERICALVALUEINVALID_SS , where, str);
447
/* the seconds finally */
450
t = strtod(dptr, &dptr);
451
ldummy += (u_long32)t;
452
*rlimp = (sge_rlim_t)(long)add_infinity(*rlimp, t);
456
if (!isspace((int) *dptr)) {
457
snprintf(err_str, err_len, MSG_GDI_NUMERICALVALUEINVALID_SS , where, str);
466
else if (strchr(str, '.') || *str != '0') {
467
/* obviously this is no hex and no oct
468
* ==> allow for both decimal and fixed float
471
double t = strtod(str, &dptr);
478
if ((dummy == 0.0) && (dptr == str)) { /* no valid number ==> bail */
479
snprintf(err_str, err_len, MSG_GDI_NUMERICALVALUEINVALIDNONUMBER_SS , where, str);
484
if (!(muli = get_multiplier(&rlmuli, &dptr, where, err_str, err_len)))
486
dummy = (u_long32) (dummy * muli);
489
if (t > RLIM_MAX || rlmuli>= RLIM_MAX || (double)(RLIM_MAX/muli)<t)
490
*rlimp = RLIM_INFINITY;
492
*rlimp = (sge_rlim_t)(t*rlmuli);
494
return (u_long32)dummy;
497
else { /* if ( strchr(str,'.') || *str != '0' ) */
498
/* This is either a hex or an octal ==> no fixed float allowed;
501
u_long32 t = strtol(str, &dptr, 0); /* base=0 will handle both hex and oct */
506
if (dptr == str) { /* no valid number ==> bail */
507
snprintf(err_str, err_len, MSG_GDI_NUMERICALVALUEINVALIDNOHEXOCTNUMBER_SS , where, str);
511
if (!(muli = get_multiplier(&rlmuli, &dptr, where, err_str, err_len)))
513
ldummy *= (u_long32)muli;
514
*rlimp = mul_infinity(*rlimp, rlmuli);
517
return (u_long32)ldummy;