Implement CLOCK_MONOTONIC using getnanouptime(), which in DragonFly is
[dragonfly.git] / contrib / cvs-1.12.9 / src / error.c
1 /* error.c -- error handler for noninteractive utilities
2    Copyright (C) 1990-1992 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 /* David MacKenzie */
15 /* Brian Berliner added support for CVS */
16
17 #include "cvs.h"
18
19 /* If non-zero, error will use the CVS protocol to stdout to report error
20    messages.  This will only be set in the CVS server parent process;
21    most other code is run via do_cvs_command, which forks off a child
22    process and packages up its stderr in the protocol.  */
23 int error_use_protocol; 
24
25 #ifndef strerror
26 extern char *strerror (int);
27 #endif
28
29
30
31 /* Print the program name and error message MESSAGE, which is a printf-style
32    format string with optional args.  This is a very limited printf subset:
33    %s, %d, %c, %x and %% only (without anything between the % and the s,
34    d, &c).  Callers who want something fancier can use sprintf.
35
36    If ERRNUM is nonzero, print its corresponding system error message.
37    Exit with status EXIT_FAILURE if STATUS is nonzero.  If MESSAGE is "",
38    no need to print a message.
39
40    I think this is largely cleaned up to the point where it does the right
41    thing for the server, whether the normal server_active (child process)
42    case or the error_use_protocol (parent process) case.  The one exception
43    is that STATUS nonzero for error_use_protocol probably doesn't work yet;
44    in that case still need to use the pending_error machinery in server.c.
45
46    error() does not molest errno; some code (e.g. Entries_Open) depends
47    on being able to say something like:
48       error (0, 0, "foo");
49       error (0, errno, "bar");
50
51    */
52
53 /* VARARGS */
54 void
55 error (int status, int errnum, const char *message, ...)
56 {
57     int save_errno = errno;
58
59     if (message[0] != '\0')
60     {
61         va_list args;
62         const char *p;
63         char *q;
64         char *str;
65         int num;
66         long lnum;
67         unsigned int unum;
68         unsigned long ulnum;
69         int ch;
70         char buf[100];
71
72         cvs_outerr (program_name, 0);
73         if (cvs_cmd_name && *cvs_cmd_name)
74         {
75             cvs_outerr (" ", 1);
76             if (status != 0)
77                 cvs_outerr ("[", 1);
78             cvs_outerr (cvs_cmd_name, 0);
79             if (status != 0)
80                 cvs_outerr (" aborted]", 0);
81         }
82         cvs_outerr (": ", 2);
83
84         va_start( args, message );
85         p = message;
86         while ((q = strchr (p, '%')) != NULL)
87         {
88             static const char msg[] =
89                 "\ninternal error: bad % in error()\n";
90             if (q - p > 0)
91                 cvs_outerr (p, q - p);
92
93             switch (q[1])
94             {
95             case 's':
96                 str = va_arg (args, char *);
97                 cvs_outerr (str, strlen (str));
98                 break;
99             case 'd':
100                 num = va_arg (args, int);
101                 sprintf (buf, "%d", num);
102                 cvs_outerr (buf, strlen (buf));
103                 break;
104             case 'l':
105                 if (q[2] == 'd')
106                 {
107                     lnum = va_arg (args, long);
108                     sprintf (buf, "%ld", lnum);
109                 }
110                 else if (q[2] == 'u')
111                 {
112                     ulnum = va_arg (args, unsigned long);
113                     sprintf (buf, "%lu", ulnum);
114                 }
115                 else goto bad;
116                 cvs_outerr (buf, strlen (buf));
117                 q++;
118                 break;
119             case 'x':
120                 unum = va_arg (args, unsigned int);
121                 sprintf (buf, "%x", unum);
122                 cvs_outerr (buf, strlen (buf));
123                 break;
124             case 'c':
125                 ch = va_arg (args, int);
126                 buf[0] = ch;
127                 cvs_outerr (buf, 1);
128                 break;
129             case '%':
130                 cvs_outerr ("%", 1);
131                 break;
132             default:
133             bad:
134                 cvs_outerr (msg, sizeof (msg) - 1);
135                 /* Don't just keep going, because q + 1 might point to the
136                    terminating '\0'.  */
137                 goto out;
138             }
139             p = q + 2;
140         }
141         cvs_outerr (p, strlen (p));
142     out:
143         va_end (args);
144
145         if (errnum != 0)
146         {
147             cvs_outerr (": ", 2);
148             cvs_outerr (strerror (errnum), 0);
149         }
150         cvs_outerr ("\n", 1);
151     }
152
153     if (status)
154         exit (EXIT_FAILURE);
155     errno = save_errno;
156 }
157
158 /* Print the program name and error message MESSAGE, which is a printf-style
159    format string with optional args to the file specified by FP.
160    If ERRNUM is nonzero, print its corresponding system error message.
161    Exit with status EXIT_FAILURE if STATUS is nonzero.  */
162 /* VARARGS */
163 void
164 fperrmsg (FILE *fp, int status, int errnum, char *message, ...)
165 {
166     va_list args;
167
168     fprintf (fp, "%s: ", program_name);
169     va_start( args, message );
170     vfprintf (fp, message, args);
171     va_end (args);
172     if (errnum)
173         fprintf (fp, ": %s", strerror (errnum));
174     putc ('\n', fp);
175     fflush (fp);
176     if (status)
177         exit (EXIT_FAILURE);
178 }