Files
finit/helpers.c
T
Joachim Nilsson c0356b5c7a Massive cleanup to be able to boot Debian 6.0
Update license and copyright information details in all files.
Much cleanup by moving hard coded strings/data to #defines and using more
common default values for each such #define.

finit.c:
        o Make sdown[], startx[] allocated strings by default NULL
        o This fixes the issues where the shutdown handler segfaulted
        o Add ability to handle NULL input to build_cmd() by allocating space
        o Ignore kernel cmdline "quiet" if in debug mode
        o Add support for "network" stanza in finit.conf
        o Mount -n to skip removing /etc/mtab
        o Call swapon to enable swap if enabled in /etc/fstab
        o Cleanup /tmp, /var/run and /var/lock
        o Move sig_setup() *after* mount, sig_init() otoh runs early
        o Start initctl monitor before forking off startx/getty process
        o The startx process is now the console process. Only a getty is
          started when in debug mode. Otherwise only X is started if it
          is properly setup in /etc/finit.conf
        o NOTE: Currently X evdev does not work!
        o Support for /usr/sbin/services.sh has been replaced with finit
          now instead supporting builtin run-parts for /etc/finit.d/

helpers.c:
        o Bug fixes in run_parts() and also added chdir(oldpwd) at bottom.
        o New functions:
          - getuser() similar to getgroup()
          - cls() clear screen, only runs when not in debug mode
          - set_procname() used to set name "console" on console process
          - set_hostname() encapsulates /etc/hostname and sethostname()

signal.c:
        o Split sig_setup() in two: sig_init() and sig_setup()
          The former to be called as soon as possible, while latter is
          supposed to run when the base filesystem is properly up.
        o Remove hard coded distribution specific progress bar write()
        o Add debug messages to do_shutdown()
        o Remove any lingering sync files in sig_setup()

initctl.c:
        o Add debug messages and a new default: case to catch stray runlevels

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2012-09-19 18:06:12 +02:00

278 lines
5.4 KiB
C

