Storing the length of all the overloading names saves a strlen() in a
[p5sagit/p5-mst-13.2.git] / vos / vos.c
1 /* Beginning of modification history */
2 /* Written 02-01-02 by Nick Ing-Simmons (nick@ing-simmons.net) */
3 /* Modified 02-03-27 by Paul Green (Paul.Green@stratus.com) to
4      add socketpair() dummy. */
5 /* Modified 02-04-24 by Paul Green (Paul.Green@stratus.com) to
6      have pow(0,0) return 1, avoiding c-1471. */
7 /* Modified 06-09-25 by Paul Green (Paul.Green@stratus.com) to
8      add syslog entries. */
9 /* End of modification history */
10
11 #include <errno.h>
12 #include <fcntl.h>
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <sys/types.h>
17 #include <unistd.h>
18
19 #include "vos/syslog.h"
20
21 /* VOS doesn't supply a truncate function, so we build one up
22    from the available POSIX functions.  */
23
24 int
25 truncate(const char *path, off_t len)
26 {
27  int fd = open(path,O_WRONLY);
28  int code = -1;
29  if (fd >= 0) {
30    code = ftruncate(fd,len);
31    close(fd); 
32  }
33  return code;
34 }
35
36 /* VOS doesn't implement AF_UNIX (AF_LOCAL) style sockets, and
37    the perl emulation of them hangs on VOS (due to stcp-1257),
38    so we supply this version that always fails.  */
39
40 int
41 socketpair (int family, int type, int protocol, int fd[2]) {
42  fd[0] = 0;
43  fd[1] = 0;
44  errno = ENOSYS;
45  return -1;
46 }
47
48 /* Supply a private version of the power function that returns 1
49    for x**0.  This avoids c-1471.  Abigail's Japh tests depend
50    on this fix.  We leave all the other cases to the VOS C
51    runtime.  */
52
53 double s_crt_pow(double *x, double *y);
54
55 double pow(x,y)
56 double x, y;
57 {
58      if (y == 0e0)                 /* c-1471 */
59      {
60           errno = EDOM;
61           return (1e0);
62      }
63
64      return(s_crt_pow(&x,&y));
65 }
66
67 /* entries */
68
69 extern void s$log_system_message (
70 /*             char_varying (256)  *message_text, 
71                char_varying (66)   *module_name, 
72                short int           *error_code */ );
73
74 /* constants */
75
76 #define    ALL_PRIORITIES 255  /* 8 priorities, all enabled */
77 #define    BUFFER_LEN 256
78 #define    IDENT_LEN 64
79 #define    MSG_LEN 256
80 #define    PATH_LEN 257
81
82 /* static */
83
84 int  vos_syslog_facility = LOG_USER>>3;
85 int  vos_syslog_fd = -1;
86 int  vos_syslog_logopt = 0;
87 char vos_syslog_ident[IDENT_LEN] = "";
88 int  vos_syslog_ident_len = 0;
89 int  vos_syslog_mask = ALL_PRIORITIES;
90 char vos_syslog_path[PATH_LEN] = "/Stratus/Green/build_farm/build_farm.syslog";
91
92 char vos_syslog_facility_name [17][10] = {
93      "[KERN] ",    /* LOG_KERN */
94      "[USER] ",    /* LOG_USER */
95      "[MAIL] ",    /* LOG_MAIL */
96      "[NEWS] ",    /* LOG_NEWS */
97      "[UUCP] ",    /* LOG_UUCP */
98      "[DAEMON] ",  /* LOG_DAEMON */
99      "[AUTH] ",    /* LOG_AUTH */
100      "[CRON] ",    /* LOG_CRON */
101      "[LPR] ",     /* LOG_LPR */
102      "[LOCAL0] ",  /* LOG_LOCAL0 */
103      "[LOCAL1] ",  /* LOG_LOCAL1 */
104      "[LOCAL2] ",  /* LOG_LOCAL2 */
105      "[LOCAL3] ",  /* LOG_LOCAL3 */
106      "[LOCAL4] ",  /* LOG_LOCAL4 */
107      "[LOCAL5] ",  /* LOG_LOCAL5 */
108      "[LOCAL6] ",  /* LOG_LOCAL6 */
109      "[LOCAL7] "}; /* LOG_LOCAL7 */
110
111 /* syslog functions */
112
113 static void open_syslog (void)
114 {
115      if (vos_syslog_fd >= 0)
116           return;
117
118      vos_syslog_fd = open (vos_syslog_path, O_RDWR | O_CREAT | O_APPEND, 0777);
119      if (vos_syslog_fd < 0)
120           fprintf (stderr, "Unable to open %s (errno=%d, os_errno=%d)\n",
121                vos_syslog_path, errno, os_errno);
122 }
123
124 void closelog (void)
125 {
126      if (vos_syslog_fd >= 0)
127           close (vos_syslog_fd);
128
129      vos_syslog_facility = LOG_USER>>3;
130      vos_syslog_fd = -1;
131      vos_syslog_logopt = 0;
132      vos_syslog_ident[0] = '\0';
133      vos_syslog_ident_len = 0;
134      vos_syslog_mask = ALL_PRIORITIES;
135      return;
136 }
137
138 void openlog (const char *ident, int logopt, int facility)
139 {
140 int  n;
141
142      if (ident != NULL)
143      {
144           strncpy (vos_syslog_ident, ident, sizeof (vos_syslog_ident));
145           n = IDENT_LEN -
146                strnlen (vos_syslog_ident, sizeof (vos_syslog_ident));
147           strncat (vos_syslog_ident, ": ", n);
148           vos_syslog_ident_len = strnlen (vos_syslog_ident,
149                sizeof (vos_syslog_ident));
150      }
151
152      vos_syslog_logopt = logopt;
153      vos_syslog_facility = facility>>3;
154
155      if ((logopt & LOG_NDELAY) == LOG_NDELAY)
156           open_syslog ();
157
158      return;
159 }
160
161 int setlogmask (int maskpri)
162 {
163 int  old_mask;
164
165      old_mask = vos_syslog_mask;
166
167      if (maskpri > 0)
168           vos_syslog_mask = maskpri;
169
170      return old_mask;
171 }
172
173 void syslog (int priority, const char *format, ...)
174 {
175 va_list             ap;
176 int                 bare_facility;
177 int                 bare_priority;
178 int                 buffer_n;
179 char                buffer[BUFFER_LEN];
180 short int           code;
181 char_varying(MSG_LEN) message;
182 char_varying(66)    module_name;
183 int                 n;
184 int                 pid_n;
185 char                pid_string[32];
186 int                 r;
187 int                 user_n;
188 char                user_string[256];
189
190      /* Calculate priority and facility value.  */
191
192      bare_priority = priority & 3;
193      bare_facility = priority >> 3;
194
195      /* If the priority is not set in the mask, do not log the
196         message.  */
197
198      if ((vos_syslog_mask & LOG_MASK(bare_priority)) == 0)
199           return;
200
201      /* Output facility name.  */
202
203      if (bare_facility == 0)
204           bare_facility = vos_syslog_facility;
205
206      strcpy (buffer, vos_syslog_facility_name[bare_facility]);
207
208      /* Output priority value. */
209
210      /* TBD */
211
212      /* Output identity string. */
213
214      buffer_n = BUFFER_LEN - strlen (buffer);
215      strncat (buffer, vos_syslog_ident, buffer_n);
216
217      /* Output process ID.  */
218
219      if ((vos_syslog_logopt & LOG_PID) == LOG_PID)
220      {
221           pid_n = snprintf (pid_string, sizeof (pid_string),
222                "PID=0x%x ", getpid ());
223           if (pid_n)
224           {
225                buffer_n = BUFFER_LEN - strlen (buffer);
226                strncat (buffer, pid_string, buffer_n);
227           }
228      }
229
230      /* Output formatted message.  */
231
232      va_start (ap, format);
233      user_n = vsnprintf (user_string, sizeof (user_string), format, ap);
234      va_end (ap);
235
236      /* Ensure string ends in a newline.  */
237
238      if (user_n > 0)
239      {
240           if (user_n >= sizeof (user_string))
241                user_n = sizeof (user_string) - 1;
242
243           /* arrays are zero-origin.... */
244
245           if (user_string [user_n-1] != '\n')
246           {
247                user_string [user_n-1] = '\n';
248                user_string [user_n++] = '\0';
249           }
250      }        
251      else
252      {
253           user_string [0] = '\n';
254           user_string [1] = '\0';
255           user_n = 1;
256      }
257
258      buffer_n = BUFFER_LEN - strnlen (buffer, sizeof (buffer));
259      strncat (buffer, user_string, buffer_n);
260
261      /* If the log is not open, try to open it now.  */
262
263      if (vos_syslog_fd < 0)
264           open_syslog ();
265
266      /* Try to write the message to the syslog file.  */
267
268      if (vos_syslog_fd < 0)
269           r = -1;
270      else
271      {
272           buffer_n = strnlen (buffer, sizeof (buffer));
273           r = write (vos_syslog_fd, buffer, buffer_n);
274      }
275
276      /* If we were unable to write to the log and if LOG_CONS is
277         set, send it to the console.  */
278
279      if (r < 0)
280           if ((vos_syslog_logopt & LOG_CONS) == LOG_CONS)
281           {
282                strcpy_vstr_nstr (&message, "syslog: ");
283                n = MSG_LEN - sizeof ("syslog: ");
284                strncat_vstr_nstr (&message, buffer, n);
285                strcpy_vstr_nstr (&module_name, "");
286                s$log_system_message (&message, &module_name, &code);
287           }
288
289      return;
290 }