Pristine Ack-5.5
[Ack-5.5.git] / util / int / io.c
1 /*
2         In and output, error messages, etc.
3 */
4
5 /* $Id: io.c,v 2.5 1995/08/17 14:30:55 ceriel Exp $ */
6
7 #include        <stdio.h>
8 #if __STDC__
9 #include        <stdarg.h>
10 extern fatal(char *, ...);
11 #else
12 #include        <varargs.h>
13 #endif
14
15 #include        "logging.h"
16 #include        "global.h"
17 #include        "mem.h"
18 #include        "linfil.h"
19
20 extern int running;                     /* from main.c */
21 extern char *prog_name;                 /* from main.c */
22 extern char *load_name;                 /* from init.c */
23
24 /********  The message file  ********/
25
26 extern char mess_file[64];              /* from main.c */
27 long mess_id;                           /* Id, to determine unique mess file */
28 FILE *mess_fp;                          /* Filepointer of message file */
29
30 PRIVATE do_fatal();
31
32 incr_mess_id()
33 {       /* for a new child */
34         mess_id++;
35 }
36
37 #ifdef  LOGGING
38 extern long inr;                        /* from log.c */
39 #endif  /* LOGGING */
40
41 /********  General file handling  ********/
42
43 PRIVATE int highestfd();
44
45 int fd_limit = 100;                     /* first non-available file descriptor */
46
47 FILE *fcreat_high(fn)
48         char *fn;
49 {
50         /*      Creates an unbuffered FILE with name  fn  on the highest
51                 possible file descriptor.
52         */
53         register int fd;
54         register FILE *fp;
55         
56         if ((fd = creat(fn, 0644)) == -1)
57                 return NULL;
58         fd = highestfd(fd);
59         if ((fp = fdopen(fd, "w")) == NULL)
60                 return NULL;
61         setbuf(fp, (char *) 0);         /* unbuffered! */
62         fd_limit = fd;
63         return fp;
64 }
65
66 PRIVATE int highestfd(fd)
67         int fd;
68 {
69         /*      Moves the (open) file descriptor  fd  to the highest available
70                 position and returns the new fd.  Does this without knowing
71                 how many fd-s are available.
72         */
73         register int newfd, higherfd;
74
75         /* try to get a better fd */
76         newfd = dup(fd);
77         if (newfd < 0) {
78                 return fd;
79         }
80         if (newfd > 99) {
81                 /* for systems with an unlimited supply of file descriptors */
82                 close(newfd);
83                 return fd;
84         }
85
86         /* occupying the new fd, try to do even better */
87         higherfd = highestfd(newfd);
88         close(fd);
89         return higherfd;                /* this is a deep one */
90 }
91
92 init_ofiles(firsttime)
93         int firsttime;
94 {
95         if (!firsttime) {
96                 fclose(mess_fp);        /* old message file */
97                 mess_fp = 0;
98                 sprintf(mess_file, "%s_%ld", mess_file, mess_id);
99         }
100
101         /* Create messagefile */
102         if ((mess_fp = fcreat_high(mess_file)) == NULL)
103                 fatal("Cannot create messagefile '%s'", mess_file);
104         init_wmsg();
105
106         mess_id = 1;                    /* ID of next child */
107
108 #ifdef  LOGGING
109         open_log(firsttime);
110 #endif  /* LOGGING */
111 }
112
113 #if __STDC__
114 /*VARARGS0*/
115 fatal(char *fmt, ...)
116 {
117         va_list ap;
118
119         fprintf(stderr, "%s: ", prog_name);
120
121         va_start(ap, fmt);
122         {
123                 do_fatal(stderr, fmt, ap);
124         }
125         va_end(ap);
126
127         if (mess_fp) {
128                 va_start(ap, fmt);
129                 {
130                         do_fatal(mess_fp, fmt, ap);
131                 }
132                 va_end(ap);
133         }
134
135         if (running)
136                 core_dump();
137         
138         close_down(1);
139 }
140 #else
141 /*VARARGS0*/
142 fatal(va_alist)
143         va_dcl
144 {
145         va_list ap;
146
147         fprintf(stderr, "%s: ", prog_name);
148
149         va_start(ap);
150         {
151                 register char *fmt = va_arg(ap, char *);
152                 do_fatal(stderr, fmt, ap);
153         }
154         va_end(ap);
155
156         if (mess_fp) {
157                 va_start(ap);
158                 {
159                         register char *fmt = va_arg(ap, char *);
160                         do_fatal(mess_fp, fmt, ap);
161                 }
162                 va_end(ap);
163         }
164
165         if (running)
166                 core_dump();
167         
168         close_down(1);
169 }
170 #endif
171
172 close_down(rc)
173         int rc;
174 {
175         /* all exits should go through here */
176         if (mess_fp) {
177                 fclose(mess_fp);
178                 mess_fp = 0;
179         }
180
181 #ifdef  LOGGING
182         close_log();
183 #endif  /* LOGGING */
184
185         exit(rc);
186 }
187
188 PRIVATE do_fatal(fp, fmt, ap)
189         FILE *fp;
190         char *fmt;
191         va_list ap;
192 {
193         fprintf(fp, "(Fatal error) ");
194         if (load_name)
195                 fprintf(fp, "%s: ", load_name);
196         vfprintf(fp, fmt, ap);
197         fputc('\n', fp);
198 }
199
200 #if __STDC__
201 /*VARARGS0*/
202 message(char *fmt, ...)
203 {
204         va_list ap;
205
206         fprintf(mess_fp, "(Message): ");
207
208         va_start(ap, fmt);
209         {
210                 vfprintf(mess_fp, fmt, ap);
211         }
212         va_end(ap);
213
214         fprintf(mess_fp, " at %s\n", position());
215 }
216 #else
217 /*VARARGS0*/
218 message(va_alist)
219         va_dcl
220 {
221         va_list ap;
222
223         fprintf(mess_fp, "(Message): ");
224
225         va_start(ap);
226         {
227                 register char *fmt = va_arg(ap, char *);
228                 vfprintf(mess_fp, fmt, ap);
229         }
230         va_end(ap);
231
232         fprintf(mess_fp, " at %s\n", position());
233 }
234 #endif
235
236 char *position()                        /* transient */
237 {
238         static char buff[300];
239         register char *fn = dt_fname(getFIL());
240         
241 #ifdef  LOGGING
242         sprintf(buff, "\"%s\", line %ld, INR = %ld", fn, getLIN(), inr);
243 #else   /* LOGGING */
244         sprintf(buff, "\"%s\", line %ld", fn, getLIN());
245 #endif  /* LOGGING */
246         return buff;
247 }
248
249 char *dt_fname(p)
250         ptr p;
251 {
252         return (p ? &data_loc(p) : "<unknown>");
253 }
254