My program is written in C for Linux, and has many functions with different patterns for return values:
1) one or two return n
on success and -1>
For can't fail deterministic. Yes/no responses using a more specific (bool) return type can help maintain consistency. Going further for higher level interfaces one may want to think about returning or updating a systems specific messaging/result detail structure.
My preference for 0 to always be a success is based on the following ideas:
Zero enables some basic classing for organizing failures by negative vs positive values such as total failure vs conditioned success. I don't recommend this generally as it tends to be a bit too shallow to be useful and might lead to dangerous behaviorial assumptions.
When success is zero one can make a bunch of orthogonal calls and check for group success in a single condition later simply by comparing the return code of the group..
rc = 0; rc += func1(); rc += func2(); rc += func3(); if (rc == 0) success!
Most importantly zero from my experience seems to be a consistent indication of success when working with standard libraries and third-party systems.