/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <libgen.h>
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <sys/fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include "env.h"
#include "util.h"
extern char** environ;
// Allocates a buffer and fills it with environment variables
// Sets total_size and count to appropriate values
static char* pack_env(
int *total_size) {
// first calculate a size of all envs
int size = 0;
int count = 0;
char** env = environ;
while (*env != NULL) {
size += strlen(*env) + 1;
count++;
env++;
}
size +=
sizeof (
int);
// first int - number of variables
char *data = (
char*) malloc(size);
if (data == NULL) {
return NULL;
}
*((
int*) data) = count;
char *p = data +
sizeof (
int);
env = environ;
while (*env != NULL) {
strcpy(p, *env);
p += strlen(*env) + 1;
env++;
}
*total_size = size;
return data;
}
int dumpenv(
const char* fname) {
int fd = open(fname, O_TRUNC | O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR);
if (fd == -1) {
printf(
"Failed to open");
return -1;
}
struct flock lock;
lock.l_type = F_WRLCK;
lock.l_whence = 0;
lock.l_start = SEEK_SET;
lock.l_len = 0;
if (fcntl(fd, F_SETLK, &lock) == -1) {
return (errno == EACCES || errno == EAGAIN) ? 1 : -1;
}
if (ftruncate(fd, 0) == -1) {
return -1;
}
int total_size;
char* packed_env = pack_env(&total_size);
if (packed_env == NULL) {
return -1;
}
if (writen(fd, packed_env, total_size) == -1) {
return -1;
}
close(fd);
return 0;
}
char** readenv(
const char* fname) {
int fd = open(fname, O_RDONLY);
if (fd == -1) {
return NULL;
}
struct flock lock;
lock.l_type = F_RDLCK;
lock.l_whence = 0;
lock.l_start = SEEK_SET;
lock.l_len = 0;
if (fcntl(fd, F_SETLK, &lock) == -1) {
return NULL;
// return (errno == EACCES || errno == EAGAIN) ? 1 : -1;
}
struct stat statbuf;
if (fstat(fd, &statbuf) == -1) {
return NULL;
}
int count;
if (read(fd, &count,
sizeof (count)) == -1) {
return NULL;
}
int datasize = statbuf.st_size -
sizeof (
int);
char* env_data = malloc(datasize);
if (read(fd, env_data, datasize) == -1) {
return NULL;
}
close(fd);
char**env = malloc((count + 1) *
sizeof (
char*));
char*p = env_data;
for (
int i = 0; i < count; i++) {
env[i] = p;
p += strlen(p) + 1;
}
return env;
}