/* Misc. utility functions and C-library extensions to simplify finit system setup.
*
* Copyright (c) 2008-2010 Claudio Matsuoka <cmatsuoka@gmail.com>
* Copyright (c) 2008-2012 Joachim Nilsson <troglobit@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <string.h>
#include <limits.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/prctl.h>
#include <sys/socket.h>
#include <net/if.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#ifdef BUILTIN_RUNPARTS
#include <dirent.h>
#include <stdarg.h>
#include <sys/wait.h>
#endif
#include <grp.h>
#include <pwd.h>
#include "finit.h"
#include "helpers.h"
/*
* Helpers to replace system() calls
*/
int makepath(char *p)
{
char *x, path[PATH_MAX];
int ret;
x = path;
do {
do { *x++ = *p++; } while (*p && *p != '/');
*x = 0;
ret = mkdir(path, 0777);
} while (*p && (*p != '/' || *(p + 1))); /* ignore trailing slash */
return ret;
}
void ifconfig(char *name, char *inet, char *mask, int up)
{
struct ifreq ifr;
struct sockaddr_in *a = (struct sockaddr_in *)&ifr.ifr_addr;
int sock;
if ((sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP)) < 0)
return;
memset(&ifr, 0, sizeof (ifr));
strncpy(ifr.ifr_name, name, IFNAMSIZ);
a->sin_family = AF_INET;
if (up) {
inet_aton(inet, &a->sin_addr);
ioctl(sock, SIOCSIFADDR, &ifr);
inet_aton(mask, &a->sin_addr);
ioctl(sock, SIOCSIFNETMASK, &ifr);
}
ioctl(sock, SIOCGIFFLAGS, &ifr);
if (up)
ifr.ifr_flags |= IFF_UP;
else
ifr.ifr_flags &= ~IFF_UP;
ioctl(sock, SIOCSIFFLAGS, &ifr);
close(sock);
}
#define BUF_SIZE 4096
void copyfile(char *src, char *dst, int size)
{
char buffer[BUF_SIZE];
int s, d, n;
/* Size == 0 means copy entire file */
if (size == 0)
size = INT_MAX;
if ((s = open(src, O_RDONLY)) >= 0) {
if ((d = open(dst, O_WRONLY | O_CREAT, 0644)) >= 0) {
do {
int csize = size > BUF_SIZE ? BUF_SIZE : size;
if ((n = read(s, buffer, csize)) > 0)
write(d, buffer, n);
size -= csize;
} while (size > 0 && n == BUF_SIZE);
close(d);
}
close(s);
}
}
#ifdef BUILTIN_RUNPARTS
#define NUM_SCRIPTS 128 /* ought to be enough for anyone */
#define NUM_ARGS 16
static int cmp(const void *s1, const void *s2)
{
return strcmp(*(char **)s1, *(char **)s2);
}
int run_parts(char *dir, ...)
{
DIR *d;
struct dirent *e;
struct stat st;
char *oldpwd = NULL;
char *ent[NUM_SCRIPTS];
int i, num = 0, argnum = 1;
char *args[NUM_ARGS];
va_list ap;
oldpwd = getcwd (NULL, 0);
if (chdir(dir)) {
if (oldpwd) free(oldpwd);
return -1;
}
if ((d = opendir(dir)) == NULL) {
if (oldpwd) free(oldpwd);
return -1;
}
va_start(ap, dir);
while (argnum < NUM_ARGS && (args[argnum++] = va_arg(ap, char *)));
va_end(ap);
while ((e = readdir(d))) {
if (e->d_type == DT_REG && stat(e->d_name, &st) == 0) {
_d("Found %s/%s ...", dir, e->d_name);
if (st.st_mode & S_IXUSR) {
ent[num++] = strdup(e->d_name);
if (num >= NUM_SCRIPTS)
break;
}
}
}
closedir(d);
if (num == 0) {
if (oldpwd) free(oldpwd);
return 0;
}
qsort(ent, num, sizeof(char *), cmp);
for (i = 0; i < num; i++) {
pid_t pid = 0;
int status;
args[0] = ent[i];
args[1] = NULL;
pid = fork();
if (!pid) {
_d("Calling %s ...", ent[i]);
execv(ent[i], args);
exit(0);
}
waitpid(pid, &status, 0);
free(ent[i]);
}
chdir(oldpwd);
free(oldpwd);
return 0;
}
#endif /* BUILTIN_RUNPARTS */
int getuser(char *s)
{
struct passwd *usr;
if ((usr = getpwnam(s)) == NULL)
return -1;
return usr->pw_uid;
}
int getgroup(char *s)
{
struct group *grp;
if ((grp = getgrnam(s)) == NULL)
return -1;
return grp->gr_gid;
}
/*
* Other convenience functions
*/
void cls(void)
{
static const char cls[] = "\e[2J\e[1;1H";
if (!debug)
fprintf (stderr, "%s", cls);
}
void chomp(char *s)
{
char *x;
if ((x = strchr((s), 0x0a)) != NULL)
*x = 0;
}
void set_procname(char *args[], char *name)
{
size_t len = strlen(args[0]) + 1; /* Include terminating '\0' */
prctl(PR_SET_NAME, name, 0, 0, 0);
memset(args[0], 0, len);
strncpy(args[0], name, len);
}
void set_hostname(char *hostname)
{
FILE *fp;
_d("Set hostname: %s", hostname);
if ((fp = fopen("/etc/hostname", "r")) != NULL) {
fgets(hostname, HOSTNAME_SIZE, fp);
chomp(hostname);
fclose(fp);
}
sethostname(hostname, strlen(hostname));
}
/**
* Local Variables:
* version-control: t
* indent-tabs-mode: t
* c-file-style: "linux"
* End:
*/