aboutsummaryrefslogtreecommitdiffstats
path: root/FICS/playerdb.c
diff options
context:
space:
mode:
Diffstat (limited to 'FICS/playerdb.c')
-rw-r--r--FICS/playerdb.c267
1 files changed, 192 insertions, 75 deletions
diff --git a/FICS/playerdb.c b/FICS/playerdb.c
index f9e9410..1373630 100644
--- a/FICS/playerdb.c
+++ b/FICS/playerdb.c
@@ -35,12 +35,24 @@
Markus Uhlin 24/11/24 Fixed incorrect format strings
Markus Uhlin 24/12/02 Made many improvements
Markus Uhlin 24/12/04 Added player number checks
+ Markus Uhlin 25/02/11 Calc string length once
+ Markus Uhlin 25/03/22 Fixed overflowed return value in
+ player_search().
+ Markus Uhlin 25/03/23 Fixed overflowed array index
+ read/write.
+ Markus Uhlin 25/03/29 player_remove_request:
+ fixed overflowed array index
+ read/write.
+ 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.
*/
#include "stdinclude.h"
#include "common.h"
#include <err.h>
+#include <errno.h>
#include <stdint.h>
#include "command.h"
@@ -74,6 +86,21 @@ player_num_ok_chk(const int num)
num < (int)ARRAY_SIZE(parray));
}
+PUBLIC void
+xrename(const char *fn, const char *name1, const char *name2)
+{
+ if (fn == NULL || name1 == NULL || name2 == NULL) {
+ errno = EINVAL;
+ warn("%s", __func__);
+ return;
+ }
+
+ errno = 0;
+
+ if (rename(name1, name2) != 0)
+ warn("%s: '%s' -> '%s'", fn, name1, name2);
+}
+
PRIVATE int
get_empty_slot(void)
{
@@ -385,10 +412,14 @@ add_to_list(FILE *fp, enum ListWhich lw, int *size, int p)
#define SCAN_STR "%1023s"
- if (*size <= 0)
+ if (*size <= 0 || *size > MAX_GLOBAL_LIST_SIZE) {
+// warnx("%s: illegal list size (%d)", __func__, *size);
return -2;
+ }
+
while ((*size)-- > 0 && fscanf(fp, SCAN_STR, buf) == 1)
list_add(p, lw, buf);
+
return (*size <= 0 ? 0 : -1);
}
@@ -411,7 +442,7 @@ ReadV1PlayerFmt(int p, player *pp, FILE *fp, char *file, int version)
/*
* Name
*/
- if (fgets(tmp2, sizeof tmp2, fp) != NULL &&
+ if (fgets(tmp2, sizeof tmp2, fp) != NULL && // NOLINT
strcmp(tmp2, "NONE\n") != 0) {
tmp2[strcspn(tmp2, "\n")] = '\0';
pp->name = xstrdup(tmp2);
@@ -422,7 +453,7 @@ ReadV1PlayerFmt(int p, player *pp, FILE *fp, char *file, int version)
/*
* Full name
*/
- if (fgets(tmp2, sizeof tmp2, fp) != NULL &&
+ if (fgets(tmp2, sizeof tmp2, fp) != NULL && // NOLINT
strcmp(tmp2, "NONE\n") != 0) {
tmp2[strcspn(tmp2, "\n")] = '\0';
pp->fullName = xstrdup(tmp2);
@@ -433,7 +464,7 @@ ReadV1PlayerFmt(int p, player *pp, FILE *fp, char *file, int version)
/*
* Password
*/
- if (fgets(tmp2, sizeof tmp2, fp) != NULL &&
+ if (fgets(tmp2, sizeof tmp2, fp) != NULL && // NOLINT
strcmp(tmp2, "NONE\n") != 0) {
tmp2[strcspn(tmp2, "\n")] = '\0';
pp->passwd = xstrdup(tmp2);
@@ -444,7 +475,7 @@ ReadV1PlayerFmt(int p, player *pp, FILE *fp, char *file, int version)
/*
* Email
*/
- if (fgets(tmp2, sizeof tmp2, fp) != NULL &&
+ if (fgets(tmp2, sizeof tmp2, fp) != NULL && // NOLINT
strcmp(tmp2, "NONE\n") != 0) {
tmp2[strcspn(tmp2, "\n")] = '\0';
pp->emailAddress = xstrdup(tmp2);
@@ -452,7 +483,9 @@ ReadV1PlayerFmt(int p, player *pp, FILE *fp, char *file, int version)
pp->emailAddress = NULL;
}
- if (fscanf(fp, "%d %d %d %d %d %d %jd %d %jd %d %d %d %d %d %d %jd %d %jd "
+ if (feof(fp) ||
+ ferror(fp) ||
+ fscanf(fp, "%d %d %d %d %d %d %jd %d %jd %d %d %d %d %d %d %jd %d %jd "
"%d %d %d %d %d %d %jd %d %jd %d %d %d %d %d %d %jd %d %jd %d %d %d %d "
"%d %d %jd %d %jd %u\n",
&pp->s_stats.num, &pp->s_stats.win, &pp->s_stats.los,
@@ -554,6 +587,23 @@ ReadV1PlayerFmt(int p, player *pp, FILE *fp, char *file, int version)
pp->timeOfReg = array[0];
pp->totalTime = array[1];
+ if (pp->num_plan >= MAX_PLAN) {
+ warnx("Player %s is corrupt\nToo many plans (%d)",
+ parray[p].name,
+ pp->num_plan);
+ return;
+ } else if (pp->num_formula >= MAX_FORMULA) {
+ warnx("Player %s is corrupt\nToo many formulas (%d)",
+ parray[p].name,
+ pp->num_formula);
+ return;
+ } else if (pp->numAlias >= MAX_ALIASES) {
+ warnx("Player %s is corrupt\nToo many aliases (%d)",
+ parray[p].name,
+ pp->numAlias);
+ return;
+ }
+
if (pp->num_plan > 0) {
for (i = 0; i < pp->num_plan; i++) {
if (fgets(tmp2, sizeof tmp2, fp) == NULL) {
@@ -618,14 +668,13 @@ ReadV1PlayerFmt(int p, player *pp, FILE *fp, char *file, int version)
return;
}
- if (!(len = strlen(tmp2))) {
+ if (!strlen(tmp2)) { // XXX
fprintf(stderr, "FICS: Error bad alias in "
"file %s\n", file);
i--;
pp->numAlias--;
} else {
tmp2[strcspn(tmp2, "\n")] = '\0';
- tmp = tmp2;
tmp = eatword(tmp2);
*tmp = '\0';
tmp++;
@@ -810,9 +859,11 @@ got_attr_value_player(int p, char *attr, char *value, FILE *fp, char *file)
* num_plan
*/
- parray[p].num_plan = atoi(value);
-
- if (parray[p].num_plan > 0) {
+ if ((parray[p].num_plan = atoi(value)) >= MAX_PLAN) {
+ warnx("%s: %s: too many plans (%d)", __func__, file,
+ parray[p].num_plan);
+ return -1;
+ } else if (parray[p].num_plan > 0) {
for (i = 0; i < parray[p].num_plan; i++) {
if (fgets(tmp, sizeof tmp, fp) == NULL) {
@@ -834,15 +885,19 @@ got_attr_value_player(int p, char *attr, char *value, FILE *fp, char *file)
xstrdup(tmp) : NULL);
}
}
+ } else {
+ /* null */;
}
} else if (!strcmp(attr, "num_formula:")) {
/*
* num_formula
*/
- parray[p].num_formula = atoi(value);
-
- if (parray[p].num_formula > 0) {
+ if ((parray[p].num_formula = atoi(value)) >= MAX_FORMULA) {
+ warnx("%s: %s: too many formulas (%d)", __func__, file,
+ parray[p].num_formula);
+ return -1;
+ } else if (parray[p].num_formula > 0) {
for (i = 0; i < parray[p].num_formula; i++) {
if (fgets(tmp, sizeof tmp, fp) == NULL) {
warnx("%s: bad formula: feof %s",
@@ -863,6 +918,8 @@ got_attr_value_player(int p, char *attr, char *value, FILE *fp, char *file)
xstrdup(tmp) : NULL);
}
}
+ } else {
+ /* null */;
}
} else if (!strcmp(attr, "formula:")) {
/*
@@ -875,9 +932,11 @@ got_attr_value_player(int p, char *attr, char *value, FILE *fp, char *file)
* num_alias
*/
- parray[p].numAlias = atoi(value);
-
- if (parray[p].numAlias > 0) {
+ if ((parray[p].numAlias = atoi(value)) >= MAX_ALIASES) {
+ warnx("%s: %s: too many aliases (%d)", __func__, file,
+ parray[p].numAlias);
+ return -1;
+ } else if (parray[p].numAlias > 0) {
for (i = 0; i < parray[p].numAlias; i++) {
if (fgets(tmp, sizeof tmp, fp) == NULL) {
warnx("%s: bad alias: feof %s",
@@ -885,7 +944,7 @@ got_attr_value_player(int p, char *attr, char *value, FILE *fp, char *file)
return -1;
}
- if (!(len = strlen(tmp))) {
+ if (!strlen(tmp)) { // XXX
fprintf(stderr, "FICS: Error bad alias "
"in file %s\n", file);
i--;
@@ -904,13 +963,21 @@ got_attr_value_player(int p, char *attr, char *value, FILE *fp, char *file)
xstrdup(tmp1);
}
}
+ } else {
+ /* null */;
}
} else if (!strcmp(attr, "num_censor:")) {
/*
* num_censor
*/
- i = atoi(value);
+ if ((i = atoi(value)) < 0) {
+ warnx("%s: num censor negative", __func__);
+ return -1;
+ } else if (i > MAX_CENSOR) {
+ warnx("%s: num censor too large", __func__);
+ return -1;
+ }
while (i--) {
if (fgets(tmp, sizeof tmp, fp) == NULL) {
@@ -929,7 +996,13 @@ got_attr_value_player(int p, char *attr, char *value, FILE *fp, char *file)
}
}
} else if (!strcmp(attr, "num_notify:")) {
- i = atoi(value);
+ if ((i = atoi(value)) < 0) {
+ warnx("%s: num notify negative", __func__);
+ return -1;
+ } else if (i > MAX_NOTIFY) {
+ warnx("%s: num notify too large", __func__);
+ return -1;
+ }
while (i--) {
if (fgets(tmp, sizeof tmp, fp) == NULL) {
@@ -948,7 +1021,10 @@ got_attr_value_player(int p, char *attr, char *value, FILE *fp, char *file)
}
}
} else if (!strcmp(attr, "num_noplay:")) {
- i = atoi(value);
+ if ((i = atoi(value)) < 0) {
+ warnx("%s: num noplay negative", __func__);
+ return -1;
+ }
while (i--) {
if (fgets(tmp, sizeof tmp, fp) == NULL) {
@@ -967,7 +1043,10 @@ got_attr_value_player(int p, char *attr, char *value, FILE *fp, char *file)
}
}
} else if (!strcmp(attr, "num_gnotify:")) {
- i = atoi(value);
+ if ((i = atoi(value)) < 0) {
+ warnx("%s: num gnotify negative", __func__);
+ return -1;
+ }
while (i--) {
if (fgets(tmp, sizeof tmp, fp) == NULL) {
@@ -1023,7 +1102,7 @@ player_read(int p, char *name)
}
if (line[0] == 'v')
- sscanf(line, "%*c %d", &version);
+ (void)sscanf(line, "%*c %d", &version);
if (version > 0) // Quick method:
ReadV1PlayerFmt(p, &parray[p], fp, fname, version);
else { // Do it the old SLOW way
@@ -1103,7 +1182,7 @@ player_markdeleted(int p)
parray[p].login[0], parray[p].login);
snprintf(fname2, sizeof fname2, "%s/%c/%s.delete", player_dir,
parray[p].login[0], parray[p].login);
- rename(fname, fname2);
+ xrename(__func__, fname, fname2);
if ((fp = fopen(fname2, "a")) != NULL) { // Touch the file
fprintf(fp, "\n");
@@ -1282,10 +1361,13 @@ player_find_part_login(char *name)
{
int found = -1;
int i;
+ size_t namelen;
if ((i = player_find_bylogin(name)) >= 0)
return i;
+ namelen = strlen(name);
+
for (i = 0; i < p_num; i++) {
if (parray[i].status == PLAYER_EMPTY ||
parray[i].status == PLAYER_LOGIN ||
@@ -1295,7 +1377,7 @@ player_find_part_login(char *name)
if (!parray[i].login)
continue;
- if (!strncmp(parray[i].login, name, strlen(name))) {
+ if (!strncmp(parray[i].login, name, namelen)) {
if (found >= 0) /* Ambiguous */
return -2;
found = i;
@@ -1581,7 +1663,7 @@ player_lastconnect(int p)
char loginName[MAX_LOGIN_NAME];
int inout, registered;
int ret, too_long;
- long int lval;
+ long int lval = 0;
time_t last = 0;
ret = snprintf(fname, sizeof fname, "%s/player_data/%c/%s.%s",
@@ -1766,17 +1848,26 @@ player_new_pendto(int p)
PUBLIC int
player_remove_pendto(int p, int p1, int type)
{
- int w;
+ bool removed = false;
+ int w;
if ((w = player_find_pendto(p, p1, type)) < 0)
return -1;
- for (; w < (parray[p].num_to - 1); w++)
+ for (; w < (parray[p].num_to - 1); w++) {
+ if (w + 1 >= (int)ARRAY_SIZE(parray[0].p_to_list)) {
+ warnx("%s: overflowed array index write", __func__);
+ break;
+ }
+
parray[p].p_to_list[w] = parray[p].p_to_list[w + 1];
+ removed = true;
+ }
- parray[p].num_to = (parray[p].num_to - 1);
+ UNUSED_VAR(removed);
+ parray[p].num_to -= 1;
- return 0;
+ return (0);
}
PUBLIC int
@@ -1820,17 +1911,26 @@ player_new_pendfrom(int p)
PUBLIC int
player_remove_pendfrom(int p, int p1, int type)
{
- int w;
+ bool removed = false;
+ int w;
if ((w = player_find_pendfrom(p, p1, type)) < 0)
return -1;
- for (; w < (parray[p].num_from - 1); w++)
+ for (; w < (parray[p].num_from - 1); w++) {
+ if (w + 1 >= (int)ARRAY_SIZE(parray[0].p_from_list)) {
+ warnx("%s: overflowed array index write", __func__);
+ break;
+ }
+
parray[p].p_from_list[w] = parray[p].p_from_list[w + 1];
+ removed = true;
+ }
- parray[p].num_from = (parray[p].num_from - 1);
+ UNUSED_VAR(removed);
+ parray[p].num_from -= 1;
- return 0;
+ return (0);
}
PUBLIC int
@@ -1865,28 +1965,44 @@ player_add_request(int p, int p1, int type, int param)
PUBLIC int
player_remove_request(int p, int p1, int type)
{
- int to = 0, from = 0;
+ bool removed;
+ int to = 0, from = 0;
- while (to != -1) {
- if ((to = player_find_pendto(p, p1, type)) != -1) {
- for (; to < parray[p].num_to - 1; to++) {
- parray[p].p_to_list[to] =
- parray[p].p_to_list[to + 1];
+ while (to != -1 && (to = player_find_pendto(p, p1, type)) != -1) {
+ removed = false;
+
+ for (; to < parray[p].num_to - 1; to++) {
+ if (to + 1 >= (int)ARRAY_SIZE(parray[0].p_to_list)) {
+ warnx("%s: overflowed array index read/write",
+ __func__);
+ break;
}
- parray[p].num_to = (parray[p].num_to - 1);
+ parray[p].p_to_list[to] = parray[p].p_to_list[to + 1];
+ removed = true;
}
+
+ UNUSED_VAR(removed);
+ parray[p].num_to -= 1;
}
- while (from != -1) {
- if ((from = player_find_pendfrom(p1, p, type)) != -1) {
- for (; from < parray[p1].num_from - 1; from++) {
- parray[p1].p_from_list[from] =
- parray[p1].p_from_list[from + 1];
+ while (from != -1 && (from = player_find_pendfrom(p1, p, type)) != -1) {
+ removed = false;
+
+ for (; from < parray[p1].num_from - 1; from++) {
+ if (from + 1 >= (int)ARRAY_SIZE(parray[0].p_from_list)) {
+ warnx("%s: overflowed array index read/write",
+ __func__);
+ break;
}
- parray[p1].num_from = (parray[p1].num_from - 1);
+ parray[p1].p_from_list[from] =
+ parray[p1].p_from_list[from + 1];
+ removed = true;
}
+
+ UNUSED_VAR(removed);
+ parray[p1].num_from -= 1;
}
if ((type == PEND_ALL || type == PEND_MATCH) && parray[p].partner >= 0)
@@ -2254,7 +2370,6 @@ player_goto_next_board(int p)
on = parray[p].simul_info.onBoard;
start = on;
- g = -1;
do {
on++;
@@ -2283,7 +2398,6 @@ player_goto_prev_board(int p)
on = parray[p].simul_info.onBoard;
start = on;
- g = -1;
do {
--on;
@@ -2722,7 +2836,7 @@ player_show_messages(int p)
PUBLIC int
ShowMsgsBySender(int p, param_list param)
{
- int nFrom, nTo;
+ int nFrom = -1, nTo = -1;
int p1, connected;
textlist *Head;
@@ -2735,8 +2849,6 @@ ShowMsgsBySender(int p, param_list param)
return -1; /* no need to disconnect */
}
- nFrom = nTo = -1;
-
if (p != p1) {
if ((nTo = LoadMsgs(p1, p + 1, &Head)) <= 0) {
pprintf(p, "%s has no messages from you.\n",
@@ -2825,8 +2937,11 @@ player_search(int p, char *name)
int p1, count;
// Exact match with connected player?
- if ((p1 = player_find_bylogin(name)) >= 0)
+ if ((p1 = player_find_bylogin(name)) >= 0) {
+ if (p1 + 1 >= (int)ARRAY_SIZE(parray))
+ return 0;
return (p1 + 1);
+ }
// Exact match with registered player?
snprintf(pdir, sizeof pdir, "%s/%c", player_dir, name[0]);
@@ -2882,7 +2997,7 @@ player_kill(char *name)
name);
snprintf(fname2, sizeof fname2, "%s/%c/.rem.%s", player_dir, name[0],
name);
- rename(fname, fname2);
+ xrename(__func__, fname, fname2);
RemHist(name);
@@ -2890,25 +3005,25 @@ player_kill(char *name)
stats_dir, name[0], name);
snprintf(fname2, sizeof fname2, "%s/player_data/%c/.rem.%s.games",
stats_dir, name[0], name);
- rename(fname, fname2);
+ xrename(__func__, fname, fname2);
snprintf(fname, sizeof fname, "%s/player_data/%c/%s.comments",
stats_dir, name[0], name);
snprintf(fname2, sizeof fname2, "%s/player_data/%c/.rem.%s.comments",
stats_dir, name[0], name);
- rename(fname, fname2);
+ xrename(__func__, fname, fname2);
snprintf(fname, sizeof fname, "%s/player_data/%c/%s.logons",
stats_dir, name[0], name);
snprintf(fname2, sizeof fname2, "%s/player_data/%c/.rem.%s.logons",
stats_dir, name[0], name);
- rename(fname, fname2);
+ xrename(__func__, fname, fname2);
snprintf(fname, sizeof fname, "%s/player_data/%c/%s.messages",
stats_dir, name[0], name);
snprintf(fname2, sizeof fname2, "%s/player_data/%c/.rem.%s.messages",
stats_dir, name[0], name);
- rename(fname, fname2);
+ xrename(__func__, fname, fname2);
return 0;
}
@@ -2923,31 +3038,31 @@ player_rename(char *name, char *newname)
name);
snprintf(fname2, sizeof fname2, "%s/%c/%s", player_dir, newname[0],
newname);
- rename(fname, fname2);
+ xrename(__func__, fname, fname2);
snprintf(fname, sizeof fname, "%s/player_data/%c/%s.games",
stats_dir, name[0], name);
snprintf(fname2, sizeof fname2, "%s/player_data/%c/%s.games",
stats_dir, newname[0], newname);
- rename(fname, fname2);
+ xrename(__func__, fname, fname2);
snprintf(fname, sizeof fname, "%s/player_data/%c/%s.comments",
stats_dir, name[0], name);
snprintf(fname2, sizeof fname2, "%s/player_data/%c/%s.comments",
stats_dir, newname[0], newname);
- rename(fname, fname2);
+ xrename(__func__, fname, fname2);
snprintf(fname, sizeof fname, "%s/player_data/%c/%s.logons",
stats_dir, name[0], name);
snprintf(fname2, sizeof fname2, "%s/player_data/%c/%s.logons",
stats_dir, newname[0], newname);
- rename(fname, fname2);
+ xrename(__func__, fname, fname2);
snprintf(fname, sizeof fname, "%s/player_data/%c/%s.messages",
stats_dir, name[0], name);
snprintf(fname2, sizeof fname2, "%s/player_data/%c/%s.messages",
stats_dir, newname[0], newname);
- rename(fname, fname2);
+ xrename(__func__, fname, fname2);
return 0;
}
@@ -2962,31 +3077,31 @@ player_raise(char *name)
name[0], name);
snprintf(fname2, sizeof fname2, "%s/%c/.rem.%s", player_dir,
name[0], name);
- rename(fname2, fname);
+ xrename(__func__, fname2, fname);
snprintf(fname, sizeof fname, "%s/player_data/%c/%s.games",
stats_dir, name[0], name);
snprintf(fname2, sizeof fname2, "%s/player_data/%c/.rem.%s.games",
stats_dir, name[0], name);
- rename(fname2, fname);
+ xrename(__func__, fname2, fname);
snprintf(fname, sizeof fname, "%s/player_data/%c/%s.comments",
stats_dir, name[0], name);
snprintf(fname2, sizeof fname2, "%s/player_data/%c/.rem.%s.comments",
stats_dir, name[0], name);
- rename(fname2, fname);
+ xrename(__func__, fname2, fname);
snprintf(fname, sizeof fname, "%s/player_data/%c/%s.logons",
stats_dir, name[0], name);
snprintf(fname2, sizeof fname2, "%s/player_data/%c/.rem.%s.logons",
stats_dir, name[0], name);
- rename(fname2, fname);
+ xrename(__func__, fname2, fname);
snprintf(fname, sizeof fname, "%s/player_data/%c/%s.messages",
stats_dir, name[0], name);
snprintf(fname2, sizeof fname2, "%s/player_data/%c/.rem.%s.messages",
stats_dir, name[0], name);
- rename(fname2, fname);
+ xrename(__func__, fname2, fname);
return 0;
}
@@ -3001,31 +3116,31 @@ player_reincarn(char *name, char *newname)
newname[0], newname);
snprintf(fname2, sizeof fname2, "%s/%c/.rem.%s", player_dir,
name[0], name);
- rename(fname2, fname);
+ xrename(__func__, fname2, fname);
snprintf(fname, sizeof fname, "%s/player_data/%c/%s.games",
stats_dir, newname[0], newname);
snprintf(fname2, sizeof fname2, "%s/player_data/%c/.rem.%s.games",
stats_dir, name[0], name);
- rename(fname2, fname);
+ xrename(__func__, fname2, fname);
snprintf(fname, sizeof fname, "%s/player_data/%c/%s.comments",
stats_dir, newname[0], newname);
snprintf(fname2, sizeof fname2, "%s/player_data/%c/.rem.%s.comments",
stats_dir, name[0], name);
- rename(fname2, fname);
+ xrename(__func__, fname2, fname);
snprintf(fname, sizeof fname, "%s/player_data/%c/%s.logons",
stats_dir, newname[0], newname);
snprintf(fname2, sizeof fname2, "%s/player_data/%c/.rem.%s.logons",
stats_dir, name[0], name);
- rename(fname2, fname);
+ xrename(__func__, fname2, fname);
snprintf(fname, sizeof fname, "%s/player_data/%c/%s.messages",
stats_dir, newname[0], newname);
snprintf(fname2, sizeof fname2, "%s/player_data/%c/.rem.%s.messages",
stats_dir, name[0], name);
- rename(fname2, fname);
+ xrename(__func__, fname2, fname);
return 0;
}
@@ -3067,11 +3182,13 @@ player_add_comment(int p_by, int p_to, char *comment)
PUBLIC int
player_show_comments(int p, int p1)
{
- char fname[MAX_FILENAME_SIZE];
+ char fname[MAX_FILENAME_SIZE] = { '\0' };
snprintf(fname, sizeof fname, "%s/player_data/%c/%s.%s", stats_dir,
parray[p1].login[0], parray[p1].login, "comments");
- psend_file(p, NULL, fname);
+
+ if (psend_file(p, NULL, fname) == -1)
+ warnx("%s: psend_file() error", __func__);
return 0;
}