@@ -919,10 +919,26 @@ size_t parseprogbasename(char *buf, size_t buflen, const char *progname, size_t
919919 return progbasenamelen ;
920920}
921921
922- int checkprocname ( pid_t pid , const char * progname )
922+ int checkprocname_ignored ( const char * caller )
923923{
924- /* If we can determine the binary path name of the specified "pid",
924+ char * s = NULL ;
925+
926+ if ((s = getenv ("NUT_IGNORE_CHECKPROCNAME" ))) {
927+ /* FIXME: Make server/conf.c::parse_boolean() reusable */
928+ if ( (!strcasecmp (s , "true" )) || (!strcasecmp (s , "on" )) || (!strcasecmp (s , "yes" )) || (!strcasecmp (s , "1" ))) {
929+ upsdebugx (1 , "%s for %s: skipping because caller set NUT_IGNORE_CHECKPROCNAME" , __func__ , NUT_STRARG (caller ));
930+ return 1 ;
931+ }
932+ }
933+
934+ return 0 ;
935+ }
936+
937+ int compareprocname (pid_t pid , const char * procname , const char * progname )
938+ {
939+ /* Given the binary path name of (presumably) a running process,
925940 * check if it matches the assumed name of the current program.
941+ * The "pid" value is used in log reporting.
926942 * Returns:
927943 * -3 Skipped because NUT_IGNORE_CHECKPROCNAME is set
928944 * -2 Could not parse a program name (ok to proceed,
@@ -932,9 +948,9 @@ int checkprocname(pid_t pid, const char *progname)
932948 * 0 Process name identified, does not seem to match
933949 * 1+ Process name identified, and seems to match with
934950 * varying precision
935- * Generally speaking, if (checkprocname (...)) then ok to proceed
951+ * Generally speaking, if (compareprocname (...)) then ok to proceed
936952 */
937- char * procname = NULL , * s ;
953+
938954 int ret = -127 ;
939955 size_t procbasenamelen = 0 , progbasenamelen = 0 ;
940956 /* Track where the last dot is in the basename; 0 means none */
@@ -945,16 +961,11 @@ int checkprocname(pid_t pid, const char *progname)
945961 char procbasename [PATH_MAX ], progbasename [PATH_MAX ];
946962#endif
947963
948- if ((s = getenv ("NUT_IGNORE_CHECKPROCNAME" ))) {
949- /* FIXME: Make server/conf.c::parse_boolean() reusable */
950- if ( (!strcasecmp (s , "true" )) || (!strcasecmp (s , "on" )) || (!strcasecmp (s , "yes" )) || (!strcasecmp (s , "1" ))) {
951- upsdebugx (1 , "%s: skipping because caller set NUT_IGNORE_CHECKPROCNAME" , __func__ );
952- ret = -3 ;
953- goto finish ;
954- }
964+ if (checkprocname_ignored (__func__ )) {
965+ ret = -3 ;
966+ goto finish ;
955967 }
956968
957- procname = getprocname (pid );
958969 if (!procname || !progname ) {
959970 ret = -1 ;
960971 goto finish ;
@@ -975,7 +986,7 @@ int checkprocname(pid_t pid, const char *progname)
975986 }
976987
977988 /* First quickly try for an exact hit of base names */
978- if (progbasenamelen == procbasenamelen && progbasenamedot == procbasenamedot && !strcmp (procname , progname )) {
989+ if (progbasenamelen == procbasenamelen && progbasenamedot == procbasenamedot && !strcmp (procbasename , progbasename )) {
979990 ret = 2 ;
980991 goto finish ;
981992 }
@@ -1091,6 +1102,42 @@ int checkprocname(pid_t pid, const char *progname)
10911102 return ret ;
10921103}
10931104
1105+ int checkprocname (pid_t pid , const char * progname )
1106+ {
1107+ /* If we can determine the binary path name of the specified "pid",
1108+ * check if it matches the assumed name of the current program.
1109+ * Returns: same as compareprocname()
1110+ * Generally speaking, if (checkprocname(...)) then ok to proceed
1111+ */
1112+ char * procname = NULL ;
1113+ int ret = 0 ;
1114+
1115+ /* Quick skip before drilling into getprocname() */
1116+ if (checkprocname_ignored (__func__ )) {
1117+ ret = -3 ;
1118+ goto finish ;
1119+ }
1120+
1121+ if (!progname ) {
1122+ ret = -1 ;
1123+ goto finish ;
1124+ }
1125+
1126+ procname = getprocname (pid );
1127+ if (!procname ) {
1128+ ret = -1 ;
1129+ goto finish ;
1130+ }
1131+
1132+ ret = compareprocname (pid , procname , progname );
1133+
1134+ finish :
1135+ if (procname )
1136+ free (procname );
1137+
1138+ return ret ;
1139+ }
1140+
10941141#ifdef WIN32
10951142/* In WIN32 all non binaries files (namely configuration and PID files)
10961143 are retrieved relative to the path of the binary itself.
@@ -1154,7 +1201,7 @@ int sendsignalpid(pid_t pid, int sig, const char *progname, int check_current_pr
11541201{
11551202#ifndef WIN32
11561203 int ret , cpn1 = -10 , cpn2 = -10 ;
1157- char * current_progname = NULL ;
1204+ char * current_progname = NULL , * procname = NULL ;
11581205
11591206 /* TOTHINK: What about containers where a NUT daemon *is* the only process
11601207 * and is the PID=1 of the container (recycle if dead)? */
@@ -1167,9 +1214,12 @@ int sendsignalpid(pid_t pid, int sig, const char *progname, int check_current_pr
11671214 }
11681215
11691216 ret = 0 ;
1170- if (progname ) {
1217+ if (!checkprocname_ignored (__func__ ))
1218+ procname = getprocname (pid );
1219+
1220+ if (procname && progname ) {
11711221 /* Check against some expected (often built-in) name */
1172- if (!(cpn1 = checkprocname (pid , progname ))) {
1222+ if (!(cpn1 = compareprocname (pid , procname , progname ))) {
11731223 /* Did not match expected (often built-in) name */
11741224 ret = -1 ;
11751225 } else {
@@ -1182,13 +1232,13 @@ int sendsignalpid(pid_t pid, int sig, const char *progname, int check_current_pr
11821232 }
11831233 /* if (cpn1 == -3) => NUT_IGNORE_CHECKPROCNAME=true */
11841234 /* if (cpn1 == -1) => could not determine name of PID... retry just in case? */
1185- if (ret <= 0 && check_current_progname && cpn1 != -3 ) {
1235+ if (procname && ret <= 0 && check_current_progname && cpn1 != -3 ) {
11861236 /* NOTE: This could be optimized a bit by pre-finding the procname
11871237 * of "pid" and re-using it, but this is not a hot enough code path
11881238 * to bother much.
11891239 */
11901240 current_progname = getprocname (getpid ());
1191- if (current_progname && (cpn2 = checkprocname (pid , current_progname ))) {
1241+ if (current_progname && (cpn2 = compareprocname (pid , procname , current_progname ))) {
11921242 if (cpn2 > 0 ) {
11931243 /* Matched current process as asked, ok to proceed */
11941244 ret = 2 ;
@@ -1206,17 +1256,23 @@ int sendsignalpid(pid_t pid, int sig, const char *progname, int check_current_pr
12061256 }
12071257
12081258 /* if ret == 0, ok to proceed - not asked for any sanity checks;
1209- * if ret > 0 we had some definitive match above
1259+ * if ret > 0, ok to proceed - we had some definitive match above;
1260+ * if ret < 0, NOT OK to proceed - we had some definitive fault above
12101261 */
12111262 if (ret < 0 ) {
12121263 upsdebugx (1 ,
12131264 "%s: ran at least one check, and all such checks "
12141265 "found a process name for PID %" PRIuMAX " and "
1215- "failed to match: expected progname='%s' (res=%d), "
1216- "current progname='%s' (res=%d)" ,
1266+ "failed to match: "
1267+ "found procname='%s', "
1268+ "expected progname='%s' (res=%d%s), "
1269+ "current progname='%s' (res=%d%s)" ,
12171270 __func__ , (uintmax_t )pid ,
1271+ NUT_STRARG (procname ),
12181272 NUT_STRARG (progname ), cpn1 ,
1219- NUT_STRARG (current_progname ), cpn2 );
1273+ (cpn1 == -10 ? ": did not check" : "" ),
1274+ NUT_STRARG (current_progname ), cpn2 ,
1275+ (cpn2 == -10 ? ": did not check" : "" ));
12201276
12211277 if (nut_debug_level > 0 || nut_sendsignal_debug_level > 1 ) {
12221278 switch (ret ) {
@@ -1267,14 +1323,25 @@ int sendsignalpid(pid_t pid, int sig, const char *progname, int check_current_pr
12671323 current_progname = NULL ;
12681324 }
12691325
1326+ if (procname ) {
1327+ free (procname );
1328+ procname = NULL ;
1329+ }
1330+
12701331 /* Logged or not, sanity-check was requested and failed */
12711332 return -1 ;
12721333 }
1334+
12731335 if (current_progname ) {
12741336 free (current_progname );
12751337 current_progname = NULL ;
12761338 }
12771339
1340+ if (procname ) {
1341+ free (procname );
1342+ procname = NULL ;
1343+ }
1344+
12781345 /* see if this is going to work first - does the process exist,
12791346 * and do we have permissions to signal it? */
12801347 ret = kill (pid , 0 );
0 commit comments