env.go 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. package frankenphp
  2. // #include "frankenphp.h"
  3. import "C"
  4. import (
  5. "os"
  6. "strings"
  7. "unsafe"
  8. )
  9. //export go_putenv
  10. func go_putenv(str *C.char, length C.int) C.bool {
  11. envString := C.GoStringN(str, length)
  12. // Check if '=' is present in the string
  13. if key, val, found := strings.Cut(envString, "="); found {
  14. return os.Setenv(key, val) == nil
  15. }
  16. // No '=', unset the environment variable
  17. return os.Unsetenv(envString) == nil
  18. }
  19. //export go_getfullenv
  20. func go_getfullenv(threadIndex C.uintptr_t) (*C.go_string, C.size_t) {
  21. thread := phpThreads[threadIndex]
  22. env := os.Environ()
  23. goStrings := make([]C.go_string, len(env)*2)
  24. for i, envVar := range env {
  25. key, val, _ := strings.Cut(envVar, "=")
  26. goStrings[i*2] = C.go_string{C.size_t(len(key)), thread.pinString(key)}
  27. goStrings[i*2+1] = C.go_string{C.size_t(len(val)), thread.pinString(val)}
  28. }
  29. value := unsafe.SliceData(goStrings)
  30. thread.Pin(value)
  31. return value, C.size_t(len(env))
  32. }
  33. //export go_getenv
  34. func go_getenv(threadIndex C.uintptr_t, name *C.go_string) (C.bool, *C.go_string) {
  35. thread := phpThreads[threadIndex]
  36. // Create a byte slice from C string with a specified length
  37. envName := C.GoStringN(name.data, C.int(name.len))
  38. // Get the environment variable value
  39. envValue, exists := os.LookupEnv(envName)
  40. if !exists {
  41. // Environment variable does not exist
  42. return false, nil // Return 0 to indicate failure
  43. }
  44. // Convert Go string to C string
  45. value := &C.go_string{C.size_t(len(envValue)), thread.pinString(envValue)}
  46. thread.Pin(value)
  47. return true, value // Return 1 to indicate success
  48. }
  49. //export go_sapi_getenv
  50. func go_sapi_getenv(threadIndex C.uintptr_t, name *C.go_string) *C.char {
  51. envName := C.GoStringN(name.data, C.int(name.len))
  52. envValue, exists := os.LookupEnv(envName)
  53. if !exists {
  54. return nil
  55. }
  56. return phpThreads[threadIndex].pinCString(envValue)
  57. }