]>
git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - libxcmd/input.c
2 * Copyright (c) 2003-2005 Silicon Graphics, Inc.
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation.
9 * This program is distributed in the hope that it would be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write the Free Software Foundation,
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 #include "platform_defs.h"
24 #if defined(ENABLE_READLINE)
25 # include <readline/history.h>
26 # include <readline/readline.h>
27 #elif defined(ENABLE_EDITLINE)
28 # include <histedit.h>
31 extern char *progname
;
36 static char prompt
[FILENAME_MAX
+ 2 /*"> "*/ + 1 /*"\0"*/ ];
39 snprintf(prompt
, sizeof(prompt
), "%s> ", progname
);
43 #if defined(ENABLE_READLINE)
49 line
= readline(get_prompt());
54 #elif defined(ENABLE_EDITLINE)
55 static char *el_get_prompt(EditLine
*e
) { return get_prompt(); }
66 hist
= history_init();
67 history(hist
, &hevent
, H_SETSIZE
, 100);
68 el
= el_init(progname
, stdin
, stdout
, stderr
);
70 el_set(el
, EL_SIGNAL
, 1);
71 el_set(el
, EL_PROMPT
, el_get_prompt
);
72 el_set(el
, EL_HIST
, history
, (const char *)hist
);
74 line
= strdup(el_gets(el
, &count
));
79 history(hist
, &hevent
, H_ENTER
, line
);
84 # define MAXREADLINESZ 1024
88 char *p
, *line
= malloc(MAXREADLINESZ
);
92 printf("%s", get_prompt());
94 if (!fgets(line
, MAXREADLINESZ
, stdin
)) {
98 p
= line
+ strlen(line
);
99 if (p
!= line
&& p
[-1] == '\n')
112 char **rval
= calloc(sizeof(char *), 1);
114 while (rval
&& (p
= strsep(&input
, " ")) != NULL
) {
118 rval
= realloc(rval
, sizeof(*rval
) * (c
+ 1));
147 for (len
= 0, tmp
= val
; tmp
> 0; tmp
= tmp
/ base
)
149 return len
== 0 ? 1 : len
;
153 * Convert string to int64_t, set errno if the conversion fails or
154 * doesn't fit. Does not allow unit specifiers. Sets errno to zero
155 * prior to conversion so you can check for bad inputs by examining
156 * errno immediately after the call.
167 i
= strtoll(s
, &sp
, base
);
169 * If the input would over or underflow, return the clamped
170 * value and let the user check errno. If we went all the
171 * way to the end of the input, return the converted value;
172 * errno will be zero.
174 if (errno
|| (*sp
== '\0' && sp
!= s
))
177 /* Not all the input was consumed, return error. */
183 * Convert string to int32_t, set errno if the conversion fails or
184 * doesn't fit. Does not allow unit specifiers. Sets errno to zero
185 * prior to conversion so you can check for bad inputs by examining
186 * errno immediately after the call.
195 i
= cvt_s64(s
, base
);
198 if (i
> INT32_MAX
|| i
< INT32_MIN
) {
206 * Convert string to int16_t, set errno if the conversion fails or
207 * doesn't fit. Does not allow unit specifiers. Sets errno to zero
208 * prior to conversion so you can check for bad inputs by examining
209 * errno immediately after the call.
218 i
= cvt_s64(s
, base
);
221 if (i
> INT16_MAX
|| i
< INT16_MIN
) {
229 * Convert string to uint64_t, set errno if the conversion fails or
230 * doesn't fit. Does not allow unit specifiers. Sets errno to zero
231 * prior to conversion so you can check for bad inputs by examining
232 * errno immediately after the call.
243 i
= strtoll(s
, &sp
, base
);
245 * If the input would over or underflow, return the clamped
246 * value and let the user check errno. If we went all the
247 * way to the end of the input, return the converted value;
248 * errno will be zero.
250 if (errno
|| (*sp
== '\0' && sp
!= s
))
253 /* Not all the input was consumed, return error. */
259 * Convert string to uint32_t, set errno if the conversion fails or
260 * doesn't fit. Does not allow unit specifiers. Sets errno to zero
261 * prior to conversion so you can check for bad inputs by examining
262 * errno immediately after the call.
271 i
= cvt_u64(s
, base
);
274 if (i
> UINT32_MAX
) {
282 * Convert string to uint16_t, set errno if the conversion fails or
283 * doesn't fit. Does not allow unit specifiers. Sets errno to zero
284 * prior to conversion so you can check for bad inputs by examining
285 * errno immediately after the call.
294 i
= cvt_u64(s
, base
);
297 if (i
> UINT16_MAX
) {
304 #define EXABYTES(x) ((long long)(x) << 60)
305 #define PETABYTES(x) ((long long)(x) << 50)
306 #define TERABYTES(x) ((long long)(x) << 40)
307 #define GIGABYTES(x) ((long long)(x) << 30)
308 #define MEGABYTES(x) ((long long)(x) << 20)
309 #define KILOBYTES(x) ((long long)(x) << 10)
321 i
= strtoll(s
, &sp
, 0);
322 if (i
== 0 && sp
== s
)
333 return i
* blocksize
;
335 return i
* sectorsize
;
352 #define TO_EXABYTES(x) ((x) / EXABYTES(1))
353 #define TO_PETABYTES(x) ((x) / PETABYTES(1))
354 #define TO_TERABYTES(x) ((x) / TERABYTES(1))
355 #define TO_GIGABYTES(x) ((x) / GIGABYTES(1))
356 #define TO_MEGABYTES(x) ((x) / MEGABYTES(1))
357 #define TO_KILOBYTES(x) ((x) / KILOBYTES(1))
368 precise
= ((double)value
* 1000 == (double)(int)value
* 1000);
370 if (value
>= EXABYTES(1)) {
371 fmt
= precise
? "%.f EiB" : "%.3f EiB";
372 snprintf(str
, size
, fmt
, TO_EXABYTES(value
));
373 } else if (value
>= PETABYTES(1)) {
374 fmt
= precise
? "%.f PiB" : "%.3f PiB";
375 snprintf(str
, size
, fmt
, TO_PETABYTES(value
));
376 } else if (value
>= TERABYTES(1)) {
377 fmt
= precise
? "%.f TiB" : "%.3f TiB";
378 snprintf(str
, size
, fmt
, TO_TERABYTES(value
));
379 } else if (value
>= GIGABYTES(1)) {
380 fmt
= precise
? "%.f GiB" : "%.3f GiB";
381 snprintf(str
, size
, fmt
, TO_GIGABYTES(value
));
382 } else if (value
>= MEGABYTES(1)) {
383 fmt
= precise
? "%.f MiB" : "%.3f MiB";
384 snprintf(str
, size
, fmt
, TO_MEGABYTES(value
));
385 } else if (value
>= KILOBYTES(1)) {
386 fmt
= precise
? "%.f KiB" : "%.3f KiB";
387 snprintf(str
, size
, fmt
, TO_KILOBYTES(value
));
389 snprintf(str
, size
, "%f bytes", value
);
393 #define MINUTES_TO_SECONDS(m) ((m) * 60)
394 #define HOURS_TO_SECONDS(h) ((h) * MINUTES_TO_SECONDS(60))
395 #define DAYS_TO_SECONDS(d) ((d) * HOURS_TO_SECONDS(24))
396 #define WEEKS_TO_SECONDS(w) ((w) * DAYS_TO_SECONDS(7))
405 i
= strtoul(s
, &sp
, 0);
406 if (i
== 0 && sp
== s
)
410 if ((*sp
== 'm' && sp
[1] == '\0') ||
411 (strcmp(sp
, "minutes") == 0) ||
412 (strcmp(sp
, "minute") == 0))
413 return MINUTES_TO_SECONDS(i
);
414 if ((*sp
== 'h' && sp
[1] == '\0') ||
415 (strcmp(sp
, "hours") == 0) ||
416 (strcmp(sp
, "hour") == 0))
417 return HOURS_TO_SECONDS(i
);
418 if ((*sp
== 'd' && sp
[1] == '\0') ||
419 (strcmp(sp
, "days") == 0) ||
420 (strcmp(sp
, "day") == 0))
421 return DAYS_TO_SECONDS(i
);
422 if ((*sp
== 'w' && sp
[1] == '\0') ||
423 (strcmp(sp
, "weeks") == 0) ||
424 (strcmp(sp
, "week") == 0))
425 return WEEKS_TO_SECONDS(i
);
430 tadd(struct timeval t1
, struct timeval t2
)
432 t1
.tv_usec
+= t2
.tv_usec
;
433 if (t1
.tv_usec
> 1000000) {
434 t1
.tv_usec
-= 1000000;
437 t1
.tv_sec
+= t2
.tv_sec
;
442 tsub(struct timeval t1
, struct timeval t2
)
444 t1
.tv_usec
-= t2
.tv_usec
;
445 if (t1
.tv_usec
< 0) {
446 t1
.tv_usec
+= 1000000;
449 t1
.tv_sec
-= t2
.tv_sec
;
454 tdiv(double value
, struct timeval tv
)
456 return value
/ ((double)tv
.tv_sec
+ ((double)tv
.tv_usec
/ 1000000.0));
459 #define HOURS(sec) ((sec) / (60 * 60))
460 #define MINUTES(sec) (((sec) % (60 * 60)) / 60)
461 #define SECONDS(sec) ((sec) % 60)
470 double usec
= (double)tv
->tv_usec
/ 1000000.0;
472 if (format
& TERSE_FIXED_TIME
) {
473 if (!HOURS(tv
->tv_sec
)) {
474 snprintf(ts
, size
, "%u:%02u.%02u",
475 (unsigned int) MINUTES(tv
->tv_sec
),
476 (unsigned int) SECONDS(tv
->tv_sec
),
477 (unsigned int) usec
* 100);
480 format
|= VERBOSE_FIXED_TIME
; /* fallback if hours needed */
483 if ((format
& VERBOSE_FIXED_TIME
) || tv
->tv_sec
) {
484 snprintf(ts
, size
, "%u:%02u:%02u.%02u",
485 (unsigned int) HOURS(tv
->tv_sec
),
486 (unsigned int) MINUTES(tv
->tv_sec
),
487 (unsigned int) SECONDS(tv
->tv_sec
),
488 (unsigned int) usec
* 100);
490 snprintf(ts
, size
, "0.%04u sec", (unsigned int) usec
* 10000);
495 * Convert from a pair of arbitrary user strings into a timespec.
499 timespec_from_string(
502 struct timespec
* ts
)
505 if (!secs
|| !nsecs
|| !ts
)
507 ts
->tv_sec
= strtoull(secs
, &p
, 0);
510 ts
->tv_nsec
= strtoull(nsecs
, &p
, 0);
517 * Convert from arbitrary user strings into a numeric ID.
518 * If it's all numeric, we convert that inplace, else we do
519 * the name lookup, and return the found identifier.
527 unsigned long prid_long
;
531 * Allow either a full numeric or a valid projectname, even
532 * if it starts with a digit.
534 prid_long
= strtoul(project
, &sp
, 10);
535 if (*project
!= '\0' && *sp
== '\0') {
536 if ((prid_long
== ULONG_MAX
&& errno
== ERANGE
)
537 || (prid_long
> (prid_t
)-1))
539 return (prid_t
)prid_long
;
541 prj
= getprnam(project
);
552 unsigned long uid_long
;
555 uid_long
= strtoul(user
, &sp
, 10);
556 if (sp
!= user
&& *sp
== '\0') {
557 if ((uid_long
== ULONG_MAX
&& errno
== ERANGE
)
558 || (uid_long
> (uid_t
)-1))
560 return (uid_t
)uid_long
;
562 pwd
= getpwnam(user
);
573 unsigned long gid_long
;
576 gid_long
= strtoul(group
, &sp
, 10);
577 if (sp
!= group
&& *sp
== '\0') {
578 if ((gid_long
== ULONG_MAX
&& errno
== ERANGE
)
579 || (gid_long
> (gid_t
)-1))
581 return (gid_t
)gid_long
;
583 grp
= getgrnam(group
);
594 for (i
= 0; i
< strlen(str
); i
++) {
595 if (!isdigit(str
[i
]))
601 #define HAVE_FTW_H 1 /* TODO: configure me */
607 int (*fn
)(const char *, const struct stat
*, int, struct FTW
*),
611 fprintf(stderr
, "%s: not implemented, no recursion available\n",