aboutsummaryrefslogtreecommitdiffstats
path: root/FICS
diff options
context:
space:
mode:
Diffstat (limited to 'FICS')
-rw-r--r--FICS/adminproc.c8
-rw-r--r--FICS/command.c13
-rw-r--r--FICS/comproc.c34
-rw-r--r--FICS/gamedb.c37
-rw-r--r--FICS/playerdb.c95
-rw-r--r--FICS/ratings.c34
-rw-r--r--FICS/utils.c17
7 files changed, 180 insertions, 58 deletions
diff --git a/FICS/adminproc.c b/FICS/adminproc.c
index 04331a4..e670d44 100644
--- a/FICS/adminproc.c
+++ b/FICS/adminproc.c
@@ -19,6 +19,8 @@
#include <sys/param.h>
#include <err.h>
+#include <inttypes.h>
+#include <stdint.h>
#include "adminproc.h"
#include "command.h"
@@ -367,12 +369,12 @@ PUBLIC int
com_anews(int p, param_list param)
{
FILE *fp = NULL;
- char *junkp = NULL;
char count[10] = { '\0' };
char filename[MAX_FILENAME_SIZE] = { '\0' };
char junk[MAX_LINE_SIZE] = { '\0' };
+ char *junkp = NULL;
int found = 0;
- long int lval = 0;
+ int64_t lval = 0;
time_t crtime = 0;
msnprintf(filename, sizeof filename, "%s/newadminnews.index", news_dir);
@@ -382,7 +384,7 @@ com_anews(int p, param_list param)
return COM_OK;
}
-#define SCAN_JUNK "%ld %9s"
+#define SCAN_JUNK ("%" SCNd64 " " "%9s")
_Static_assert(9 < ARRAY_SIZE(count), "Array too small");
if (param[0].type == 0) {
diff --git a/FICS/command.c b/FICS/command.c
index 569c27a..301c305 100644
--- a/FICS/command.c
+++ b/FICS/command.c
@@ -36,6 +36,7 @@
Markus Uhlin 25/03/09 Fixed double free()
Markus Uhlin 25/03/11 Fixed memleak
Markus Uhlin 25/03/16 Fixed use of 32-bit 'time_t'
+ Markus Uhlin 25/07/28 Usage of 'int64_t'
*/
#include "stdinclude.h"
@@ -44,6 +45,8 @@
#include <sys/param.h>
#include <err.h>
+#include <inttypes.h>
+#include <stdint.h>
#include "command.h"
#include "command_list.h"
@@ -716,10 +719,10 @@ boot_out(int p, int p1)
PUBLIC void
rscan_news(FILE *fp, int p, time_t lc)
{
- char *junkp = NULL;
char count[10] = { '\0' };
char junk[MAX_LINE_SIZE] = { '\0' };
- long int lval = 0;
+ char *junkp = NULL;
+ int64_t lval = 0;
time_t crtime = 0;
if (fgets(junk, sizeof junk, fp) == NULL ||
@@ -728,7 +731,7 @@ rscan_news(FILE *fp, int p, time_t lc)
_Static_assert(ARRAY_SIZE(count) > 9, "Unexpected array size");
- if (sscanf(junk, "%ld %9s", &lval, count) != 2) {
+ if (sscanf(junk, ("%" SCNd64 " " "%9s"), &lval, count) != 2) {
warnx("%s: sscanf() error: too few items", __func__);
return;
}
@@ -752,13 +755,13 @@ rscan_news(FILE *fp, int p, time_t lc)
PRIVATE void
check_news(int p, int admin)
{
-#define SCAN_JUNK "%ld %9s"
+#define SCAN_JUNK ("%" SCNd64 " " "%9s")
FILE *fp = NULL;
char count[10] = { '\0' };
char filename[MAX_FILENAME_SIZE] = { '\0' };
char junk[MAX_LINE_SIZE] = { '\0' };
char *junkp = NULL;
- long int lval = 0;
+ int64_t lval = 0;
time_t crtime = 0;
time_t lc = player_lastconnect(p);
diff --git a/FICS/comproc.c b/FICS/comproc.c
index b3c05a3..06592cc 100644
--- a/FICS/comproc.c
+++ b/FICS/comproc.c
@@ -45,6 +45,9 @@
array index read/write.
Markus Uhlin 25/07/21 com_who: fixed multiplication
result converted to larger type.
+ Markus Uhlin 25/07/24 Fixed use of potentially
+ dangerous functions.
+ Markus Uhlin 25/07/29 Usage of 'int64_t'.
*/
#include "stdinclude.h"
@@ -53,6 +56,9 @@
#include <sys/resource.h>
#include <err.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <stdint.h>
#include "board.h"
#include "command.h"
@@ -127,17 +133,17 @@ com_more(int p, param_list param)
PUBLIC void
rscan_news2(FILE *fp, int p, int num)
{
- char *junkp;
char count[10] = { '\0' };
char junk[MAX_LINE_SIZE] = { '\0' };
- long int lval;
+ char *junkp;
+ int64_t lval;
time_t crtime;
if (num == 0)
return;
if (fgets(junk, sizeof junk, fp) == NULL || feof(fp) ||
- sscanf(junk, "%ld %9s", &lval, count) != 2)
+ sscanf(junk, "%" SCNd64 " " "%9s", &lval, count) != 2)
return;
rscan_news2(fp, p, num - 1);
@@ -154,12 +160,12 @@ PUBLIC int
com_news(int p, param_list param)
{
FILE *fp = NULL;
- char *junkp = NULL;
char count[10] = { '\0' };
char filename[MAX_FILENAME_SIZE] = { '\0' };
char junk[MAX_LINE_SIZE] = { '\0' };
+ char *junkp = NULL;
int found = 0;
- long int lval = 0;
+ int64_t lval = 0;
time_t crtime = 0;
snprintf(filename, sizeof filename, "%s/newnews.index", news_dir);
@@ -169,7 +175,7 @@ com_news(int p, param_list param)
return COM_OK;
}
-#define SCAN_JUNK "%ld %9s"
+#define SCAN_JUNK ("%" SCNd64 " " "%9s")
_Static_assert(9 < ARRAY_SIZE(count), "'count' too small");
if (param[0].type == 0) {
@@ -590,9 +596,14 @@ com_stats(int p, param_list param)
if (connected &&
parray[p1].registered &&
(p == p1 || parray[p].adminLevel > 0)) {
- char *timeToStr = ctime((time_t *) &parray[p1].timeOfReg);
+ char timeToStr[30] = { '\0' };
+
+ errno = 0;
+
+ if (ctime_r(&parray[p1].timeOfReg, timeToStr) == NULL)
+ warn("%s: ctime_r", __func__);
+ timeToStr[strcspn(timeToStr, "\n")] = '\0';
- timeToStr[strlen(timeToStr) - 1] = '\0';
pprintf(p, "\n");
onTime = ((time(NULL) - parray[p1].logon_time) +
@@ -755,7 +766,7 @@ plogins(int p, char *fname)
char ipstr[20] = { '\0' };
char loginName[MAX_LOGIN_NAME + 1] = { '\0' };
int registered = 0;
- long int lval = 0;
+ int64_t lval = 0;
time_t tval = 0;
uint16_t inout = 0;
@@ -767,9 +778,10 @@ plogins(int p, char *fname)
_Static_assert(19 < ARRAY_SIZE(ipstr), "'ipstr' too small");
_Static_assert(19 < ARRAY_SIZE(loginName), "'loginName' too small");
+#define SCAN_FMT ("%" SCNu16 " %19s " "%" SCNd64 " " "%d %19s\n")
while (!feof(fp)) {
- if (fscanf(fp, "%hu %19s %ld %d %19s\n", &inout, loginName,
- &lval, &registered, ipstr) != 5) {
+ if (fscanf(fp, SCAN_FMT, &inout, loginName, &lval, &registered,
+ ipstr) != 5) {
fprintf(stderr, "FICS: Error in login info format. "
"%s\n", fname);
fclose(fp);
diff --git a/FICS/gamedb.c b/FICS/gamedb.c
index 2656447..19f0dc7 100644
--- a/FICS/gamedb.c
+++ b/FICS/gamedb.c
@@ -43,6 +43,9 @@
Markus Uhlin 25/04/01 ReadV1GameFmt: guard num half
moves.
Markus Uhlin 25/04/06 Fixed Clang Tidy warnings.
+ Markus Uhlin 25/07/28 Fixed use of potentially
+ dangerous functions.
+ Markus Uhlin 25/07/29 Usage of 'int64_t'.
*/
#include "stdinclude.h"
@@ -50,7 +53,9 @@
#include <err.h>
#include <errno.h>
+#include <inttypes.h>
#include <limits.h>
+#include <stdint.h>
#include "command.h"
#include "config.h"
@@ -563,12 +568,12 @@ EndSym(int g)
PUBLIC char *
movesToString(int g, int pgn)
{
+ char tmp[160] = { '\0' };
char *serv_loc = SERVER_LOCATION;
char *serv_name = SERVER_NAME;
- char tmp[160] = { '\0' };
int i, col;
int wr, br;
- struct tm *tm_ptr = NULL;
+ struct tm v_tm = {0};
time_t curTime;
wr = garray[g].white_rating;
@@ -586,14 +591,16 @@ movesToString(int g, int pgn)
serv_name,
serv_loc);
- if ((tm_ptr = localtime(&curTime)) != NULL) {
+ errno = 0;
+
+ if (localtime_r(&curTime, &v_tm) != NULL) {
strftime(tmp, sizeof(tmp),
"[Date \"%Y.%m.%d\"]\n"
"[Time \"%H:%M:%S\"]\n",
- tm_ptr);
+ &v_tm);
mstrlcat(gameString, tmp, sizeof gameString);
} else
- warn("%s: localtime", __func__);
+ warn("%s: localtime_r()", __func__);
msnprintf(tmp, sizeof tmp,
"[Round \"-\"]\n"
@@ -668,11 +675,13 @@ movesToString(int g, int pgn)
mstrlcat(gameString, tmp, sizeof gameString);
mstrlcat(gameString, "--- ", sizeof gameString);
- if ((tm_ptr = localtime(&curTime)) != NULL) {
- strftime(tmp, sizeof tmp, "%Y.%m.%d %H:%M:%S", tm_ptr);
+ errno = 0;
+
+ if (localtime_r(&curTime, &v_tm) != NULL) {
+ strftime(tmp, sizeof tmp, "%Y.%m.%d %H:%M:%S", &v_tm);
mstrlcat(gameString, tmp, sizeof gameString);
} else
- warn("%s: localtime", __func__);
+ warn("%s: localtime_r()", __func__);
if (garray[g].rated) {
mstrlcat(gameString, "\nRated ", sizeof gameString);
@@ -1276,7 +1285,7 @@ PRIVATE int
ReadV1GameFmt(game *g, FILE *fp, const char *file, int version)
{
int ret[3];
- long int lval;
+ int64_t lval;
_Static_assert(17 < ARRAY_SIZE(g->white_name), "Unexpected array size");
_Static_assert(17 < ARRAY_SIZE(g->black_name), "Unexpected array size");
@@ -1300,7 +1309,7 @@ ReadV1GameFmt(game *g, FILE *fp, const char *file, int version)
if (version < 3 && !g->bInitTime)
g->bInitTime = g->wInitTime;
- if (fscanf(fp, "%ld", &lval) != 1) {
+ if (fscanf(fp, "%" SCNd64, &lval) != 1) {
warnx("%s: %s: failed to get time of start", __func__, file);
return -1;
} else
@@ -1514,7 +1523,7 @@ PRIVATE void
WriteGameFile(FILE *fp, int g)
{
game *gg = &garray[g];
- long int lval;
+ int64_t lval;
player *bp = &parray[gg->black];
player *wp = &parray[gg->white];
@@ -1525,7 +1534,7 @@ WriteGameFile(FILE *fp, int g)
gg->bInitTime, gg->bIncrement);
lval = gg->timeOfStart;
- fprintf(fp, "%ld\n", lval);
+ fprintf(fp, "%" PRId64 "\n", lval);
#ifdef TIMESEAL
fprintf(fp, "%d %d\n",
@@ -2123,6 +2132,8 @@ pgames(int p, int p1, char *fname)
_Static_assert(ARRAY_SIZE(ending) > 99, "'ending' too small");
while (!feof(fp)) {
+ char tbuf[30] = { '\0' };
+
if (fscanf(fp, "%d %1s %d %1s %d %19s %99s %d %d %d %d %99s "
"%99s %ld\n",
&count, result, &MyRating, MyColor,
@@ -2145,7 +2156,7 @@ pgames(int p, int p1, char *fname)
count, result, MyRating, MyColor,
OppRating, OppName,
type, (wt / 600), (wi / 10), eco, ending,
- ctime(&t));
+ ctime_r(&t, tbuf) != NULL ? &tbuf[0] : "");
}
fclose(fp);
diff --git a/FICS/playerdb.c b/FICS/playerdb.c
index c85ec0c..29e14f4 100644
--- a/FICS/playerdb.c
+++ b/FICS/playerdb.c
@@ -46,6 +46,9 @@
Markus Uhlin 25/04/02 add_to_list: added an upper
limit for the list size.
Markus Uhlin 25/04/06 Fixed Clang Tidy warnings.
+ Markus Uhlin 25/07/28 Restricted file permissions upon
+ creation.
+ Markus Uhlin 25/07/30 Usage of 'int64_t'.
*/
#include "stdinclude.h"
@@ -53,6 +56,8 @@
#include <err.h>
#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
#include <stdint.h>
#include "command.h"
@@ -1174,6 +1179,7 @@ player_markdeleted(int p)
FILE *fp;
char fname[MAX_FILENAME_SIZE];
char fname2[MAX_FILENAME_SIZE];
+ int fd;
if (!parray[p].registered) // Player must not be registered
return -1;
@@ -1184,9 +1190,17 @@ player_markdeleted(int p)
parray[p].login[0], parray[p].login);
xrename(__func__, fname, fname2);
- if ((fp = fopen(fname2, "a")) != NULL) { // Touch the file
+ errno = 0;
+ fd = open(fname2, O_WRONLY|O_CREAT, S_IWUSR|S_IRUSR);
+
+ if (fd < 0) {
+ warn("%s: open", __func__);
+ return -1;
+ } else if ((fp = fdopen(fd, "a")) != NULL) { // Touch the file
fprintf(fp, "\n");
fclose(fp);
+ } else {
+ close(fd);
}
return 0;
@@ -1290,6 +1304,7 @@ player_save(int p)
{
FILE *fp;
char fname[MAX_FILENAME_SIZE];
+ int fd;
if (!player_num_ok_chk(p)) {
warnx("%s: invalid player number %d", __func__, p);
@@ -1314,8 +1329,15 @@ player_save(int p)
snprintf(fname, sizeof fname, "%s/%c/%s", player_dir,
parray[p].login[0], parray[p].login);
- if ((fp = fopen(fname, "w")) == NULL) {
+ errno = 0;
+ fd = open(fname, O_WRONLY|O_CREAT, S_IWUSR|S_IRUSR);
+
+ if (fd < 0) {
+ warn("%s: Problem opening file %s for write", __func__, fname);
+ return -1;
+ } else if ((fp = fdopen(fd, "w")) == NULL) {
warn("%s: Problem opening file %s for write", __func__, fname);
+ close(fd);
return -1;
}
@@ -1601,10 +1623,20 @@ player_ontime(int p)
PRIVATE void
write_p_inout(int inout, int p, char *file, int maxlines)
{
- FILE *fp;
+ FILE *fp;
+ int fd;
+
+ errno = 0;
+ fd = open(file, O_WRONLY|O_CREAT, S_IWUSR|S_IRUSR);
- if ((fp = fopen(file, "a")) == NULL)
+ if (fd < 0) {
+ warn("%s: open", __func__);
+ return;
+ } else if ((fp = fdopen(fd, "a")) == NULL) {
+ warn("%s: fdopen", __func__);
+ close(fd);
return;
+ }
fprintf(fp, "%d %s %ld %d %s\n", inout, parray[p].name,
(long int)time(NULL), parray[p].registered,
@@ -1663,7 +1695,7 @@ player_lastconnect(int p)
char loginName[MAX_LOGIN_NAME];
int inout, registered;
int ret, too_long;
- long int lval;
+ int64_t lval = 0;
time_t last = 0;
ret = snprintf(fname, sizeof fname, "%s/player_data/%c/%s.%s",
@@ -1689,8 +1721,8 @@ player_lastconnect(int p)
_Static_assert(19 < ARRAY_SIZE(ipstr),
"'ipstr' too small");
- if (fscanf(fp, "%d %19s %ld %d %19s\n", &inout, loginName,
- &lval, &registered, ipstr) != 5) {
+ if (fscanf(fp, ("%d %19s " "%" SCNd64 " %d %19s\n"), &inout,
+ loginName, &lval, &registered, ipstr) != 5) {
fprintf(stderr, "FICS: Error in login info format. %s"
"\n", fname);
fclose(fp);
@@ -1711,7 +1743,7 @@ player_lastdisconnect(int p)
char loginName[MAX_LOGIN_NAME];
int inout, registered;
int ret, too_long;
- long int lval;
+ int64_t lval;
time_t last = 0;
ret = snprintf(fname, sizeof fname, "%s/player_data/%c/%s.%s",
@@ -1732,8 +1764,8 @@ player_lastdisconnect(int p)
_Static_assert(19 < ARRAY_SIZE(ipstr),
"'ipstr' too small");
- if (fscanf(fp, "%d %19s %ld %d %19s\n", &inout, loginName,
- &lval, &registered, ipstr) != 5) {
+ if (fscanf(fp, ("%d %19s " "%" SCNd64 " %d %19s\n"), &inout,
+ loginName, &lval, &registered, ipstr) != 5) {
fprintf(stderr, "FICS: Error in login info format. %s"
"\n", fname);
fclose(fp);
@@ -2573,9 +2605,10 @@ PUBLIC int
player_add_message(int top, int fromp, char *message)
{
FILE *fp;
- char fname[MAX_FILENAME_SIZE];
- char messbody[1024];
- char subj[256];
+ char fname[MAX_FILENAME_SIZE] = { '\0' };
+ char messbody[1024] = { '\0' };
+ char subj[256] = { '\0' };
+ int fd;
time_t t = time(NULL);
if (!parray[top].registered)
@@ -2588,8 +2621,16 @@ player_add_message(int top, int fromp, char *message)
if (lines_file(fname) >= MAX_MESSAGES && parray[top].adminLevel == 0)
return -1;
- if ((fp = fopen(fname, "a")) == NULL)
+ errno = 0;
+ fd = open(fname, O_WRONLY|O_CREAT, S_IWUSR|S_IRUSR);
+
+ if (fd < 0)
+ return -1;
+ else if ((fp = fdopen(fd, "a")) == NULL) {
+ close(fd);
return -1;
+ }
+
fprintf(fp, "%s at %s: %s\n", parray[fromp].name, strltime(&t),
message);
fclose(fp);
@@ -2752,13 +2793,21 @@ PRIVATE int
WriteMsgFile(int p, textlist *Head)
{
FILE *fp;
- char fName[MAX_FILENAME_SIZE];
+ char fName[MAX_FILENAME_SIZE] = { '\0' };
+ int fd;
textlist *Cur;
GetMsgFile(p, fName, sizeof fName, __func__);
- if ((fp = fopen(fName, "w")) == NULL)
+ errno = 0;
+ fd = open(fName, O_WRONLY|O_CREAT, S_IWUSR|S_IRUSR);
+
+ if (fd < 0)
+ return 0;
+ else if ((fp = fdopen(fd, "w")) == NULL) {
+ close(fd);
return 0;
+ }
for (Cur = Head; Cur != NULL; Cur = Cur->next)
fprintf(fp, "%s", Cur->text);
fclose(fp);
@@ -3161,7 +3210,8 @@ PUBLIC int
player_add_comment(int p_by, int p_to, char *comment)
{
FILE *fp;
- char fname[MAX_FILENAME_SIZE];
+ char fname[MAX_FILENAME_SIZE] = { '\0' };
+ int fd;
time_t t = time(NULL);
if (!parray[p_to].registered)
@@ -3170,8 +3220,17 @@ player_add_comment(int p_by, int p_to, char *comment)
snprintf(fname, sizeof fname, "%s/player_data/%c/%s.%s", stats_dir,
parray[p_to].login[0], parray[p_to].login, "comments");
- if ((fp = fopen(fname, "a")) == NULL)
+ errno = 0;
+ fd = open(fname, O_WRONLY|O_CREAT, S_IWUSR|S_IRUSR);
+
+ if (fd < 0) {
+ warn("%s: open", __func__);
+ return -1;
+ } else if ((fp = fdopen(fd, "a")) == NULL) {
+ warn("%s: fdopen", __func__);
+ close(fd);
return -1;
+ }
fprintf(fp, "%s at %s: %s\n", parray[p_by].name, strltime(&t), comment);
fclose(fp);
diff --git a/FICS/ratings.c b/FICS/ratings.c
index e445c51..a719be0 100644
--- a/FICS/ratings.c
+++ b/FICS/ratings.c
@@ -33,6 +33,10 @@
Markus Uhlin 24/11/28 Added null checks
Markus Uhlin 25/03/16 Fixed use of 32-bit 'time_t'.
Markus Uhlin 25/04/06 Fixed Clang Tidy warnings.
+ Markus Uhlin 25/07/28 Fixed missing return-value check
+ for a 'scanf'-like function.
+ Markus Uhlin 25/07/28 Restricted file permissions upon
+ creation.
*/
#include "stdinclude.h"
@@ -40,6 +44,7 @@
#include <err.h>
#include <errno.h>
+#include <fcntl.h>
#include <limits.h>
#include <stdint.h>
@@ -407,12 +412,20 @@ save_ratings(void)
{
FILE *fp;
char fname[MAX_FILENAME_SIZE] = { '\0' };
+ int fd;
snprintf(fname, sizeof fname, "%s/newratingsV%d_data", stats_dir,
STATS_VERSION);
- if ((fp = fopen(fname, "w")) == NULL) {
+ errno = 0;
+ fd = open(fname, O_WRONLY|O_CREAT, S_IWUSR|S_IRUSR);
+
+ if (fd < 0) {
+ warn("%s: can't write ratings data", __func__);
+ return;
+ } else if ((fp = fdopen(fd, "w")) == NULL) {
warn("%s: can't write ratings data", __func__);
+ close(fd);
return;
}
@@ -1475,7 +1488,8 @@ UpdateRank(int type, char *addName, statistics *sNew, char *delName)
char command[MAX_STRING_LENGTH];
char line[MAX_RANK_LINE] = { '\0' };
char login[MAX_LOGIN_NAME] = { '\0' };
- int comp;
+ int comp = 0;
+ int fd = -1;
statistics sCur;
if (GetRankFileName(RankFile, sizeof RankFile, type) < 0)
@@ -1488,9 +1502,17 @@ UpdateRank(int type, char *addName, statistics *sNew, char *delName)
snprintf(TmpRankFile, sizeof TmpRankFile, "%s/tmpRank", sdir);
- if ((fptemp = fopen(TmpRankFile, "w")) == NULL) {
+ errno = 0;
+ fd = open(TmpRankFile, O_WRONLY|O_CREAT, S_IWUSR|S_IRUSR);
+
+ if (fd < 0) {
+ warn("%s: open", __func__);
+ fclose(fp);
+ return;
+ } else if ((fptemp = fdopen(fd, "w")) == NULL) {
warn("%s: unable to open rank file for updating", __func__);
fclose(fp);
+ close(fd);
return;
}
@@ -1567,7 +1589,8 @@ GetRank(FILE *fp, char *target, int countComp)
char line[MAX_RANK_LINE] = { '\0' };
char login[MAX_LOGIN_NAME] = { '\0' };
int count = 0;
- int nGames, is_computer;
+ int is_computer = 0;
+ int nGames = 0;
int playerFound = 0;
while (fgets(line, sizeof line, fp) != NULL &&
@@ -1575,8 +1598,7 @@ GetRank(FILE *fp, char *target, int countComp)
_Static_assert(ARRAY_SIZE(login) > 19, "'login' too small");
if (sscanf(line, "%19s %*d %d %d", login, &nGames, &is_computer)
- != 1) {
-// warnx("%s: sscanf() error", __func__);
+ < 3) {
continue;
}
diff --git a/FICS/utils.c b/FICS/utils.c
index cf12871..0e1461a 100644
--- a/FICS/utils.c
+++ b/FICS/utils.c
@@ -42,12 +42,16 @@
Markus Uhlin 25/07/21 Replaced non-reentrant functions
with their corresponding thread
safe version.
+ Markus Uhlin 25/07/28 truncate_file: restricted file
+ permissions upon creation.
*/
#include "stdinclude.h"
#include "common.h"
#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
#include "config.h"
#include "network.h"
@@ -853,8 +857,17 @@ truncate_file(char *file, int lines)
fclose(fp);
if (trunc) {
- if ((fp = fopen(file, "w")) == NULL) {
- warn("%s: fopen", __func__);
+ int fd;
+
+ errno = 0;
+ fd = open(file, O_WRONLY|O_CREAT, S_IWUSR|S_IRUSR);
+
+ if (fd < 0) {
+ warn("%s: open", __func__);
+ return 1;
+ } else if ((fp = fdopen(fd, "w")) == NULL) {
+ warn("%s: fdopen", __func__);
+ close(fd);
return 1;
}