78 |
|
|
79 |
message = va_arg (args, char *); |
message = va_arg (args, char *); |
80 |
/* The following is incredibly stupid and broken, but I don't know how to |
/* The following is incredibly stupid and broken, but I don't know how to |
81 |
do it better in C. */ |
do it better in C. */ |
82 |
if (num_arg > 0) |
if (num_arg > 0) |
83 |
{ |
{ |
84 |
char *message2 = va_arg (args, char *); |
char *message2 = va_arg (args, char *); |
85 |
asprintf (&buf, "%s: %s %s\n", program_name, message, message2); |
asprintf (&buf, "%s: %s %s\n", program_name, message, message2); |
86 |
} |
} |
87 |
else |
else |
88 |
{ |
{ |
89 |
asprintf (&buf, "%s: %s\n", program_name, message); |
asprintf (&buf, "%s: %s\n", program_name, message); |
90 |
} |
} |
91 |
|
|
92 |
switch (log_method) |
switch (log_method) |
93 |
{ |
{ |
94 |
#ifdef HAVE_SYSLOG_H |
#ifdef HAVE_SYSLOG_H |
95 |
case SYSLOG: |
case SYSLOG: |
96 |
syslog (severity, "%s", buf); |
syslog (severity, "%s", buf); |
97 |
break; |
break; |
98 |
#endif |
#endif |
99 |
case MAIL: |
case MAIL: |
100 |
/* This is currently not used, because it could send a lot of mails |
/* This is currently not used, because it could send a lot of mails |
101 |
to someone. */ |
to someone. */ |
102 |
program_error (__FILE__, __LINE__); |
program_error (__FILE__, __LINE__); |
103 |
break; |
break; |
104 |
case LOGFILE: |
case LOGFILE: |
105 |
if (gnats_logfile != (FILE *)NULL) |
if (gnats_logfile != (FILE *)NULL) |
106 |
{ |
{ |
107 |
fprintf (gnats_logfile, "%s", buf); |
fprintf (gnats_logfile, "%s", buf); |
108 |
break; |
break; |
109 |
} |
} |
110 |
/* No log file, log to stderr. */ |
/* No log file, log to stderr. */ |
111 |
case STDERR: |
case STDERR: |
112 |
fprintf (stderr, "%s", buf); |
fprintf (stderr, "%s", buf); |
113 |
break; |
break; |
114 |
case NOLOG: |
case NOLOG: |
115 |
/* Do nothing. */ |
/* Do nothing. */ |
116 |
break; |
break; |
117 |
default: |
default: |
118 |
program_error (__FILE__, __LINE__); |
program_error (__FILE__, __LINE__); |
119 |
} |
} |
120 |
|
|
121 |
free (buf); |
free (buf); |
122 |
} |
} |
136 |
/* A log file explicitly requested. Let's try to open it. */ |
/* A log file explicitly requested. Let's try to open it. */ |
137 |
gnats_logfile = fopen (logfile, "at"); |
gnats_logfile = fopen (logfile, "at"); |
138 |
if (gnats_logfile != NULL) |
if (gnats_logfile != NULL) |
139 |
{ |
{ |
140 |
log_method = LOGFILE; |
log_method = LOGFILE; |
141 |
return; |
return; |
142 |
} |
} |
143 |
} |
} |
144 |
|
|
145 |
if (isatty (fileno (stderr))) |
if (isatty (fileno (stderr))) |
186 |
free (mailAgentPath); |
free (mailAgentPath); |
187 |
|
|
188 |
if (debugMode (database)) |
if (debugMode (database)) |
189 |
{ |
{ |
190 |
fprintf (fp, "From: %s (GNATS Management)\n", |
fprintf (fp, "From: %s (GNATS Management)\n", |
191 |
gnatsAdminMailAddr (database)); |
gnatsAdminMailAddr (database)); |
192 |
fprintf (fp, "To: %s\n", gnatsAdminMailAddr (database)); |
fprintf (fp, "To: %s\n", gnatsAdminMailAddr (database)); |
193 |
fprintf (fp, "Subject: mail output from %s\n", program_name); |
fprintf (fp, "Subject: mail output from %s\n", program_name); |
194 |
fprintf (fp, "\n\n"); |
fprintf (fp, "\n\n"); |
195 |
} |
} |
196 |
} |
} |
197 |
|
|
198 |
return fp; |
return fp; |
228 |
If any error occurs, NULL is returned and `err' is set appropriately. */ |
If any error occurs, NULL is returned and `err' is set appropriately. */ |
229 |
DatabaseInfo |
DatabaseInfo |
230 |
init_gnats (const char *program_name, const char *database_name, |
init_gnats (const char *program_name, const char *database_name, |
231 |
ErrorDesc *err) |
ErrorDesc *err) |
232 |
{ |
{ |
233 |
init_logging (NULL); |
init_logging (NULL); |
234 |
re_set_syntax ((RE_SYNTAX_POSIX_EXTENDED | RE_BK_PLUS_QM) & ~RE_DOT_NEWLINE); |
re_set_syntax ((RE_SYNTAX_POSIX_EXTENDED | RE_BK_PLUS_QM) & ~RE_DOT_NEWLINE); |
303 |
for (p = string; *p != '\0'; p++) |
for (p = string; *p != '\0'; p++) |
304 |
{ |
{ |
305 |
if (*p == '"') |
if (*p == '"') |
306 |
{ |
{ |
307 |
len++; |
len++; |
308 |
} |
} |
309 |
} |
} |
310 |
|
|
311 |
res = xmalloc (len + 1); |
res = xmalloc (len + 1); |
318 |
for (p = string; *p != '\0'; p++) |
for (p = string; *p != '\0'; p++) |
319 |
{ |
{ |
320 |
if (*p == '"') |
if (*p == '"') |
321 |
{ |
{ |
322 |
*(rp++) = '\\'; |
*(rp++) = '\\'; |
323 |
} |
} |
324 |
*(rp++) = *p; |
*(rp++) = *p; |
325 |
} |
} |
326 |
return res; |
return res; |
347 |
char *res = xmalloc (max_len>0 ? max_len+1 : default_len); |
char *res = xmalloc (max_len>0 ? max_len+1 : default_len); |
348 |
|
|
349 |
while (fgets (res+len, (max_len>0 ? max_len : default_len), input) |
while (fgets (res+len, (max_len>0 ? max_len : default_len), input) |
350 |
!= NULL) |
!= NULL) |
351 |
{ |
{ |
352 |
size_t slen = strlen (res + len); |
size_t slen = strlen (res + len); |
353 |
len += slen; |
len += slen; |
354 |
if (res[len - 1] == '\n') |
if (res[len - 1] == '\n') |
355 |
break; |
break; |
356 |
|
|
357 |
if (max_len > 0) |
if (max_len > 0) |
358 |
{ |
{ |
359 |
max_len -= slen; |
max_len -= slen; |
360 |
if (max_len == 0) |
if (max_len == 0) |
361 |
break; |
break; |
362 |
} |
} |
363 |
else |
else |
364 |
{ |
{ |
365 |
res = xrealloc (res, len + default_len); |
res = xrealloc (res, len + default_len); |
366 |
} |
} |
367 |
} |
} |
368 |
|
|
369 |
if (len == 0) |
if (len == 0) |
409 |
(sdcsvax!rmr or rmr@@uscd). If you want it, it's yours. |
(sdcsvax!rmr or rmr@@uscd). If you want it, it's yours. |
410 |
|
|
411 |
Severely hacked over by John Gilmore to make a 4.2BSD compatible |
Severely hacked over by John Gilmore to make a 4.2BSD compatible |
412 |
subroutine. 11Mar86; hoptoad!gnu |
subroutine. 11Mar86; hoptoad!gnu |
413 |
|
|
414 |
Modified by rmtodd@@uokmax 6-28-87 -- when making an already existing dir, |
Modified by rmtodd@@uokmax 6-28-87 -- when making an already existing dir, |
415 |
subroutine didn't return EEXIST. It does now. */ |
subroutine didn't return EEXIST. It does now. */ |
424 |
|
|
425 |
if (stat (dpath, &statbuf) == 0) |
if (stat (dpath, &statbuf) == 0) |
426 |
{ |
{ |
427 |
errno = EEXIST; /* stat worked, so it already exists. */ |
errno = EEXIST; /* stat worked, so it already exists. */ |
428 |
return -1; |
return -1; |
429 |
} |
} |
430 |
|
|
435 |
cpid = fork (); |
cpid = fork (); |
436 |
switch (cpid) |
switch (cpid) |
437 |
{ |
{ |
438 |
case -1: /* Cannot fork. */ |
case -1: /* Cannot fork. */ |
439 |
return -1; /* errno is set already. */ |
return -1; /* errno is set already. */ |
440 |
|
|
441 |
case 0: /* Child process. */ |
case 0: /* Child process. */ |
442 |
/* Cheap hack to set mode of new directory. Since this child |
/* Cheap hack to set mode of new directory. Since this child |
443 |
process is going away anyway, we zap its umask. |
process is going away anyway, we zap its umask. |
444 |
This won't suffice to set SUID, SGID, etc. on this |
This won't suffice to set SUID, SGID, etc. on this |
445 |
directory, so the parent process calls chmod afterward. */ |
directory, so the parent process calls chmod afterward. */ |
446 |
status = umask (0); /* Get current umask. */ |
status = umask (0); /* Get current umask. */ |
447 |
umask (status | (0777 & ~dmode)); /* Set for mkdir. */ |
umask (status | (0777 & ~dmode)); /* Set for mkdir. */ |
448 |
execl ("/bin/mkdir", "mkdir", dpath, (char *) 0); |
execl ("/bin/mkdir", "mkdir", dpath, (char *) 0); |
449 |
_exit (1); |
_exit (1); |
450 |
|
|
451 |
default: /* Parent process. */ |
default: /* Parent process. */ |
452 |
while (wait (&status) != cpid) /* Wait for kid to finish. */ |
while (wait (&status) != cpid) /* Wait for kid to finish. */ |
453 |
/* Do nothing. */ ; |
/* Do nothing. */ ; |
454 |
|
|
455 |
if (status & 0xFFFF) |
if (status & 0xFFFF) |
456 |
{ |
{ |
457 |
errno = EIO; /* /bin/mkdir failed. */ |
errno = EIO; /* /bin/mkdir failed. */ |
458 |
return -1; |
return -1; |
459 |
} |
} |
460 |
return chmod (dpath, dmode); |
return chmod (dpath, dmode); |
461 |
} |
} |
462 |
} |
} |
481 |
for (i = 0; i < NUMBER_OF_TRIALS && fd < 0; i++) |
for (i = 0; i < NUMBER_OF_TRIALS && fd < 0; i++) |
482 |
{ |
{ |
483 |
#ifdef HAVE_MKTEMP |
#ifdef HAVE_MKTEMP |
484 |
mktemp (template); |
mktemp (template); |
485 |
#else |
#else |
486 |
mkstemps (template, 0); |
mkstemps (template, 0); |
487 |
#endif |
#endif |
488 |
fd = open (template, O_RDWR | O_CREAT | O_EXCL, mode); |
fd = open (template, O_RDWR | O_CREAT | O_EXCL, mode); |
489 |
} |
} |
490 |
} |
} |
491 |
#endif |
#endif |
535 |
|
|
536 |
/* mktime() not portably reliable; calculate minutes offset ourselves */ |
/* mktime() not portably reliable; calculate minutes offset ourselves */ |
537 |
offset = ((local.tm_hour - gmt.tm_hour) * 60 + |
offset = ((local.tm_hour - gmt.tm_hour) * 60 + |
538 |
(local.tm_min - gmt.tm_min)); |
(local.tm_min - gmt.tm_min)); |
539 |
|
|
540 |
/* Adjust backwards/forwards if the day is different */ |
/* Adjust backwards/forwards if the day is different */ |
541 |
if (local.tm_year < gmt.tm_year) offset -= MINUTES_PER_DAY; |
if (local.tm_year < gmt.tm_year) offset -= MINUTES_PER_DAY; |
550 |
by libc. */ |
by libc. */ |
551 |
size_t |
size_t |
552 |
gnats_strftime (char *s, size_t size, const char *template, |
gnats_strftime (char *s, size_t size, const char *template, |
553 |
const struct tm *brokentime) |
const struct tm *brokentime) |
554 |
{ |
{ |
555 |
static short have_strftime_with_z = -1; |
static short have_strftime_with_z = -1; |
556 |
if (have_strftime_with_z < 0) |
if (have_strftime_with_z < 0) |
563 |
** return from get_curr_date() cannot be parsed by get_date(). |
** return from get_curr_date() cannot be parsed by get_date(). |
564 |
*/ |
*/ |
565 |
have_strftime_with_z = ((int)buf[0] == '+' || (int)buf[0] == '-') && |
have_strftime_with_z = ((int)buf[0] == '+' || (int)buf[0] == '-') && |
566 |
isdigit ((int)(buf[1])); |
isdigit ((int)(buf[1])); |
567 |
} |
} |
568 |
|
|
569 |
if (have_strftime_with_z) |
if (have_strftime_with_z) |
585 |
* As we are going to replace each "%z" by "+hhmm" (sign, hours, |
* As we are going to replace each "%z" by "+hhmm" (sign, hours, |
586 |
* minutes), this is 3 extra chars for each %z. */ |
* minutes), this is 3 extra chars for each %z. */ |
587 |
while (*in) |
while (*in) |
588 |
{ |
{ |
589 |
if (*in == '%' && *(in+1) == 'z') |
if (*in == '%' && *(in+1) == 'z') |
590 |
{ |
{ |
591 |
in += 2; |
in += 2; |
592 |
padding += 3; /* 3 extra chars for each %z */ |
padding += 3; /* 3 extra chars for each %z */ |
593 |
} |
} |
594 |
else |
else |
595 |
{ |
{ |
596 |
in++; |
in++; |
597 |
} |
} |
598 |
} |
} |
599 |
|
|
600 |
/* Now allocate enough space. */ |
/* Now allocate enough space. */ |
601 |
fixed_template = (char*)xmalloc (strlen(template)+padding+1); |
fixed_template = (char*)xmalloc (strlen(template)+padding+1); |
603 |
out = fixed_template; |
out = fixed_template; |
604 |
|
|
605 |
while (*in != '\0') |
while (*in != '\0') |
606 |
{ |
{ |
607 |
char c = *in++; |
char c = *in++; |
608 |
if (c != '%') |
if (c != '%') |
609 |
{ |
{ |
610 |
*out++ = c; |
*out++ = c; |
611 |
} |
} |
612 |
else if (*in != 'z') |
else if (*in != 'z') |
613 |
{ |
{ |
614 |
*out++ = c; /* the '%' */ |
*out++ = c; /* the '%' */ |
615 |
*out++ = *in++; |
*out++ = *in++; |
616 |
} |
} |
617 |
else |
else |
618 |
{ |
{ |
619 |
int offset = minutes_gmt_offset (brokentime); |
int offset = minutes_gmt_offset (brokentime); |
620 |
char offset_buf[6]; |
char offset_buf[6]; |
621 |
char sign = '+'; |
char sign = '+'; |
622 |
unsigned int i, hours, minutes; |
unsigned int i, hours, minutes; |
623 |
|
|
624 |
if (offset < 0) |
if (offset < 0) |
625 |
{ |
{ |
626 |
sign = '-'; |
sign = '-'; |
627 |
offset = -offset; |
offset = -offset; |
628 |
} |
} |
629 |
hours = offset / 60; |
hours = offset / 60; |
630 |
minutes = offset % 60; |
minutes = offset % 60; |
631 |
sprintf (offset_buf, "%c%02d%02d", sign, hours, minutes); |
sprintf (offset_buf, "%c%02d%02d", sign, hours, minutes); |
632 |
for (i = 0; i < strlen (offset_buf); i++) |
for (i = 0; i < strlen (offset_buf); i++) |
633 |
*out++ = offset_buf[i]; |
*out++ = offset_buf[i]; |
634 |
in++; /* skip over 'z' */ |
in++; /* skip over 'z' */ |
635 |
} |
} |
636 |
} |
} |
637 |
*out = '\0'; |
*out = '\0'; |
638 |
|
|
639 |
result = strftime (s, size, fixed_template, &btime); |
result = strftime (s, size, fixed_template, &btime); |
676 |
unsigned int i; |
unsigned int i; |
677 |
for (i = 0; i < strlen (string); i++) |
for (i = 0; i < strlen (string); i++) |
678 |
if (! isspace ((int)(unsigned char)(string[i]))) |
if (! isspace ((int)(unsigned char)(string[i]))) |
679 |
return FALSE; |
return FALSE; |
680 |
return TRUE; |
return TRUE; |
681 |
} |
} |
682 |
} |
} |
683 |
|
|
684 |
|
#ifndef HAVE_UNSETENV |
685 |
|
#define __environ environ |
686 |
|
extern char **environ; |
687 |
|
|
688 |
|
void |
689 |
|
unsetenv (name) |
690 |
|
const char *name; |
691 |
|
{ |
692 |
|
const size_t len = strlen (name); |
693 |
|
char **ep; |
694 |
|
|
695 |
|
for (ep = __environ; *ep; ++ep) |
696 |
|
if (!strncmp (*ep, name, len) && (*ep)[len] == '=') |
697 |
|
{ |
698 |
|
/* Found it. Remove this pointer by moving later ones back. */ |
699 |
|
char **dp = ep; |
700 |
|
do |
701 |
|
dp[0] = dp[1]; |
702 |
|
while (*dp++); |
703 |
|
/* Continue the loop in case NAME appears again. */ |
704 |
|
} |
705 |
|
|
706 |
|
} |
707 |
|
#endif /* !HAVE_UNSETENV */ |