mirror of
https://github.com/samsonjs/csc360-a1-shell.git
synced 2026-04-27 14:57:43 +00:00
[c] Format code
This commit is contained in:
parent
94ca5e6024
commit
5a9cf1a0ab
10 changed files with 519 additions and 582 deletions
175
c/builtins.c
175
c/builtins.c
|
|
@ -20,124 +20,103 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "builtins.h"
|
#include "builtins.h"
|
||||||
#include "main.h"
|
|
||||||
#include "exec.h"
|
#include "exec.h"
|
||||||
#include "jobs.h"
|
#include "jobs.h"
|
||||||
|
#include "main.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
int builtin_bg ( int argc, char **argv )
|
int builtin_bg(int argc, char **argv) {
|
||||||
{
|
if (argc < 2) {
|
||||||
if ( argc < 2 )
|
queue_message("bg: usage 'bg <command>'");
|
||||||
{
|
queue_message(" runs <command> in the background");
|
||||||
queue_message ("bg: usage 'bg <command>'");
|
return -1;
|
||||||
queue_message (" runs <command> in the background");
|
}
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
pid_t pid = exec_command (&argv[1], 1); /* &argv[1] skips 'bg' */
|
pid_t pid = exec_command(&argv[1], 1); /* &argv[1] skips 'bg' */
|
||||||
if (pid > 0)
|
if (pid > 0) {
|
||||||
{
|
job j = add_job(pid, &argv[1]);
|
||||||
job j = add_job (pid, &argv[1]);
|
|
||||||
|
|
||||||
char *message = (char *)myxmalloc (MSGLEN);
|
char *message = (char *)myxmalloc(MSGLEN);
|
||||||
snprintf (message, MSGLEN,
|
snprintf(message, MSGLEN, "Running job " YELLOW "%i" WHITE " (pid %i) in background" CLEAR, j->id, pid);
|
||||||
"Running job " YELLOW "%i" WHITE " (pid %i) in background" CLEAR,
|
queue_message(message);
|
||||||
j->id, pid);
|
free(message);
|
||||||
queue_message (message);
|
}
|
||||||
free (message);
|
return pid;
|
||||||
}
|
|
||||||
return pid;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int builtin_bgkill ( int argc, char **argv )
|
int builtin_bgkill(int argc, char **argv) {
|
||||||
{
|
if (argc != 2) {
|
||||||
if ( argc != 2 )
|
queue_message("bgkill: usage 'bgkill <job number>'");
|
||||||
{
|
queue_message(" type 'bglist' to see running jobs");
|
||||||
queue_message ("bgkill: usage 'bgkill <job number>'");
|
return -1;
|
||||||
queue_message (" type 'bglist' to see running jobs");
|
}
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int job_id = atoi (argv[1]);
|
int job_id = atoi(argv[1]);
|
||||||
job j = job_with_id (job_id);
|
job j = job_with_id(job_id);
|
||||||
if (!j)
|
if (!j) {
|
||||||
{
|
queue_message(YELLOW "Invalid job number");
|
||||||
queue_message (YELLOW "Invalid job number");
|
queue_message("(type 'bglist' to see running jobs)");
|
||||||
queue_message ("(type 'bglist' to see running jobs)");
|
return -1;
|
||||||
return -1;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
kill (j->pid, SIGTERM);
|
kill(j->pid, SIGTERM);
|
||||||
/*delete_job (j);*/
|
/*delete_job (j);*/
|
||||||
/* queue_message ("Job killed");*/
|
/* queue_message ("Job killed");*/
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int builtin_bglist ( void )
|
int builtin_bglist(void) {
|
||||||
{
|
int num_jobs;
|
||||||
int num_jobs;
|
if (!(num_jobs = get_num_jobs()))
|
||||||
if ( !(num_jobs = get_num_jobs()) )
|
return 0;
|
||||||
return 0;
|
|
||||||
|
|
||||||
job j;
|
job j;
|
||||||
char *message = (char *)myxmalloc (MSGLEN);
|
char *message = (char *)myxmalloc(MSGLEN);
|
||||||
for (j = get_job_list(); j; j = j->next)
|
for (j = get_job_list(); j; j = j->next) {
|
||||||
{
|
snprintf(message, MSGLEN, YELLOW "%i" WHITE ": (pid %i)" YELLOW " %s" CLEAR, j->id, j->pid, j->cmdline);
|
||||||
snprintf (message, MSGLEN,
|
queue_message(message);
|
||||||
YELLOW "%i" WHITE ": (pid %i)" YELLOW " %s" CLEAR,
|
}
|
||||||
j->id, j->pid, j->cmdline);
|
snprintf(message, MSGLEN, GREEN "Total: %i background job(s) running" CLEAR, num_jobs);
|
||||||
queue_message (message);
|
queue_message(message);
|
||||||
}
|
free(message);
|
||||||
snprintf (message, MSGLEN,
|
return num_jobs;
|
||||||
GREEN "Total: %i background job(s) running" CLEAR, num_jobs);
|
|
||||||
queue_message (message);
|
|
||||||
free (message);
|
|
||||||
return num_jobs;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int builtin_cd ( int argc, char **argv )
|
int builtin_cd(int argc, char **argv) {
|
||||||
{
|
static char *lastdir = NULL;
|
||||||
static char *lastdir = NULL;
|
char *dir, *pwd = getcwd(NULL, 0);
|
||||||
char *dir, *pwd = getcwd(NULL, 0);
|
|
||||||
|
|
||||||
if (!lastdir) /* initialize */
|
if (!lastdir) /* initialize */
|
||||||
lastdir = pwd;
|
lastdir = pwd;
|
||||||
|
|
||||||
if ( argc < 2 ) /* cd w/ no args acts like cd $HOME */
|
if (argc < 2) /* cd w/ no args acts like cd $HOME */
|
||||||
dir = getenv("HOME");
|
dir = getenv("HOME");
|
||||||
else
|
else {
|
||||||
{
|
if (!strncmp(argv[1], "-", 1))
|
||||||
if ( !strncmp(argv[1], "-", 1) )
|
dir = lastdir; /* cd - changes to previous dir */
|
||||||
dir = lastdir; /* cd - changes to previous dir */
|
else
|
||||||
else
|
dir = argv[1];
|
||||||
dir = argv[1];
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if ( chdir (dir) < 0 )
|
if (chdir(dir) < 0) { /* error */
|
||||||
{ /* error */
|
size_t len = strlen(dir);
|
||||||
size_t len = strlen (dir);
|
char *message = (char *)myxmalloc(len + MSGLEN);
|
||||||
char *message = (char *)myxmalloc (len + MSGLEN);
|
(void)snprintf(message, len + MSGLEN, RED "cd: %s: %s" CLEAR, strerror(errno), dir);
|
||||||
(void) snprintf (message, len + MSGLEN,
|
queue_message(message);
|
||||||
RED "cd: %s: %s" CLEAR, strerror (errno), dir);
|
free(message);
|
||||||
queue_message (message);
|
return -1;
|
||||||
free (message);
|
}
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* save the last dir for cd -, if it's different */
|
/* save the last dir for cd -, if it's different */
|
||||||
if ( strcmp(pwd, dir) )
|
if (strcmp(pwd, dir))
|
||||||
lastdir = pwd;
|
lastdir = pwd;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void builtin_clear ( void )
|
void builtin_clear(void) { printf("\033[2J"); }
|
||||||
{
|
|
||||||
printf ("\033[2J");
|
|
||||||
}
|
|
||||||
|
|
||||||
void builtin_pwd ( void )
|
void builtin_pwd(void) {
|
||||||
{
|
char *pwd = getcwd(NULL, 0);
|
||||||
char *pwd = getcwd(NULL, 0);
|
queue_message(pwd);
|
||||||
queue_message (pwd);
|
xfree(pwd);
|
||||||
xfree (pwd);
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
12
c/builtins.h
12
c/builtins.h
|
|
@ -9,9 +9,9 @@
|
||||||
* $Id: builtins.h 184 2006-01-29 08:53:30Z sjs $
|
* $Id: builtins.h 184 2006-01-29 08:53:30Z sjs $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int builtin_bg ( int argc, char **argv );
|
int builtin_bg(int argc, char **argv);
|
||||||
int builtin_bgkill ( int argc, char **argv );
|
int builtin_bgkill(int argc, char **argv);
|
||||||
int builtin_bglist ( void );
|
int builtin_bglist(void);
|
||||||
int builtin_cd ( int argc, char **argv );
|
int builtin_cd(int argc, char **argv);
|
||||||
void builtin_clear ( void );
|
void builtin_clear(void);
|
||||||
void builtin_pwd ( void );
|
void builtin_pwd(void);
|
||||||
|
|
|
||||||
129
c/exec.c
129
c/exec.c
|
|
@ -12,87 +12,76 @@
|
||||||
/*#define _GNU_SOURCE*/
|
/*#define _GNU_SOURCE*/
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/types.h> /* waitpid */
|
#include <sys/types.h> /* waitpid */
|
||||||
#include <sys/wait.h> /* waitpid */
|
#include <sys/wait.h> /* waitpid */
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "exec.h"
|
#include "exec.h"
|
||||||
#include "utils.h"
|
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
char *is_executable ( char *file )
|
char *is_executable(char *file) {
|
||||||
{
|
if (strchr(file, '/')) { /* process absolute and relative paths directly */
|
||||||
if ( strchr (file, '/') )
|
if (access(file, X_OK) == 0)
|
||||||
{ /* process absolute and relative paths directly */
|
return strdup(file);
|
||||||
if ( access (file, X_OK) == 0 )
|
else
|
||||||
return strdup (file);
|
return NULL;
|
||||||
else
|
}
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *path = strdup ( getenv ("PATH") );
|
char *path = strdup(getenv("PATH"));
|
||||||
int file_len = strlen (file);
|
int file_len = strlen(file);
|
||||||
char *dir = strtok (path, ":");
|
char *dir = strtok(path, ":");
|
||||||
char *filename = NULL;
|
char *filename = NULL;
|
||||||
while ( dir )
|
while (dir) {
|
||||||
{
|
filename = (char *)myxmalloc(strlen(dir) + file_len + 2);
|
||||||
filename = (char *)myxmalloc (strlen (dir) + file_len + 2);
|
sprintf(filename, "%s/%s", dir, file);
|
||||||
sprintf (filename, "%s/%s", dir, file);
|
if (access(filename, X_OK) == 0)
|
||||||
if ( access (filename, X_OK) == 0 )
|
break;
|
||||||
break;
|
free(filename);
|
||||||
free (filename);
|
filename = NULL;
|
||||||
filename = NULL;
|
dir = strtok(NULL, ":");
|
||||||
dir = strtok (NULL, ":");
|
}
|
||||||
}
|
xfree(path);
|
||||||
xfree (path);
|
return filename;
|
||||||
return filename;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pid_t exec_command ( char **argv, int background )
|
pid_t exec_command(char **argv, int background) {
|
||||||
{
|
int status;
|
||||||
int status;
|
pid_t pid;
|
||||||
pid_t pid;
|
char *filename;
|
||||||
char *filename;
|
|
||||||
|
|
||||||
if ( !(filename = is_executable (argv[0])) )
|
if (!(filename = is_executable(argv[0]))) { /* error, not executable */
|
||||||
{ /* error, not executable */
|
char *msg = (char *)myxmalloc(MSGLEN);
|
||||||
char *msg = (char *)myxmalloc (MSGLEN);
|
sprintf(msg, RED "%s: %s" CLEAR, argv[0], strerror(errno));
|
||||||
sprintf (msg, RED "%s: %s" CLEAR, argv[0], strerror (errno));
|
queue_message(msg);
|
||||||
queue_message (msg);
|
free(msg);
|
||||||
free (msg);
|
return -1;
|
||||||
return -1;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if ( (pid = fork()) > 0 )
|
if ((pid = fork()) > 0) { /* parent */
|
||||||
{ /* parent */
|
if (background)
|
||||||
if ( background )
|
waitpid(pid, &status, WNOHANG);
|
||||||
waitpid (pid, &status, WNOHANG);
|
else
|
||||||
else
|
waitpid(pid, &status, 0);
|
||||||
waitpid (pid, &status, 0);
|
} else if (pid == 0) { /* child */
|
||||||
}
|
/* kludge, briefly wait for the job to be created so that if the
|
||||||
else if ( pid == 0 )
|
* command exits quickly, the job is found and removed. otherwise there
|
||||||
{ /* child */
|
* are zombie jobs erroneously lying around. note, this isn't guaranteed
|
||||||
/* kludge, briefly wait for the job to be created so that if the
|
* to work, it just seems to be enough time in tests here.
|
||||||
* command exits quickly, the job is found and removed. otherwise there
|
*/
|
||||||
* are zombie jobs erroneously lying around. note, this isn't guaranteed
|
usleep(100);
|
||||||
* to work, it just seems to be enough time in tests here.
|
execv(filename, argv);
|
||||||
*/
|
|
||||||
usleep (100);
|
|
||||||
execv (filename, argv);
|
|
||||||
|
|
||||||
/* if we get here there was an error, display it */
|
/* if we get here there was an error, display it */
|
||||||
printf (RED "\nCannot execute '%s' (%s)\n" CLEAR, argv[0],
|
printf(RED "\nCannot execute '%s' (%s)\n" CLEAR, argv[0], strerror(errno));
|
||||||
strerror(errno));
|
free(filename);
|
||||||
free (filename);
|
_exit(EXIT_FAILURE);
|
||||||
_exit (EXIT_FAILURE);
|
} else { /* error, pid < 0 */
|
||||||
}
|
queue_message(RED "Unable to fork(), uh oh..." CLEAR);
|
||||||
else
|
}
|
||||||
{ /* error, pid < 0 */
|
free(filename);
|
||||||
queue_message (RED "Unable to fork(), uh oh..." CLEAR);
|
return pid;
|
||||||
}
|
|
||||||
free (filename);
|
|
||||||
return pid;
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
2
c/exec.h
2
c/exec.h
|
|
@ -11,4 +11,4 @@
|
||||||
|
|
||||||
/* execute the command argv[0], with arg list argv[], background can be
|
/* execute the command argv[0], with arg list argv[], background can be
|
||||||
* non-zero to run the task in the background under our limited job control */
|
* non-zero to run the task in the background under our limited job control */
|
||||||
pid_t exec_command ( char **argv, int background );
|
pid_t exec_command(char **argv, int background);
|
||||||
|
|
|
||||||
180
c/jobs.c
180
c/jobs.c
|
|
@ -24,120 +24,102 @@ static job job_list_head = NULL;
|
||||||
static int num_jobs = 0;
|
static int num_jobs = 0;
|
||||||
static int next_id = 1;
|
static int next_id = 1;
|
||||||
|
|
||||||
static int get_next_id ( void )
|
static int get_next_id(void) {
|
||||||
{
|
while (job_with_id(next_id))
|
||||||
while ( job_with_id (next_id) )
|
next_id++;
|
||||||
next_id++;
|
return next_id++;
|
||||||
return next_id++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
job add_job ( pid_t pid, char **argv )
|
job add_job(pid_t pid, char **argv) {
|
||||||
{
|
job i, j = (job)myxmalloc(sizeof(struct job));
|
||||||
job i, j = (job)myxmalloc (sizeof (struct job));
|
j->id = get_next_id();
|
||||||
j->id = get_next_id();
|
j->pid = pid;
|
||||||
j->pid = pid;
|
j->cmdline = array_cat(argv);
|
||||||
j->cmdline = array_cat (argv);
|
if (DEBUG)
|
||||||
if (DEBUG)
|
printf("DEBUG: cmdline='%s'\n", j->cmdline);
|
||||||
printf("DEBUG: cmdline='%s'\n", j->cmdline);
|
j->next = NULL;
|
||||||
j->next = NULL;
|
j->prev = NULL;
|
||||||
j->prev = NULL;
|
|
||||||
|
|
||||||
for (i = job_list_head; i && i->next; i = i->next)
|
for (i = job_list_head; i && i->next; i = i->next) { /* insert jobs in job_id order */
|
||||||
{ /* insert jobs in job_id order */
|
if (i->id > j->id) { /* insert BEFORE i */
|
||||||
if ( i->id > j->id )
|
if (DEBUG)
|
||||||
{ /* insert BEFORE i */
|
printf("DEBUG: i=%i, i->next=%i, i->prev=%p\n", i->id, i->next->id, i->prev);
|
||||||
if (DEBUG)
|
j->next = i;
|
||||||
printf("DEBUG: i=%i, i->next=%i, i->prev=%p\n", i->id, i->next->id, i->prev);
|
j->prev = i->prev;
|
||||||
j->next = i;
|
if (i->prev)
|
||||||
j->prev = i->prev;
|
i->prev->next = j;
|
||||||
if (i->prev)
|
i->prev = j;
|
||||||
i->prev->next = j;
|
|
||||||
i->prev = j;
|
|
||||||
|
|
||||||
if ( job_list_head == i )
|
if (job_list_head == i)
|
||||||
job_list_head = j;
|
job_list_head = j;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( i == NULL ) /* empty list */
|
if (i == NULL) /* empty list */
|
||||||
{
|
{
|
||||||
if (DEBUG)
|
if (DEBUG)
|
||||||
printf("DEBUG: i=%p, job_list_head=%p\n", i, job_list_head);
|
printf("DEBUG: i=%p, job_list_head=%p\n", i, job_list_head);
|
||||||
job_list_head = j;
|
job_list_head = j;
|
||||||
}
|
} else if (!i->next) /* at the end, i->next == NULL */
|
||||||
else if ( !i->next ) /* at the end, i->next == NULL */
|
{ /* at this point, append the new job to the end of the list */
|
||||||
{ /* at this point, append the new job to the end of the list */
|
if (DEBUG)
|
||||||
if (DEBUG)
|
printf("DEBUG: i=%i\n", i->id);
|
||||||
printf("DEBUG: i=%i\n", i->id);
|
i->next = j;
|
||||||
i->next = j;
|
j->prev = i;
|
||||||
j->prev = i;
|
}
|
||||||
}
|
if (DEBUG)
|
||||||
if (DEBUG)
|
printf("DEBUG: job added: (%i,%i)\n", j->id, j->pid);
|
||||||
printf("DEBUG: job added: (%i,%i)\n", j->id, j->pid);
|
num_jobs++;
|
||||||
num_jobs++;
|
return j;
|
||||||
return j;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void delete_job ( job j )
|
void delete_job(job j) {
|
||||||
{
|
next_id = MIN(next_id, j->id); /* prefer the lower id */
|
||||||
next_id = MIN(next_id, j->id); /* prefer the lower id */
|
|
||||||
|
|
||||||
if ( j == job_list_head )
|
if (j == job_list_head) {
|
||||||
{
|
if (j->next)
|
||||||
if (j->next)
|
job_list_head = j->next;
|
||||||
job_list_head = j->next;
|
else
|
||||||
else
|
job_list_head = NULL;
|
||||||
job_list_head = NULL;
|
}
|
||||||
}
|
if (j->prev)
|
||||||
if (j->prev)
|
j->prev->next = j->next;
|
||||||
j->prev->next = j->next;
|
if (j->next)
|
||||||
if (j->next)
|
j->next->prev = j->prev;
|
||||||
j->next->prev = j->prev;
|
|
||||||
|
|
||||||
if (DEBUG)
|
if (DEBUG)
|
||||||
printf("DEBUG: str=%p\n", j->cmdline);
|
printf("DEBUG: str=%p\n", j->cmdline);
|
||||||
xfree (j->cmdline);
|
xfree(j->cmdline);
|
||||||
xfree (j);
|
xfree(j);
|
||||||
num_jobs--;
|
num_jobs--;
|
||||||
}
|
}
|
||||||
|
|
||||||
void free_job_list ( void )
|
void free_job_list(void) {
|
||||||
{
|
while (job_list_head)
|
||||||
while ( job_list_head )
|
delete_job(job_list_head);
|
||||||
delete_job ( job_list_head );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
job job_with_id ( int job_id )
|
job job_with_id(int job_id) {
|
||||||
{
|
job j;
|
||||||
job j;
|
for (j = job_list_head; j; j = j->next) {
|
||||||
for (j = job_list_head; j; j = j->next)
|
/* printf("DEBUG: id=%i, j=%p:%i:%i\n", job_id, j, j->id, j->pid); */
|
||||||
{
|
if (j->id == job_id)
|
||||||
/* printf("DEBUG: id=%i, j=%p:%i:%i\n", job_id, j, j->id, j->pid); */
|
return j;
|
||||||
if (j->id == job_id)
|
}
|
||||||
return j;
|
return NULL;
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
job job_with_pid ( pid_t pid )
|
job job_with_pid(pid_t pid) {
|
||||||
{
|
job j;
|
||||||
job j;
|
for (j = job_list_head; j; j = j->next) {
|
||||||
for (j = job_list_head; j; j = j->next)
|
printf("DEBUG: pid=%i, j=%p:%i:%i\n", pid, j, j->id, j->pid);
|
||||||
{
|
if (j->pid == pid)
|
||||||
printf("DEBUG: pid=%i, j=%p:%i:%i\n", pid, j, j->id, j->pid);
|
return j;
|
||||||
if (j->pid == pid)
|
}
|
||||||
return j;
|
return NULL;
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
job get_job_list ( void )
|
job get_job_list(void) { return job_list_head; }
|
||||||
{
|
|
||||||
return job_list_head;
|
|
||||||
}
|
|
||||||
|
|
||||||
int get_num_jobs ( void )
|
int get_num_jobs(void) { return num_jobs; }
|
||||||
{
|
|
||||||
return num_jobs;
|
|
||||||
}
|
|
||||||
|
|
|
||||||
24
c/jobs.h
24
c/jobs.h
|
|
@ -12,18 +12,18 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
struct job {
|
struct job {
|
||||||
int id;
|
int id;
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
char *cmdline;
|
char *cmdline;
|
||||||
struct job *next;
|
struct job *next;
|
||||||
struct job *prev;
|
struct job *prev;
|
||||||
};
|
};
|
||||||
typedef struct job *job;
|
typedef struct job *job;
|
||||||
|
|
||||||
job add_job ( pid_t pid, char **argv );
|
job add_job(pid_t pid, char **argv);
|
||||||
void delete_job ( job j );
|
void delete_job(job j);
|
||||||
void free_job_list ( void );
|
void free_job_list(void);
|
||||||
int get_num_jobs ( void );
|
int get_num_jobs(void);
|
||||||
job get_job_list ( void );
|
job get_job_list(void);
|
||||||
job job_with_id ( int job_id );
|
job job_with_id(int job_id);
|
||||||
job job_with_pid ( pid_t pid );
|
job job_with_pid(pid_t pid);
|
||||||
|
|
|
||||||
429
c/main.c
429
c/main.c
|
|
@ -11,271 +11,262 @@
|
||||||
|
|
||||||
/*#define _GNU_SOURCE*/
|
/*#define _GNU_SOURCE*/
|
||||||
|
|
||||||
#include <assert.h>
|
/* This must be included before readline or FILE won't be defined. */
|
||||||
#include <signal.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <readline/history.h>
|
||||||
|
#include <readline/readline.h>
|
||||||
|
#include <signal.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#include <readline/readline.h>
|
|
||||||
#include <readline/history.h>
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <wordexp.h>
|
#include <wordexp.h>
|
||||||
|
|
||||||
#include "utils.h"
|
|
||||||
#include "jobs.h"
|
|
||||||
#include "exec.h"
|
|
||||||
#include "builtins.h"
|
#include "builtins.h"
|
||||||
|
#include "exec.h"
|
||||||
|
#include "jobs.h"
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
#define MAX(a, b) (a) > (b) ? (a) : (b)
|
#define MAX(a, b) ((a) > (b) ? (a) : (b))
|
||||||
#define PROMPT BLUE "%s" WHITE "%% " CLEAR /* looks like this: /path/to/somewhere% */
|
|
||||||
#define INVALID_CHARS "&|;<>" /* for wordexp */
|
/* looks like this: /path/to/somewhere% */
|
||||||
|
#define PROMPT BLUE "%s" WHITE "%% " CLEAR
|
||||||
|
|
||||||
|
/* for wordexp */
|
||||||
|
#define INVALID_CHARS "&|;<>"
|
||||||
|
|
||||||
struct message {
|
struct message {
|
||||||
char *data;
|
char *data;
|
||||||
struct message *next;
|
struct message *next;
|
||||||
};
|
};
|
||||||
typedef struct message *message;
|
typedef struct message *message;
|
||||||
|
|
||||||
static message msg_queue_head = NULL; /* message queue */
|
static message msg_queue_head = NULL; /* message queue */
|
||||||
|
|
||||||
void queue_message ( char *msg )
|
/** queue messages so they don't mix with a running program's output
|
||||||
{ /* queue messages so they don't mix with a running program's output
|
* instead they're only displayed while waiting on input w/ readline
|
||||||
* instead they're only displayed while waiting on input w/ readline
|
* message m: freed in print_messages()
|
||||||
* message m: freed in print_messages()
|
*/
|
||||||
*/
|
void queue_message(char *msg) {
|
||||||
message i, m = (message)myxmalloc (sizeof (struct message));
|
message i, m = (message)myxmalloc(sizeof(struct message));
|
||||||
m->data = strdup (msg);
|
m->data = strdup(msg);
|
||||||
m->next = NULL;
|
m->next = NULL;
|
||||||
for (i = msg_queue_head; i && i->next; i = i->next)
|
for (i = msg_queue_head; i && i->next; i = i->next)
|
||||||
;
|
;
|
||||||
|
|
||||||
if (!i) /* if i is NULL, then i == msg_queue_head == NULL */
|
if (!i) /* if i is NULL, then i == msg_queue_head == NULL */
|
||||||
msg_queue_head = m;
|
msg_queue_head = m;
|
||||||
else /* queue m */
|
else /* queue m */
|
||||||
i->next = m;
|
i->next = m;
|
||||||
}
|
}
|
||||||
|
|
||||||
void free_message_queue ( void )
|
void free_message_queue(void) {
|
||||||
{
|
message m, n = msg_queue_head;
|
||||||
message m, n = msg_queue_head;
|
while ((m = n)) {
|
||||||
while ( (m = n) )
|
n = m->next;
|
||||||
{
|
xfree(m->data);
|
||||||
n = m->next;
|
free(m);
|
||||||
xfree (m->data);
|
}
|
||||||
free (m);
|
msg_queue_head = NULL;
|
||||||
}
|
|
||||||
msg_queue_head = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int print_messages ( void )
|
int print_messages(void) {
|
||||||
{
|
if (!msg_queue_head)
|
||||||
if (!msg_queue_head)
|
return 0;
|
||||||
return 0;
|
|
||||||
|
|
||||||
/* there must be an easier way to interrupt readline... */
|
/* there must be an easier way to interrupt readline... */
|
||||||
char *old = rl_line_buffer;
|
char *old = rl_line_buffer;
|
||||||
rl_line_buffer = strdup ("");
|
rl_line_buffer = strdup("");
|
||||||
rl_save_prompt();
|
rl_save_prompt();
|
||||||
rl_clear_message();
|
rl_clear_message();
|
||||||
|
|
||||||
message m;
|
message m;
|
||||||
for (m = msg_queue_head; m; m = m->next)
|
for (m = msg_queue_head; m; m = m->next)
|
||||||
printf (WHITE "%s\n" CLEAR, m->data);
|
printf(WHITE "%s\n" CLEAR, m->data);
|
||||||
free_message_queue ();
|
free_message_queue();
|
||||||
|
|
||||||
xfree (rl_line_buffer);
|
xfree(rl_line_buffer);
|
||||||
rl_line_buffer = old;
|
rl_line_buffer = old;
|
||||||
rl_restore_prompt();
|
rl_restore_prompt();
|
||||||
rl_forced_update_display();
|
rl_forced_update_display();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *strsignal ( int status )
|
/* like strerror for waitpid */
|
||||||
{ /* like strerror for waitpid */
|
char *strsignal(int status) {
|
||||||
char *str = (char *)myxmalloc (MSGLEN);
|
char *str = (char *)myxmalloc(MSGLEN);
|
||||||
if ( WIFEXITED(status) )
|
if (WIFEXITED(status)) {
|
||||||
{
|
if (WEXITSTATUS(status)) /* non-zero exit status */
|
||||||
if ( WEXITSTATUS(status) ) /* non-zero exit status */
|
sprintf(str, RED "exit %i", WEXITSTATUS(status));
|
||||||
sprintf (str, RED "exit %i", WEXITSTATUS(status));
|
else /* clean exit */
|
||||||
else /* clean exit */
|
sprintf(str, GREEN "done");
|
||||||
sprintf (str, GREEN "done");
|
}
|
||||||
}
|
if (WIFSIGNALED(status)) {
|
||||||
if ( WIFSIGNALED(status) )
|
switch (WTERMSIG(status)) {
|
||||||
{
|
case SIGTERM:
|
||||||
switch ( WTERMSIG(status) )
|
sprintf(str, RED "terminated");
|
||||||
{
|
break;
|
||||||
case SIGTERM:
|
|
||||||
sprintf (str, RED "terminated");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SIGKILL:
|
case SIGKILL:
|
||||||
sprintf (str, RED "killed");
|
sprintf(str, RED "killed");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SIGPIPE:
|
case SIGPIPE:
|
||||||
sprintf (str, RED "broken pipe");
|
sprintf(str, RED "broken pipe");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SIGSEGV:
|
case SIGSEGV:
|
||||||
sprintf (str, RED "segmentation fault");
|
sprintf(str, RED "segmentation fault");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SIGABRT:
|
case SIGABRT:
|
||||||
sprintf (str, RED "aborted");
|
sprintf(str, RED "aborted");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
sprintf (str, RED "signal %i", WTERMSIG(status));
|
sprintf(str, RED "signal %i", WTERMSIG(status));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
void child_state_changed ( int signum )
|
/* handler for SIGCHLD when a child's state changes */
|
||||||
{ /* handler for SIGCHLD when a child's state changes */
|
void child_state_changed(int signum) {
|
||||||
int status;
|
int status;
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
|
|
||||||
/* linux resets the sighandler after each call */
|
/* linux resets the sighandler after each call */
|
||||||
signal (SIGCHLD, child_state_changed);
|
signal(SIGCHLD, child_state_changed);
|
||||||
|
|
||||||
pid = waitpid (-1, &status, WNOHANG);
|
pid = waitpid(-1, &status, WNOHANG);
|
||||||
job j = job_with_pid (pid);
|
job j = job_with_pid(pid);
|
||||||
if (j)
|
if (j) {
|
||||||
{
|
char *strstatus = strsignal(status);
|
||||||
char *strstatus = strsignal (status);
|
/* alert the user of the termination, and delete the job */
|
||||||
/* alert the user of the termination, and delete the job */
|
size_t len = strlen(j->cmdline);
|
||||||
size_t len = strlen (j->cmdline);
|
char *msg = (char *)myxmalloc(len + MSGLEN);
|
||||||
char *msg = (char *)myxmalloc (len + MSGLEN);
|
snprintf(msg, len + MSGLEN, YELLOW "%i" WHITE ": (pid %i) %s" YELLOW ": %s" CLEAR, j->id, j->pid, strstatus, j->cmdline);
|
||||||
snprintf (msg, len + MSGLEN,
|
queue_message(msg);
|
||||||
YELLOW "%i" WHITE ": (pid %i) %s" YELLOW ": %s" CLEAR,
|
xfree(msg);
|
||||||
j->id, j->pid, strstatus, j->cmdline);
|
xfree(strstatus);
|
||||||
queue_message (msg);
|
delete_job(j);
|
||||||
xfree (msg);
|
}
|
||||||
xfree (strstatus);
|
|
||||||
delete_job (j);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
char *get_prompt ( void )
|
/* display the pwd in the prompt */
|
||||||
{ /* display the pwd in the prompt */
|
char *get_prompt(void) {
|
||||||
char *pwd, *prompt;
|
char *pwd, *prompt;
|
||||||
|
|
||||||
pwd = getcwd(NULL, 0);
|
pwd = getcwd(NULL, 0);
|
||||||
size_t len = strlen (pwd) + strlen (PROMPT);
|
size_t len = strlen(pwd) + strlen(PROMPT);
|
||||||
prompt = (char *)myxmalloc (len);
|
prompt = (char *)myxmalloc(len);
|
||||||
snprintf (prompt, len, PROMPT, pwd);
|
snprintf(prompt, len, PROMPT, pwd);
|
||||||
xfree (pwd);
|
xfree(pwd);
|
||||||
return prompt;
|
return prompt;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cmd_matches ( char *trigger, char *cmd )
|
int cmd_matches(char *trigger, char *cmd) { return !strcmp(trigger, cmd); }
|
||||||
{
|
|
||||||
return !strcmp (trigger, cmd);
|
int handle_wordexp_result(int result, char *cmd) {
|
||||||
|
switch (result) {
|
||||||
|
case WRDE_BADCHAR:
|
||||||
|
/* gcc chokes if the int decl is first, lame */
|
||||||
|
;
|
||||||
|
int invalid_char = strcspn(cmd, INVALID_CHARS);
|
||||||
|
char *msg = (char *)myxmalloc(strlen(cmd) + MSGLEN);
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < invalid_char; i++)
|
||||||
|
*(msg + i) = ' ';
|
||||||
|
sprintf(msg + invalid_char, RED "^ invalid character in column %i", invalid_char + 1);
|
||||||
|
queue_message(cmd);
|
||||||
|
queue_message(msg);
|
||||||
|
xfree(msg);
|
||||||
|
result = 0;
|
||||||
|
break;
|
||||||
|
case WRDE_BADVAL:
|
||||||
|
queue_message("undefined variable");
|
||||||
|
result = 0;
|
||||||
|
break;
|
||||||
|
case WRDE_CMDSUB:
|
||||||
|
queue_message("no command substitution allowed");
|
||||||
|
result = 0;
|
||||||
|
break;
|
||||||
|
case WRDE_NOSPACE:
|
||||||
|
queue_message("not enough memory");
|
||||||
|
result = 0;
|
||||||
|
break;
|
||||||
|
case WRDE_SYNTAX:
|
||||||
|
queue_message("syntax error");
|
||||||
|
result = 0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* success */
|
||||||
|
result = 1;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
int handle_wordexp_result ( int result, char *cmd )
|
void repl_start(void) {
|
||||||
{
|
for (;;) {
|
||||||
switch (result)
|
char *prompt = get_prompt();
|
||||||
{
|
char *cmd = readline(prompt);
|
||||||
case WRDE_BADCHAR:
|
xfree(prompt);
|
||||||
; /* gcc chokes if the int decl is first, lame */
|
|
||||||
int invalid_char = strcspn (cmd, INVALID_CHARS);
|
if (!cmd) /* exit if we get an EOF, which returns NULL */
|
||||||
char *msg = (char *)myxmalloc (strlen (cmd) + MSGLEN);
|
break;
|
||||||
int i;
|
|
||||||
for (i = 0; i < invalid_char; i++)
|
wordexp_t words;
|
||||||
*(msg + i) = ' ';
|
int result = wordexp(cmd, &words, WRDE_SHOWERR);
|
||||||
sprintf (msg + invalid_char,
|
if (handle_wordexp_result(result, cmd) && words.we_wordc > 0) {
|
||||||
RED "^ invalid character in column %i", invalid_char + 1);
|
if (DEBUG) {
|
||||||
queue_message (cmd);
|
int i;
|
||||||
queue_message (msg);
|
printf("DEBUG: args = { ");
|
||||||
xfree (msg);
|
for (i = 0; i < words.we_wordc; i++)
|
||||||
result = 0;
|
printf("'%s', ", words.we_wordv[i]);
|
||||||
break;
|
printf("}\n");
|
||||||
case WRDE_BADVAL:
|
}
|
||||||
queue_message ("undefined variable");
|
/* try the built-in commands */
|
||||||
result = 0;
|
if (cmd_matches("bg", words.we_wordv[0]))
|
||||||
break;
|
builtin_bg(words.we_wordc, words.we_wordv);
|
||||||
case WRDE_CMDSUB:
|
else if (cmd_matches("bgkill", words.we_wordv[0]))
|
||||||
queue_message ("no command substitution allowed");
|
builtin_bgkill(words.we_wordc, words.we_wordv);
|
||||||
result = 0;
|
else if (cmd_matches("bglist", words.we_wordv[0]))
|
||||||
break;
|
builtin_bglist();
|
||||||
case WRDE_NOSPACE:
|
else if (cmd_matches("cd", words.we_wordv[0]))
|
||||||
queue_message ("not enough memory");
|
builtin_cd(words.we_wordc, words.we_wordv);
|
||||||
result = 0;
|
else if (cmd_matches("clear", words.we_wordv[0]))
|
||||||
break;
|
builtin_clear();
|
||||||
case WRDE_SYNTAX:
|
else if (cmd_matches("pwd", words.we_wordv[0]))
|
||||||
queue_message ("syntax error");
|
builtin_pwd();
|
||||||
result = 0;
|
else if (cmd_matches("exit", words.we_wordv[0])) { /* quick clean-up, then break */
|
||||||
break;
|
wordfree(&words);
|
||||||
default:
|
free(cmd);
|
||||||
/* success */
|
break;
|
||||||
result = 1;
|
} else /* default to trying to execute the cmd line */
|
||||||
}
|
exec_command(words.we_wordv, 0);
|
||||||
return result;
|
|
||||||
|
add_history(cmd); /* add to the readline history */
|
||||||
|
wordfree(&words);
|
||||||
|
} /* if handle_wordexp_result (result) */
|
||||||
|
free(cmd);
|
||||||
|
} /* for (;;) */
|
||||||
}
|
}
|
||||||
|
|
||||||
int main ( void )
|
int main(int argc, char *argv[]) {
|
||||||
{
|
signal(SIGCHLD, child_state_changed); /* catch SIGCHLD */
|
||||||
signal (SIGCHLD, child_state_changed); /* catch SIGCHLD */
|
|
||||||
|
|
||||||
/* while waiting for input, display messasges */
|
/* while waiting for input, display messasges */
|
||||||
rl_event_hook = print_messages;
|
rl_event_hook = print_messages;
|
||||||
|
|
||||||
/* register clean-up function */
|
/* register clean-up function */
|
||||||
atexit (free_job_list);
|
atexit(free_job_list);
|
||||||
atexit (free_message_queue);
|
atexit(free_message_queue);
|
||||||
|
|
||||||
for (;;)
|
repl_start();
|
||||||
{
|
|
||||||
char *prompt = get_prompt();
|
|
||||||
char *cmd = readline (prompt);
|
|
||||||
xfree (prompt);
|
|
||||||
|
|
||||||
if (!cmd) /* exit if we get an EOF, which returns NULL */
|
return 0;
|
||||||
break;
|
|
||||||
|
|
||||||
wordexp_t words;
|
|
||||||
int result = wordexp (cmd, &words, WRDE_SHOWERR);
|
|
||||||
if ( handle_wordexp_result (result, cmd) && words.we_wordc > 0 )
|
|
||||||
{
|
|
||||||
if (DEBUG)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
printf("DEBUG: args = { ");
|
|
||||||
for (i = 0; i < words.we_wordc; i++)
|
|
||||||
printf ("'%s', ", words.we_wordv[i]);
|
|
||||||
printf ("}\n");
|
|
||||||
}
|
|
||||||
/* try the built-in commands */
|
|
||||||
if ( cmd_matches ("bg", words.we_wordv[0]) )
|
|
||||||
builtin_bg ( words.we_wordc, words.we_wordv );
|
|
||||||
else if ( cmd_matches ("bgkill", words.we_wordv[0]) )
|
|
||||||
builtin_bgkill ( words.we_wordc, words.we_wordv );
|
|
||||||
else if ( cmd_matches ("bglist", words.we_wordv[0]) )
|
|
||||||
builtin_bglist ();
|
|
||||||
else if ( cmd_matches ("cd", words.we_wordv[0]) )
|
|
||||||
builtin_cd ( words.we_wordc, words.we_wordv );
|
|
||||||
else if ( cmd_matches ("clear", words.we_wordv[0]) )
|
|
||||||
builtin_clear ();
|
|
||||||
else if ( cmd_matches ("pwd", words.we_wordv[0]) )
|
|
||||||
builtin_pwd ();
|
|
||||||
else if ( cmd_matches ("exit", words.we_wordv[0]) )
|
|
||||||
{ /* quick clean-up, then break */
|
|
||||||
wordfree (&words);
|
|
||||||
free (cmd);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else /* default to trying to execute the cmd line */
|
|
||||||
exec_command (words.we_wordv, 0);
|
|
||||||
|
|
||||||
add_history (cmd); /* add to the readline history */
|
|
||||||
wordfree (&words);
|
|
||||||
} /* if handle_wordexp_result (result) */
|
|
||||||
free (cmd);
|
|
||||||
} /* for (;;) */
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
2
c/main.h
2
c/main.h
|
|
@ -9,4 +9,4 @@
|
||||||
* $Id: main.h 183 2006-01-27 11:24:52Z sjs $
|
* $Id: main.h 183 2006-01-27 11:24:52Z sjs $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void queue_message ( char *message );
|
void queue_message(char *message);
|
||||||
|
|
|
||||||
94
c/utils.c
94
c/utils.c
|
|
@ -9,72 +9,66 @@
|
||||||
* $Id: utils.c 184 2006-01-29 08:53:30Z sjs $
|
* $Id: utils.c 184 2006-01-29 08:53:30Z sjs $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "utils.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "utils.h"
|
|
||||||
|
|
||||||
char *array_cat ( char **array )
|
char *array_cat(char **array) {
|
||||||
{
|
char *p = NULL, *str = NULL;
|
||||||
char *p = NULL, *str = NULL;
|
int i, pos = 0;
|
||||||
int i, pos = 0;
|
for (i = 0; array[i]; i++) {
|
||||||
for (i = 0; array[i]; i++)
|
if (DEBUG)
|
||||||
{
|
printf("DEBUG: array[%i]=%p:'%s'\n", i, array[i], array[i]);
|
||||||
if (DEBUG)
|
int len = strlen(array[i]);
|
||||||
printf("DEBUG: array[%i]=%p:'%s'\n", i, array[i], array[i]);
|
str = (char *)myxrealloc(str, pos + len + 1);
|
||||||
int len = strlen (array[i]);
|
p = str + pos;
|
||||||
str = (char *)myxrealloc (str, pos + len + 1);
|
memcpy(p, array[i], len);
|
||||||
p = str + pos;
|
|
||||||
memcpy (p, array[i], len);
|
|
||||||
p += len;
|
p += len;
|
||||||
*p++ = ' ';
|
*p++ = ' ';
|
||||||
pos += len + 1;
|
pos += len + 1;
|
||||||
}
|
}
|
||||||
*--p = '\0';
|
*--p = '\0';
|
||||||
if (DEBUG)
|
if (DEBUG)
|
||||||
printf("DEBUG: str=%p\n", str);
|
printf("DEBUG: str=%p\n", str);
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
void free_array ( void **array )
|
void free_array(void **array) {
|
||||||
{
|
int i = 0;
|
||||||
int i = 0;
|
|
||||||
|
|
||||||
if (!array)
|
if (!array)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
while ( array[i] )
|
while (array[i])
|
||||||
free (array[i++]);
|
free(array[i++]);
|
||||||
free (array);
|
free(array);
|
||||||
}
|
}
|
||||||
|
|
||||||
void *myxmalloc ( size_t size )
|
void *myxmalloc(size_t size) {
|
||||||
{
|
void *ptr = malloc(size);
|
||||||
void *ptr = malloc (size);
|
if (ptr)
|
||||||
if (ptr)
|
return ptr;
|
||||||
return ptr;
|
|
||||||
|
|
||||||
printf(RED "Out of memory, bailing!\n" CLEAR);
|
printf(RED "Out of memory, bailing!\n" CLEAR);
|
||||||
exit (EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void *myxrealloc( void *ptr, size_t size )
|
void *myxrealloc(void *ptr, size_t size) {
|
||||||
{
|
void *new_ptr = realloc(ptr, size);
|
||||||
void *new_ptr = realloc (ptr, size);
|
if (new_ptr)
|
||||||
if (new_ptr)
|
return new_ptr;
|
||||||
return new_ptr;
|
|
||||||
|
|
||||||
printf(RED "Out of memory, bailing!\n" CLEAR);
|
printf(RED "Out of memory, bailing!\n" CLEAR);
|
||||||
exit (EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void **array_realloc ( void **array, size_t size )
|
void **array_realloc(void **array, size_t size) {
|
||||||
{
|
void **ptr = realloc(array, size * sizeof(void *));
|
||||||
void **ptr = realloc (array, size * sizeof (void *));
|
if (ptr)
|
||||||
if (ptr)
|
return ptr;
|
||||||
return ptr;
|
|
||||||
|
|
||||||
free_array (array);
|
free_array(array);
|
||||||
printf (RED "Out of memory, bailing!\n" CLEAR);
|
printf(RED "Out of memory, bailing!\n" CLEAR);
|
||||||
exit (EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
30
c/utils.h
30
c/utils.h
|
|
@ -11,29 +11,31 @@
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#define DEBUG 1
|
#define DEBUG 1
|
||||||
#define MSGLEN 255 /* soft limit on message lengths */
|
#define MSGLEN 255 /* soft limit on message lengths */
|
||||||
|
|
||||||
/* these colours should be safe on dark and light backgrounds */
|
/* these colours should be safe on dark and light backgrounds */
|
||||||
#define BLUE "\033[1;34m"
|
#define BLUE "\033[1;34m"
|
||||||
#define GREEN "\033[1;32m"
|
#define GREEN "\033[1;32m"
|
||||||
#define YELLOW "\033[1;33m"
|
#define YELLOW "\033[1;33m"
|
||||||
#define RED "\033[1;31m"
|
#define RED "\033[1;31m"
|
||||||
#define WHITE "\033[1;37m"
|
#define WHITE "\033[1;37m"
|
||||||
#define CLEAR "\033[0;m"
|
#define CLEAR "\033[0;m"
|
||||||
|
|
||||||
/* free an array/list's elements (then the array itself) */
|
/* free an array/list's elements (then the array itself) */
|
||||||
void free_array ( void **array );
|
void free_array(void **array);
|
||||||
|
|
||||||
/* concatenate an array of strings, adding space between words */
|
/* concatenate an array of strings, adding space between words */
|
||||||
char *array_cat ( char **array );
|
char *array_cat(char **array);
|
||||||
|
|
||||||
/* safe malloc & realloc, they exit on failure */
|
/* safe malloc & realloc, they exit on failure */
|
||||||
void *myxmalloc ( size_t size );
|
void *myxmalloc(size_t size);
|
||||||
void *myxrealloc ( void *ptr, size_t size );
|
void *myxrealloc(void *ptr, size_t size);
|
||||||
|
|
||||||
#define xfree(ptr) if (ptr) free (ptr);
|
#define xfree(ptr) \
|
||||||
|
if (ptr) \
|
||||||
|
free(ptr);
|
||||||
|
|
||||||
/* this takes n_elems of the original array, in case of failure it will
|
/* this takes n_elems of the original array, in case of failure it will
|
||||||
* free_array (n_elems, array) before exiting */
|
* free_array (n_elems, array) before exiting */
|
||||||
void **array_realloc ( void **array, size_t size );
|
void **array_realloc(void **array, size_t size);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue