• Updated 2023-07-12: Hello, Guest! Welcome back, and be sure to check out this follow-up post about our outage a week or so ago.

A/UX porting & programming

ChristTrekker

Well-known member
As I've mentioned around this forum several times, I am working on porting pkgsrc to A/UX. You can read about my trials and tribulations if you want.

I'm currently stuck on an issue surrounding _POSIX_SOURCE, _BSD_SOURCE, and WAIT_T, if anyone has any suggestions. This seems to be a core portability piece, but I'm not sure how to proceed.

 

porter

Well-known member
Use either _POSIX_SOURCE or _BSD_SOURCE, not both.

A/UX is a System V based UNIX with BSD sockets (normally System V has TLI or XTI).

I suggest using "_POSIX_SOURCE" and link with the "libposix.a" library.

This code happily works on A/UX under these conditions...

Code:
		waitpid(pid,&status,0);

	if (WIFEXITED(status))
	{
		rc=WEXITSTATUS(status);
	}
Similarly, for signals, avoid the "signal()" API like the plague and use sigaction().

I also recommend you build a header file with the function prototypes when using an ANSI compiler.

 

ChristTrekker

Well-known member
Looking in some old (1995) archives of comp.unix.aux...

Be default, cc and gcc always define _BSD_SOURCE, _SYSV_SOURCE and _AUX_SOURCE (cc may not do that last one... it's been awhile :) ). If you specifically tell them _only_ BSD or SYSV or POSIX mode, then only they will be used. If you've got some ports that look like their "mostly" Posix friendly, just add '-D_POSIX_SOURCE -lposix' to the command line so that the POSIX compat's will be included.
 

ChristTrekker

Well-known member
Looks like I'll be trying to add some functions to libUTIL: estrdup, estrndup, and srandom. Or trying to find a way to hack around these with regular strdup, strndup, and srand. Which would be the better approach...hmmm...

 

porter

Well-known member
I recommend against having duplicate names for functions that do the same thing, better to provide a correct implementation then all code benefits. The linking order (order the libraries appear on the linking command line) is important for dragging in object files, it works strictly left to right. I suggest producing a link map to confirm the correct objects are being linked in.

 

ChristTrekker

Well-known member
I quite agree. You can read the man pages for those functions on daemon-systems.org. The "e" functions are very similar to the originals, but they are different. OTOH, srandom seems to be just a better implementation of srand, so I don't know why you wouldn't just improve srand.

 

porter

Well-known member
Yeah, and OpenBSD have their own duplicate set strlcpy etc.

Stick with the standard ones, the goal is portability, surely?

The advantage of a statically linked program is you do have a fine grain of control of what functions you link in.

 

ChristTrekker

Well-known member
Stick with the standard ones, the goal is portability, surely?
That's what I was thinking--especially with NetBSD. I think I'll put some #ifdefs in the code and send the patch upstream.

 

porter

Well-known member
Regarding portability, I have an environment with many different systems, Linux, NetBSD,OpenBSD, FreeBSD, HPUX, AIX, AUX, Solaris, IRIX and Tru64. When I make changes I regularly test they haven't broken the builds or tests in the other environments.

When doing #ifdefs it is far better to base the macro on something determined from configure or config.h, that way you haven't just solved it for a single platform, you have solved it for all platforms that have that feature or quirk.

A good example is

Code:
#ifdef HAVE_SNPRINTF
    snprintf(buf,sizeof(buf),"%d",(int)getpid());
#else
    sprintf(buf,"%d",(int)getpid());
#endif
Then if you do add snprintf to that environment a new configure and build will pick it up.

 

ChristTrekker

Well-known member
That's what I'm doing. The HAVE_* definitions are mostly set up already, and where they're not, I add the function name to the configure.in file and regenerate the configure too. This is teaching me a lot more about "programming" than just the programming part itself...fun!

Also I discovered that srandom is just a wrapper to srand48, which I do have. It's just not declared before it gets used. I tried putting it's signature at the top of that file, but it didn't work - linker still complains. Hmm.

 
Last edited by a moderator:

porter

Well-known member
I use the gcc "-include" command with the following header to define all the prototypes outside of the project code, basically fixing the system headers without touching the /usr/include directory.

Alas, you have to go through function by function and use man to get the correct prototype. Then it also becomes a problem with the man page says their are two different versions depending on the macros, currently I avoid those.

This lets me use gcc with "-Wall -Werror" which I find necessary for my configure to work.

Code:
/* Custom header for A/UX 3.1.1

must work with no other includes
*/

#ifdef __cplusplus
extern "C" {
#endif

struct timeval;
struct timezone;
struct sockaddr;
struct sigstack;
struct fd_set;
struct ether_addr;

int getcompat(void);
int setcompat(int);
int setpgrp(int,int);

int ether_hostton(char *,struct ether_addr *);
int vfork(void);
int bzero(char *,int);

int select(int,struct fd_set *,struct fd_set *,struct fd_set *,struct timeval *);
int recv(int,char *,int,int);
int send(int,const char *,int,int);
int accept(int,struct sockaddr *,int *);
int socketpair(int,int,int,int *);
int getsockname(int,struct sockaddr *,int *);
int getpeername(int,struct sockaddr *,int *);
int connect(int,struct sockaddr *,int);
int gethostname(char *,int);
int bind(int,struct sockaddr *,int);
int listen(int,int);
int socket(int,int,int);
int setsockopt(int,int,int,char *,int);
int getsockopt(int,int,int,char *,int*);
int sendto(int,const char *,int,int,const struct sockaddr *,int);
int recvfrom(int,const char *,int,int,struct sockaddr *,int *);
int ioctl(int,int,...);
int sigstack(struct sigstack*,struct sigstack *);
int slot_ether_addr(int,void *);
int gettimeofday(struct timeval *,struct timezone *);
int strcasecmp(const char *,const char *);
int shutdown(int,int);
int setgroups(int,int*);
void openlog(const char *,int,int);
void syslog(int,const char *,...);
void closelog(void);
int setlogmask(int);
int flock(int,int);
int ftruncate(int,int);
int getopt(int,char *const*,const char *);
int setsid(void);

extern char *optarg;
extern int optind, opterr;

#ifdef __cplusplus
}
#endif
 

ChristTrekker

Well-known member
Now getting undefined symbols sigprocmask, sigfillset, sigdelset, sigemptyset, sigaction, sigaddset, sigismember, and sigsuspend. These are defined in and contained in libposix.a, so I'm at a loss...

 

porter

Well-known member
These are defined in and contained in libposix.a, so I'm at a loss...
They most definitely do exist. Check which order you are linking the libraries in.

gcc [source files/object files] lib1 lib2 lib3 lib4

The libraries must appear in the correct order, if lib2 depends on lib1 then the link will fail unless one of the source files had the dependency.

Write a small test program and prove the point first.

 

ChristTrekker

Well-known member
Check which order you are linking the libraries in.
Definitely been far too long since I've seriously written any code. I should have thought of that. Though that's backwards of the order my intuition would say they should go (libs first, so the following objects can find them).

...

That did it! Thanks. On to the next problem. :)

 
Top