2013573ffc2018329c55c63b51022f44470a2e1c
[platform/upstream/coreutils.git] / src / sleep.c
1 /* sleep - delay for a specified amount of time.
2    Copyright (C) 84, 1991-1997, 1999-2003 Free Software Foundation, Inc.
3
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; either version 2, or (at your option)
7    any later version.
8
9    This program is distributed in the hope that it will 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.
13
14    You should have received a copy of the GNU General Public License
15    along with this program; if not, write to the Free Software Foundation,
16    Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
17
18 #include <config.h>
19 #include <stdio.h>
20 #include <assert.h>
21 #include <sys/types.h>
22 #include <getopt.h>
23
24 #include "system.h"
25 #include "error.h"
26 #include "long-options.h"
27 #include "xnanosleep.h"
28 #include "xstrtod.h"
29
30 /* The official name of this program (e.g., no `g' prefix).  */
31 #define PROGRAM_NAME "sleep"
32
33 #define WRITTEN_BY _("Written by Jim Meyering and Paul Eggert.")
34
35 /* The name by which this program was run. */
36 char *program_name;
37
38 static struct option const long_options[] =
39 {
40   {0, 0, 0, 0}
41 };
42
43 void
44 usage (int status)
45 {
46   if (status != 0)
47     fprintf (stderr, _("Try `%s --help' for more information.\n"),
48              program_name);
49   else
50     {
51       printf (_("\
52 Usage: %s NUMBER[SUFFIX]...\n\
53   or:  %s OPTION\n\
54 Pause for NUMBER seconds.  SUFFIX may be `s' for seconds (the default),\n\
55 `m' for minutes, `h' for hours or `d' for days.  Unlike most implementations\n\
56 that require NUMBER be an integer, here NUMBER may be an arbitrary floating\n\
57 point number.\n\
58 \n\
59 "),
60               program_name, program_name);
61       fputs (HELP_OPTION_DESCRIPTION, stdout);
62       fputs (VERSION_OPTION_DESCRIPTION, stdout);
63       printf (_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT);
64     }
65   exit (status);
66 }
67
68 /* Given a floating point value *X, and a suffix character, SUFFIX_CHAR,
69    scale *X by the multiplier implied by SUFFIX_CHAR.  SUFFIX_CHAR may
70    be the NUL byte or `s' to denote seconds, `m' for minutes, `h' for
71    hours, or `d' for days.  If SUFFIX_CHAR is invalid, don't modify *X
72    and return nonzero.  Otherwise return zero.  */
73
74 static int
75 apply_suffix (double *x, char suffix_char)
76 {
77   unsigned int multiplier;
78
79   switch (suffix_char)
80     {
81     case 0:
82     case 's':
83       multiplier = 1;
84       break;
85     case 'm':
86       multiplier = 60;
87       break;
88     case 'h':
89       multiplier = 60 * 60;
90       break;
91     case 'd':
92       multiplier = 60 * 60 * 24;
93       break;
94     default:
95       multiplier = 0;
96     }
97
98   if (multiplier == 0)
99     return 1;
100
101   *x *= multiplier;
102
103   return 0;
104 }
105
106 int
107 main (int argc, char **argv)
108 {
109   int i;
110   double seconds = 0.0;
111   int c;
112   int fail = 0;
113
114   initialize_main (&argc, &argv);
115   program_name = argv[0];
116   setlocale (LC_ALL, "");
117   bindtextdomain (PACKAGE, LOCALEDIR);
118   textdomain (PACKAGE);
119
120   atexit (close_stdout);
121
122   parse_long_options (argc, argv, PROGRAM_NAME, GNU_PACKAGE, VERSION,
123                       WRITTEN_BY, usage);
124
125   while ((c = getopt_long (argc, argv, "", long_options, NULL)) != -1)
126     {
127       switch (c)
128         {
129         case 0:
130           break;
131
132         default:
133           usage (EXIT_FAILURE);
134         }
135     }
136
137   if (argc == 1)
138     {
139       error (0, 0, _("too few arguments"));
140       usage (EXIT_FAILURE);
141     }
142
143   for (i = optind; i < argc; i++)
144     {
145       double s;
146       const char *p;
147       if (xstrtod (argv[i], &p, &s)
148           /* Nonnegative interval.  */
149           || ! (0 <= s)
150           /* No extra chars after the number and an optional s,m,h,d char.  */
151           || (*p && *(p+1))
152           /* Check any suffix char and update S based on the suffix.  */
153           || apply_suffix (&s, *p))
154         {
155           error (0, 0, _("invalid time interval `%s'"), argv[i]);
156           fail = 1;
157         }
158
159       seconds += s;
160     }
161
162   if (fail)
163     usage (EXIT_FAILURE);
164
165   if (xnanosleep (seconds))
166     error (EXIT_FAILURE, errno, _("cannot read realtime clock"));
167
168   exit (EXIT_SUCCESS);
169 }