Removed submodules
This commit is contained in:
@@ -0,0 +1,41 @@
|
||||
#
|
||||
# Simple Makefile
|
||||
# Mike Lam, James Madison University, August 2016
|
||||
#
|
||||
# This makefile builds a simple application that contains a main module
|
||||
# (specified by the EXE variable) and a predefined list of additional modules
|
||||
# (specified by the MODS variable). If there are any external library
|
||||
# dependencies (e.g., the math library, "-lm"), list them in the LIBS variable.
|
||||
# If there are any precompiled object files, list them in the OBJS variable.
|
||||
#
|
||||
# By default, this makefile will build the project with debugging symbols and
|
||||
# without optimization. To change this, edit or remove the "-g" and "-O0"
|
||||
# options in CFLAGS and LDFLAGS accordingly.
|
||||
#
|
||||
# By default, this makefile build the application using the GNU C compiler,
|
||||
# adhering to the C99 standard with all warnings enabled.
|
||||
|
||||
EXES=ls chmod head cut repeat env cat
|
||||
|
||||
# compiler/linker settings
|
||||
|
||||
CC=gcc
|
||||
CFLAGS=-g -O0 -Wall -Werror -std=c99 -pedantic -D_POSIX_C_SOURCE=200809L
|
||||
LDFLAGS=-O0
|
||||
|
||||
# build targets
|
||||
|
||||
all: ../bin $(EXES)
|
||||
|
||||
.c:
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $<
|
||||
mv $@ ../bin
|
||||
|
||||
../bin:
|
||||
mkdir ../bin
|
||||
|
||||
clean:
|
||||
rm -rf ../bin
|
||||
|
||||
.PHONY: all clean
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
static void usage (void) __attribute__ ((unused));
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
if (argc < 2)
|
||||
{
|
||||
int c;
|
||||
while ((c = getchar()) != EOF)
|
||||
{
|
||||
putchar(c);
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
FILE *fp = fopen(argv[1], "r");
|
||||
if (fp == NULL)
|
||||
{
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
int c;
|
||||
while ((c = fgetc(fp)) != EOF)
|
||||
{
|
||||
putchar(c);
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
usage (void)
|
||||
{
|
||||
printf ("cat, print the contents of a file\n");
|
||||
printf ("usage: cat FILE\n");
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
static void usage (void);
|
||||
|
||||
mode_t
|
||||
calculate_permission (char *arg_str)
|
||||
{
|
||||
const char perms[4] = "rwx";
|
||||
|
||||
if (strlen (arg_str) != 3)
|
||||
{
|
||||
usage ();
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
mode_t permission = 0;
|
||||
|
||||
for (size_t j = 0; j < 3; j++)
|
||||
{
|
||||
int perm = 1 << (2 - j);
|
||||
if (arg_str[j] == perms[j])
|
||||
{
|
||||
permission |= perm;
|
||||
}
|
||||
else if (arg_str[j] != '-')
|
||||
{
|
||||
usage ();
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
return permission;
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
if (argc != 5)
|
||||
{
|
||||
usage ();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
mode_t user = calculate_permission (argv[1]);
|
||||
mode_t group = calculate_permission (argv[2]);
|
||||
mode_t other = calculate_permission (argv[3]);
|
||||
|
||||
mode_t permissions = (user << 6) | (group << 3) | other;
|
||||
|
||||
if (chmod (argv[4], permissions) == -1)
|
||||
{
|
||||
perror ("Failed to chmod");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
usage (void)
|
||||
{
|
||||
printf ("chmod, changes permissions on a file\n");
|
||||
printf ("usage: chmod USR GRP OTH FILE\n\n");
|
||||
printf ("USR, GRP, and OTH must be of the rwx format,\n");
|
||||
printf ("with - indicating a permission is not allwed.\n");
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
#define _GNU_SOURCE
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
// You may assume that lines are no longer than 1024 bytes
|
||||
#define LINELEN 1024
|
||||
|
||||
static void usage (void);
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
int opt;
|
||||
char *delimitter = " ";
|
||||
long field = 1;
|
||||
|
||||
while ((opt = getopt (argc, argv, "d:f:")) != -1)
|
||||
{
|
||||
switch (opt)
|
||||
{
|
||||
case 'd':
|
||||
delimitter = optarg;
|
||||
break;
|
||||
case 'f':
|
||||
field = strtol (optarg, NULL, 10);
|
||||
break;
|
||||
default:
|
||||
printf ("./bin/cut: invalid option -- \'%c\'\n", optopt);
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
if (field < 1)
|
||||
{
|
||||
usage ();
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
FILE *file = optind < argc ? fopen (argv[optind], "r") : stdin;
|
||||
if (file == NULL)
|
||||
{
|
||||
perror ("Failed to open input file");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
char buffer[LINELEN];
|
||||
|
||||
while (fgets (buffer, sizeof (buffer), file) != NULL)
|
||||
{
|
||||
buffer[strcspn (buffer, "\n")] = '\0';
|
||||
|
||||
char *token = strtok (buffer, delimitter);
|
||||
long i = 1;
|
||||
while (i++ < field) token = strtok (NULL, delimitter);
|
||||
|
||||
printf("%s\n", token != NULL ? token : "");
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
usage (void)
|
||||
{
|
||||
printf ("cut, splits each line based on a delimiter\n");
|
||||
printf ("usage: cut [FLAG] FILE\n");
|
||||
printf ("FLAG can be:\n");
|
||||
printf (
|
||||
" -d C split each line based on the character C (default ' ')\n");
|
||||
printf (" -f N print the Nth field (1 is first, default 1)\n");
|
||||
printf ("If no FILE specified, read from STDIN\n");
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static void usage (void);
|
||||
|
||||
bool
|
||||
is_util (char *str)
|
||||
{
|
||||
char *utils[] = { "./bin/cat", "./bin/chmod", "./bin/cut", "./bin/env",
|
||||
"./bin/head", "./bin/ls", "./bin/repeat" };
|
||||
|
||||
for (size_t i = 0; i < 7; i++)
|
||||
{
|
||||
if (strcmp (str, utils[i]) == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char *argv[], char *envp[])
|
||||
{
|
||||
size_t envp_count = 0;
|
||||
while (envp[envp_count] != NULL) envp_count++;
|
||||
|
||||
size_t env_args = 0;
|
||||
char* util = NULL;
|
||||
|
||||
for (size_t i = 1; i < argc; i++)
|
||||
{
|
||||
if (is_util (argv[i])) {
|
||||
util = argv[i];
|
||||
break;
|
||||
}
|
||||
|
||||
env_args++;
|
||||
}
|
||||
|
||||
if (util == NULL) {
|
||||
usage();
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
char **combined_envp = calloc (envp_count + env_args + 1, sizeof (char *));
|
||||
memcpy (combined_envp, envp, envp_count * sizeof (char *));
|
||||
memcpy (combined_envp + envp_count, &argv[1], env_args * sizeof (char *));
|
||||
combined_envp[envp_count + env_args] = NULL;
|
||||
|
||||
execve(util, &argv[env_args + 1], combined_envp);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
usage (void)
|
||||
{
|
||||
printf ("env, set environment variables and execute program\n");
|
||||
printf ("usage: env [name=value ...] PROG ARGS\n");
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
#define _GNU_SOURCE
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
// You may assume that lines are no longer than 1024 bytes
|
||||
#define LINELEN 1024
|
||||
|
||||
static void usage (void) __attribute__ ((unused));
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
int opt;
|
||||
int n = 5;
|
||||
|
||||
while ((opt = getopt (argc, argv, "n:")) != -1)
|
||||
{
|
||||
switch (opt)
|
||||
{
|
||||
case 'n':
|
||||
n = strtol (optarg, NULL, 10);
|
||||
break;
|
||||
default:
|
||||
printf ("./bin/head: invalid option -- \'%c\'\n", optopt);
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
FILE *file = optind < argc ? fopen (argv[optind], "r") : stdin;
|
||||
if (file == NULL)
|
||||
{
|
||||
perror ("Failed to open input file");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
char buffer[LINELEN];
|
||||
int count = 0;
|
||||
|
||||
while (count < n && fgets (buffer, sizeof (buffer), file) != NULL)
|
||||
{
|
||||
printf ("%s", buffer);
|
||||
count++;
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
usage (void)
|
||||
{
|
||||
printf ("head, prints the first few lines of a file\n");
|
||||
printf ("usage: head [FLAG] FILE\n");
|
||||
printf ("FLAG can be:\n");
|
||||
printf (" -n N show the first N lines (default 5)\n");
|
||||
printf ("If no FILE specified, read from STDIN\n");
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
#define _GNU_SOURCE
|
||||
#include <dirent.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define MAX_PATH_LEN 4096
|
||||
|
||||
static void usage (void) __attribute__ ((unused));
|
||||
|
||||
// WARNING WARNING WARNING:
|
||||
// When using opendir and readdir to read directory listings, the files
|
||||
// are returned in the order they were created. There is randomness to that
|
||||
// creation that can cause tests to fail. You MUST sort the file names as
|
||||
// expected in the test case files. To avoid making your task harder than
|
||||
// it needs to be, we strongly suggest you use scandir instead.
|
||||
|
||||
int
|
||||
filename_cmp (const struct dirent **a, const struct dirent **b)
|
||||
{
|
||||
const char *name1 = (*a)->d_name;
|
||||
const char *name2 = (*b)->d_name;
|
||||
|
||||
while (*name1 == '.')
|
||||
name1++;
|
||||
while (*name2 == '.')
|
||||
name2++;
|
||||
|
||||
return strcasecmp (name1, name2);
|
||||
}
|
||||
|
||||
void
|
||||
print_permissions (mode_t mode)
|
||||
{
|
||||
char perms[11];
|
||||
|
||||
perms[0] = S_ISDIR (mode) ? 'd' : '-';
|
||||
perms[1] = (mode & S_IRUSR) ? 'r' : '-';
|
||||
perms[2] = (mode & S_IWUSR) ? 'w' : '-';
|
||||
perms[3] = (mode & S_IXUSR) ? 'x' : '-';
|
||||
perms[4] = (mode & S_IRGRP) ? 'r' : '-';
|
||||
perms[5] = (mode & S_IWGRP) ? 'w' : '-';
|
||||
perms[6] = (mode & S_IXGRP) ? 'x' : '-';
|
||||
perms[7] = (mode & S_IROTH) ? 'r' : '-';
|
||||
perms[8] = (mode & S_IWOTH) ? 'w' : '-';
|
||||
perms[9] = (mode & S_IXOTH) ? 'x' : '-';
|
||||
perms[10] = '\0';
|
||||
|
||||
printf ("%s", perms);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
int opt;
|
||||
int a_flag = false, p_flag = false, s_flag = false;
|
||||
|
||||
while ((opt = getopt (argc, argv, "aps")) != -1)
|
||||
{
|
||||
switch (opt)
|
||||
{
|
||||
case 'a':
|
||||
a_flag = true;
|
||||
break;
|
||||
case 'p':
|
||||
p_flag = true;
|
||||
break;
|
||||
case 's':
|
||||
s_flag = true;
|
||||
break;
|
||||
default:
|
||||
printf ("./bin/ls: invalid option -- \'%c\'\n", optopt);
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
char *dirname = optind < argc ? argv[optind] : ".";
|
||||
struct stat dirstat;
|
||||
|
||||
if (stat(dirname, &dirstat) != 0) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
struct dirent **namelist;
|
||||
int n = scandir (dirname, &namelist, NULL, filename_cmp);
|
||||
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
char path[MAX_PATH_LEN];
|
||||
snprintf (path, sizeof (path), "%s/%s", dirname, namelist[i]->d_name);
|
||||
|
||||
struct stat st;
|
||||
lstat (path, &st);
|
||||
|
||||
bool dot_dir = strcmp (namelist[i]->d_name, ".") == 0
|
||||
|| strcmp (namelist[i]->d_name, "..") == 0;
|
||||
|
||||
bool hidden = namelist[i]->d_name[0] == '.';
|
||||
|
||||
if (dot_dir || (!a_flag && hidden) || (s_flag && S_ISDIR (st.st_mode)))
|
||||
{
|
||||
free (namelist[i]);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (s_flag)
|
||||
{
|
||||
printf ("%ld ", st.st_size);
|
||||
}
|
||||
|
||||
if (p_flag)
|
||||
{
|
||||
print_permissions (st.st_mode);
|
||||
printf (" ");
|
||||
}
|
||||
|
||||
printf ("%s\n", namelist[i]->d_name);
|
||||
|
||||
free (namelist[i]);
|
||||
}
|
||||
free (namelist);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
usage (void)
|
||||
{
|
||||
printf ("ls, list directory contents\n");
|
||||
printf ("usage: ls [FLAG ...] [DIR]\n");
|
||||
printf ("FLAG is one or more of:\n");
|
||||
printf (" -a list all files (even hidden ones)\n");
|
||||
printf (" -p list permission bitmask\n");
|
||||
printf (" -s list file sizes\n");
|
||||
printf ("If no DIR specified, list current directory contents.\n\n");
|
||||
printf ("Files must be sorted alphabetically, case insensitive.\n");
|
||||
printf ("Leading dots should be ignored when sorting.\n\n");
|
||||
printf ("With the -s flag, do not show entries for subdirectories.\n");
|
||||
printf ("Permission bitmasks are 10-character strings such as:\n");
|
||||
printf (" -rwxr-x---\n\n");
|
||||
printf (
|
||||
"The first character is d for directories and - for regular files.\n\n");
|
||||
printf ("Do not show the \".\" or \"..\" directory entries.\n");
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
static void usage (void) __attribute__ ((unused));
|
||||
|
||||
int
|
||||
main (int argc, char *argv[], char *envp[])
|
||||
{
|
||||
if (argc < 3)
|
||||
{
|
||||
usage();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
int i = 1;
|
||||
while (i < argc)
|
||||
{
|
||||
char *endptr;
|
||||
long count = strtol (argv[i], &endptr, 10);
|
||||
if (*endptr != '\0' || count <= 0)
|
||||
{
|
||||
usage();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
i++;
|
||||
|
||||
if (i >= argc)
|
||||
{
|
||||
usage();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
char *var = argv[i];
|
||||
char *val = NULL;
|
||||
int x = 0;
|
||||
while (envp[x] != NULL)
|
||||
{
|
||||
if (strstr(envp[x], var) == envp[x])
|
||||
{
|
||||
val = envp[x];
|
||||
break;
|
||||
}
|
||||
x++;
|
||||
}
|
||||
|
||||
if (val == NULL)
|
||||
{
|
||||
val = "";
|
||||
for (long j = 0; j < count; j++)
|
||||
{
|
||||
printf("%s=%s\n", var, val);
|
||||
}
|
||||
val = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
for (long j = 0; j < count; j++)
|
||||
{
|
||||
printf("%s\n", val);
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
usage (void)
|
||||
{
|
||||
printf ("repeat, a tool for printing repeated environment variables\n");
|
||||
printf ("usage: repeat N VAR ...\n");
|
||||
printf ("each N must be a positive integer\n");
|
||||
printf ("N VAR can be repeated, but each repetition must have both\n");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user