7

First disclosure: I am not much of a C programmer. I am trying to compile a set of C and Fortran codes with much pedigree, using a Makefile to generate an executable for engineering computation. I am using gcc 4.7.1 on sgi Irix (6.5.30). During compilation of the main program, first I get a warning on 'Implicit declaration of function 'setenv'. Subsequently, after generating all the objective 'o' files, the compilation ends with an error :

ld32: Error 33: Unresolved data symbol "setenv"

Commenting out the single line where the 'setenv' is defined allows the compilation to succeed and generate the executable file. However the line with setenv is crucial to the program.

This led me to write a test code and confirm the same problem :

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
int main()
{
   setenv("FILE","/usr/bin/example.c",50);
   printf("File = %s\n", getenv("FILE"));
   return 0;
}

Based on all the suggestions I have found while googling here on stack exchange and other sites, I tried including different headers like

#define _POSIX_C_SOURCE

and

#define _GNU_SOURCE

before any #define statements. I have also tried compiling with -std=c99 as well as -D_XOPEN_SOURCE and -D_GNU_SOURCE with no luck.

I have also tried compiling the test program with Irix's native C compiler (cc and c99) and I get the same error:

Unresolved text symbol 'setenv'

Can someone please provide a helping hand on what else I should look for in my system and or environment variables in order to resolve this error?

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Kaushik Mallick
  • 165
  • 2
  • 8

3 Answers3

6

It indeed looks like IRIX libc does not support the setenv() command. You will have to rewrite it with putenv() like this:

putenv("FILE=/usr/bin/example.c");

See also the IRIX putenv() manpage. Looking for setenv() there does not show any hits, so I assume, this function is missing (note: IRIX 6.5.30 is from 2006)

Ctx
  • 18,090
  • 24
  • 36
  • 51
  • 1
    btw. I've found [this source code](http://man7.org/tlpi/code/online/dist/proc/setenv.c.html) for `setenv()`. Maybe it's easier to implement it than to change the code – Ingo Leonhardt Oct 05 '18 at 15:14
  • @IngoLeonhardt Especially if you really need the `overwrite` flag, this is a good option! – Ctx Oct 05 '18 at 15:15
  • ok, thank you. I see that source code for setenv(). so what do I need to do now? put that source code in a separate file and compile it together with the main or add it to the end of main? do I need to declare or prototype it? sorry for my ignorance. – Kaushik Mallick Oct 05 '18 at 15:38
  • @KaushikMallick If you do _not_ need the `overflow` parameter (it is rarely useful indeed), just use putenv. Otherwise, you can c&p the code for setenv and place it right before your main function, that should do. – Ctx Oct 05 '18 at 15:40
  • ok great. can do. the original code that I want to work is: setenv("CCX_JOBNAME_GETJOBNAME",jobnamec,1); how do replace that with putenv(). thanks a lot again. – Kaushik Mallick Oct 05 '18 at 15:53
  • Note that if you use `putenv()`, you need to worry about whether any `setenv()` implementation you found works with the built-in `putenv`. Where you have a fixed value (string literal) for the file name, using `putenv()` is simple enough. If the value being set varies, you have to worry about whether your memory management is correct. The stqandard `putenv()` does not make a copy of the string you pass to it — that string has got to survive unmangled for long enough. – Jonathan Leffler Oct 05 '18 at 17:02
0

Setting or changing an environment variable has been problematic in the past. With a fixed memory area for the environment block, various solutions have been used. These have included chaining memory fragments, and using realloc(3). There had been no standard way of changing the environment block, even now C99 specifically excludes putenv(3), and does not mention setenv(3).

POSIX includes both setenv(3) and putenv(3), which do a similar job. The standard does state, however, that setenv(3) is the preferred function:

"There was considerable debate as to whether the System V putenv() function or the BSD setenv() function should be required as a mandatory function. The setenv() function was chosen because it permitted the implementation of the unsetenv() function to delete environmental variables, without specifying an additional interface. The putenv() function is available as an XSI extension."

Neither are thread-safe.

This might be a duplicate, although it specifically mentions C99 rather than gcc.

cdarke
  • 42,728
  • 8
  • 80
  • 84
0

Thanks to all of you, my problem is solved! I replaced

setenv("CCX_JOBNAME_GETJOBNAME",jobnamec,1)

in my original main C program with

putenv("CCX_JOBNAME_GETJOBNAME=jobnamec")

and I was able to compile the codes to completion to create the final executable.

dbush
  • 205,898
  • 23
  • 218
  • 273
Kaushik Mallick
  • 165
  • 2
  • 8