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