+++ /dev/null
-/*
- * This command implements a simple Unix domain socket server.
- *
- * Usage:
- * server
- *
- * Description:
- * This program creates a Unix domain socket at the specified path
- * (defined in `server.lib.c`) and listens for incoming connections.
- * When a client sends data, the server logs it to a file and echoes
- * a receipt. The server runs until interrupted or an error occurs.
- *
- * Command-line Options and Arguments:
- * None: The program is self-contained and does not accept any
- * command-line arguments. All configuration is handled within
- * the implementation.
- */
-
-#define IFACE
-#include <stdio.h>
-#include <stdlib.h>
-#include "server.lib.c"
-
-int main(int argc, char *argv[]) {
- (void)argc; // Suppress unused variable warnings
- (void)argv;
-
- // Call the core server function
- return Server·run();
-}
+++ /dev/null
-#ifndef IFACE
-#define Server·IMPLEMENTATION
-#define IFACE
-#endif
-
-#ifndef Server·IFACE
-#define Server·IFACE
-
- // Necessary interface includes
- #include <sys/socket.h>
- #include <sys/un.h>
- #include <stddef.h>
-
- // Interface prototypes
- int Server·run();
-
-#endif // Server·IFACE
-
-#ifdef Server·IMPLEMENTATION
-
- // Implementation-specific includes
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <unistd.h>
- #include <errno.h>
-
- // Constants
- #define Server·SOCKET_PATH "mockup/subu_server_home/subu_server.sock"
- #define Server·LOG_PATH "mockup/subu_server_home/server.log"
- #define Server·BUFFER_SIZE 256
-
- int Server·run() {
- int server_fd, client_fd;
- struct sockaddr_un address;
- char buffer[Server·BUFFER_SIZE];
- FILE *log_file;
-
- // Open the log file
- log_file = fopen(Server·LOG_PATH, "a");
- if (log_file == NULL) {
- perror("Error opening log file");
- return EXIT_FAILURE;
- }
-
- // Create the socket
- if ((server_fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
- perror("Error creating socket");
- fclose(log_file);
- return EXIT_FAILURE;
- }
-
- // Configure socket address
- memset(&address, 0, sizeof(address));
- address.sun_family = AF_UNIX;
- strncpy(address.sun_path, Server·SOCKET_PATH, sizeof(address.sun_path) - 1);
-
- // Bind the socket
- unlink(Server·SOCKET_PATH); // Remove existing file if present
- if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) == -1) {
- perror("Error binding socket");
- fclose(log_file);
- close(server_fd);
- return EXIT_FAILURE;
- }
-
- // Listen for connections
- if (listen(server_fd, 5) == -1) {
- perror("Error listening on socket");
- fclose(log_file);
- close(server_fd);
- return EXIT_FAILURE;
- }
-
- printf("Server running, waiting for connections...\n");
-
- // Accept and handle client connections
- while ((client_fd = accept(server_fd, NULL, NULL)) != -1) {
- ssize_t bytes_read;
-
- memset(buffer, 0, Server·BUFFER_SIZE);
- bytes_read = read(client_fd, buffer, Server·BUFFER_SIZE - 1);
- if (bytes_read > 0) {
- fprintf(log_file, "Received: %s\n", buffer);
- fflush(log_file);
- } else if (bytes_read == -1) {
- perror("Error reading from client");
- }
-
- close(client_fd);
- }
-
- // Clean up
- perror("Error accepting connection");
- fclose(log_file);
- close(server_fd);
- unlink(Server·SOCKET_PATH);
-
- return EXIT_FAILURE;
- }
-
-#endif // Server·IMPLEMENTATION
--- /dev/null
+/*
+ Sends "hello" to `subu_server.sock`
+*/
+
+#define IFACE
+#include <stdio.h>
+#include <stdlib.h>
+#include "hello.lib.c"
+
+int main(int argc, char *argv[]) {
+ (void)argc; // Suppress unused variable warnings
+ (void)argv;
+
+ // Call the core server function
+ return Hello·run();
+}
--- /dev/null
+#ifndef IFACE
+#define Hello·IMPLEMENTATION
+#define IFACE
+#endif
+
+#ifndef Hello·IFACE
+#define Hello·IFACE
+
+ // Necessary interface includes
+ #include <sys/socket.h>
+ #include <sys/un.h>
+ #include <stddef.h>
+
+ // Interface prototypes
+ int Hello·run();
+
+#endif // Hello·IFACE
+
+#ifdef Hello·IMPLEMENTATION
+
+ // Implementation-specific includes
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
+ #include <unistd.h>
+ #include <errno.h>
+
+ // Constants
+ #define Hello·SOCKET_PATH "/var/user_data/Thomas-developer/subu/developer/mockup/subu_server_home/subu_server.sock"
+ #define Hello·LOG_PATH "server_test.log"
+ #define Hello·BUFFER_SIZE 256
+
+ int Hello·run(){
+ int client_fd;
+ struct sockaddr_un address;
+ char buffer[Hello·BUFFER_SIZE];
+ FILE *log_file;
+
+ // Open the log file
+ log_file = fopen(Hello·LOG_PATH ,"a+");
+ if( log_file == NULL ){
+ perror("Hello·run:: error opening log file");
+ return EXIT_FAILURE;
+ }
+
+ client_fd = socket(AF_UNIX ,SOCK_STREAM ,0);
+ if( client_fd == -1 ){
+ perror("Hello·run:: error opening socket");
+ fclose(log_file);
+ return EXIT_FAILURE;
+ }
+
+ // Configure server socket address
+ memset(&address ,0 ,sizeof(address));
+ address.sun_family = AF_UNIX;
+ strncpy(address.sun_path ,Hello·SOCKET_PATH ,sizeof(address.sun_path) - 1);
+
+ // Connect to the server
+ if( connect(client_fd ,(struct sockaddr *)&address ,sizeof(address)) == -1 ){
+ perror("Hello·run:: error connecting to server");
+ fclose(log_file);
+ close(client_fd);
+ return EXIT_FAILURE;
+ }
+
+ // Send message to the server
+ char *out_buf = "hello\n";
+ if( write(client_fd ,out_buf ,strlen(out_buf)) == -1 ){
+ perror("Hello·run:: error writing to server");
+ fclose(log_file);
+ close(client_fd);
+ return EXIT_FAILURE;
+ }
+
+ printf("Hello·run:: sent \"%s\"\n" ,out_buf);
+
+ // Clean up
+ fclose(log_file);
+ close(client_fd);
+
+ return EXIT_SUCCESS;
+ }
+
+#endif // Hello·IMPLEMENTATION
--- /dev/null
+/*
+ The subu server command line interface.
+
+ Usage:
+ server [-s <socket_path>] [-l <log_path>] [arguments...]
+
+ Options:
+ -s <socket_path> Specify the Unix socket file path. Default: ./socket
+ -l <log_path> Specify the log file path. Default: ./log.txt
+*/
+
+#define IFACE
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "server.lib.c"
+
+// Define defaults
+#define DEFAULT_SOCKET_PATH "socket"
+#define DEFAULT_LOG_PATH "log.txt"
+
+int main( int argc ,char *argv[] ){
+ char *socket_path = DEFAULT_SOCKET_PATH;
+ char *log_path = DEFAULT_LOG_PATH;
+ int error_flag = 0; // Flag to track errors
+
+ // Parse options
+ int opt;
+ while( (opt = getopt(argc ,argv ,"s:l:")) != -1 ){
+ switch( opt ){
+ case 's':
+ socket_path = optarg;
+ break;
+ case 'l':
+ log_path = optarg;
+ break;
+ case '?': // Unknown option
+ fprintf( stderr ,"Error: Unknown option '-%c'\n" ,optopt );
+ error_flag = 1;
+ break;
+ case ':': // Missing argument
+ fprintf( stderr ,"Error: Missing argument for '-%c'\n" ,optopt );
+ error_flag = 1;
+ break;
+ }
+ }
+
+ // Check for too many arguments
+ if( optind > argc - 1 ){
+ fprintf( stderr ,"Error: Too many arguments provided.\n" );
+ error_flag = 1;
+ }
+
+ // Exit on error after processing all options
+ if( error_flag ){
+ fprintf( stderr ,"Usage: %s [-s <socket_path>] [-l <log_path>] [arguments...]\n" ,argv[0] );
+ return EXIT_FAILURE;
+ }
+
+ // Rebase argv to prepare for run
+ argv[optind - 1] = argv[0]; // Program name at the new base
+ argc -= (optind - 1);
+ argv += (optind - 1);
+
+ // Log parsed options
+ printf( "Socket Path: %s\n" ,socket_path );
+ printf( "Log Path: %s\n" ,log_path );
+
+ // Call the core server function with the rebased arguments
+ return Server·run(argv ,argc ,socket_path ,log_path);
+}
--- /dev/null
+#ifndef IFACE
+#define Server·IMPLEMENTATION
+#define IFACE
+#endif
+
+#ifndef Server·IFACE
+#define Server·IFACE
+
+ // Interface prototype
+ int Server·run();
+
+#endif // Server·IFACE
+
+#ifdef Server·IMPLEMENTATION
+
+ // Implementation-specific includes
+ #include <sys/socket.h>
+ #include <sys/un.h>
+ #include <stddef.h>
+ #include <sys/types.h>
+ #include <bits/socket.h> // Ensure full definition of struct ucred
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
+ #include <unistd.h>
+ #include <errno.h>
+
+ // Type alias for ucred
+ typedef struct ucred ucred_t;
+
+ // Constants
+ #define Server·SOCKET_PATH "/var/user_data/Thomas-developer/subu/developer/mockup/subu_server_home/subu_server.sock"
+ #define Server·LOG_PATH "server.log"
+ #define Server·BUFFER_SIZE 256
+ #define MAX_ARGC 16
+
+ // Internal function prototypes
+ static void parse(const ucred_t *client_cred, const char *input_line);
+ static void hello(const ucred_t *client_cred, int argc, char *argv[]);
+
+ int Server·run(){
+ int server_fd, client_fd;
+ struct sockaddr_un address;
+ char buffer[Server·BUFFER_SIZE];
+ FILE *log_file;
+
+ log_file = fopen(Server·LOG_PATH, "a+");
+ if(log_file == NULL) {
+ perror("Server·run:: error opening log file");
+ return EXIT_FAILURE;
+ }
+
+ if((server_fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
+ perror("Server·run:: error creating socket");
+ fclose(log_file);
+ return EXIT_FAILURE;
+ }
+
+ memset(&address, 0, sizeof(address));
+ address.sun_family = AF_UNIX;
+ strncpy(address.sun_path, Server·SOCKET_PATH, sizeof(address.sun_path) - 1);
+
+ unlink(Server·SOCKET_PATH);
+ if(bind(server_fd, (struct sockaddr *)&address, sizeof(address)) == -1) {
+ perror("Server·run:: error binding socket");
+ fclose(log_file);
+ close(server_fd);
+ return EXIT_FAILURE;
+ }
+
+ if(listen(server_fd, 5) == -1) {
+ perror("Server·run:: error listening on socket");
+ fclose(log_file);
+ close(server_fd);
+ return EXIT_FAILURE;
+ }
+
+ printf("Server·run:: server running, waiting for connections...\n");
+
+ while((client_fd = accept(server_fd, NULL, NULL)) != -1) {
+ ucred_t client_cred;
+ socklen_t len = sizeof(client_cred);
+
+ if(getsockopt(client_fd, SOL_SOCKET, SO_PEERCRED, &client_cred, &len) == -1) {
+ perror("Server·run:: error getting client credentials");
+ close(client_fd);
+ continue;
+ }
+
+ // Log client credentials
+ fprintf(log_file, "Connection from PID=%d, UID=%d, GID=%d\n",
+ client_cred.pid, client_cred.uid, client_cred.gid);
+ fflush(log_file);
+
+ ssize_t bytes_read;
+ memset(buffer, 0, Server·BUFFER_SIZE);
+ bytes_read = read(client_fd, buffer, Server·BUFFER_SIZE - 1);
+ if(bytes_read > 0) {
+ printf("Server·run:: received: %s\n", buffer);
+ fprintf(log_file, "Received: %s\n", buffer);
+ fflush(log_file);
+
+ char *line = strtok(buffer, "\n");
+ while(line != NULL) {
+ parse(&client_cred, line);
+ line = strtok(NULL, "\n");
+ }
+ } else if(bytes_read == -1) {
+ perror("Server·run:: error reading from client");
+ }
+
+ close(client_fd);
+ }
+
+ perror("Server·run:: error accepting connection");
+ fclose(log_file);
+ close(server_fd);
+ unlink(Server·SOCKET_PATH);
+
+ return EXIT_FAILURE;
+ }
+
+ // Parse a single input line and dispatch to the appropriate command
+ static void parse(const ucred_t *client_cred, const char *input_line) {
+ char *argv[MAX_ARGC + 1] = {0};
+ int argc = 0;
+
+ char *line_copy = strdup(input_line);
+ if(!line_copy) {
+ perror("parse:: memory allocation failed");
+ return;
+ }
+
+ char *token = strtok(line_copy, " ");
+ while(token != NULL && argc < MAX_ARGC) {
+ argv[argc++] = token;
+ token = strtok(NULL, " ");
+ }
+
+ if(argc > 0) {
+ if(strcmp(argv[0], "hello") == 0) {
+ hello(client_cred, argc, argv);
+ }else{
+ fprintf(stderr, "Unknown command: %s\n", argv[0]);
+ }
+ }
+
+ free(line_copy);
+ }
+
+ // Example command: hello
+ static void hello(const ucred_t *client_cred, int argc, char *argv[]) {
+ printf("hello:: invoked by PID=%d, UID=%d, GID=%d\n",
+ client_cred->pid, client_cred->uid, client_cred->gid);
+ printf("hello:: arguments:\n");
+ for (int i = 1; i < argc; ++i) {
+ printf(" Arg %d: %s\n", i, argv[i]);
+ }
+ }
+
+#endif // Server·IMPLEMENTATION
--- /dev/null
+#ifndef IFACE
+#define Server·IMPLEMENTATION
+#define IFACE
+#endif
+
+#ifndef Server·IFACE
+#define Server·IFACE
+
+ // Necessary interface includes
+ #include <sys/socket.h>
+ #include <sys/un.h>
+ #include <stddef.h>
+
+ // Interface prototypes
+ int Server·run();
+
+#endif // Server·IFACE
+
+#ifdef Server·IMPLEMENTATION
+
+ // Implementation-specific includes
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
+ #include <unistd.h>
+ #include <errno.h>
+
+ // Constants
+ #define Server·SOCKET_PATH "/var/user_data/Thomas-developer/subu/developer/mockup/subu_server_home/subu_server.sock"
+ #define Server·LOG_PATH "server.log"
+ #define Server·BUFFER_SIZE 256
+
+ int Server·run(){
+ int server_fd ,client_fd;
+ struct sockaddr_un address;
+ char buffer[Server·BUFFER_SIZE];
+ FILE *log_file;
+
+ // Open the log file
+ log_file = fopen(Server·LOG_PATH ,"a+");
+ if( log_file == NULL ){
+ perror("Server·run:: error opening log file");
+ return EXIT_FAILURE;
+ }
+
+ // Create the socket
+ if( (server_fd = socket(AF_UNIX ,SOCK_STREAM ,0)) == -1 ){
+ perror("Server·run:: error creating socket");
+ fclose(log_file);
+ return EXIT_FAILURE;
+ }
+
+ // Configure socket address
+ memset(&address ,0 ,sizeof(address));
+ address.sun_family = AF_UNIX;
+ strncpy(address.sun_path ,Server·SOCKET_PATH ,sizeof(address.sun_path) - 1);
+
+ // Bind the socket
+ unlink(Server·SOCKET_PATH); // Remove existing file if present
+ if( bind(server_fd ,(struct sockaddr *)&address ,sizeof(address)) == -1 ){
+ perror("Server·run:: error binding socket");
+ fclose(log_file);
+ close(server_fd);
+ return EXIT_FAILURE;
+ }
+
+ // Listen for connections
+ if( listen(server_fd ,5) == -1 ){
+ perror("Server·run:: error listening on socket");
+ fclose(log_file);
+ close(server_fd);
+ return EXIT_FAILURE;
+ }
+
+ printf("Server·run:: server running, waiting for connections...\n");
+
+ // Accept and handle client connections
+ while( (client_fd = accept(server_fd ,NULL ,NULL)) != -1 ){
+ ssize_t bytes_read;
+ printf("Server·run:: connection made!\n");
+
+ memset(buffer ,0 ,Server·BUFFER_SIZE);
+ bytes_read = read(client_fd ,buffer ,Server·BUFFER_SIZE - 1);
+ if( bytes_read > 0 ){
+ printf("Server·run:: connection said: %s\n" ,buffer);
+ fprintf(log_file ,"Received: %s\n" ,buffer);
+ fflush(log_file);
+ } else if( bytes_read == -1 ){
+ perror("Server·run:: error reading from client");
+ }
+
+ close(client_fd);
+ }
+
+ // Clean up
+ perror("Server·run:: error accepting connection");
+ fclose(log_file);
+ close(server_fd);
+ unlink(Server·SOCKET_PATH);
+
+ return EXIT_FAILURE;
+ }
+
+#endif // Server·IMPLEMENTATION
--- /dev/null
+Received: hello
+
+Received: hello
+
+Connection from PID=7196, UID=2005, GID=2005
+Received: hello
+
--- /dev/null
+
+1. automatic create server log if it does not exist.
+2. option to pass in the home directory
+3. command processing of course
+4. proper permissions, group member can rx home directory, and w the socket. Can not do
+anything to other files.
+
+
+
+
# /bin/make must be run from $REPO_HOME/developer
-RESOURCE := $(REPO_HOME)/tool_shared/third_party/resource/release/make
-include $(RESOURCE)/makefile-environment
+RESOURCE:=$(REPO_HOME)/tool_shared/third_party/resource/release
+include $(RESOURCE)/make/environment_RT_0
-# overriding defaults
+# override defaults
EXECDIR=mockup/subu_server_home
LIBDIR=scratchpad
# assign a compiler to use
C=gcc
-CFLAGS= -include "$(RESOURCE)/environment.h" -std=gnu18 -Werror -O0 -ggdb -DDEBUG -DDEBUGDB -I$(INCDIR)
-LINKFLAGS=-L$(LIBDIR) -L/usr/lib -L/usr/lib64 -l$(PROJECT)
+
+# _GNU_SOURCE is needed to get ucred, the credentials of the pid that connects to a socket
+CFLAGS= -Werror -ggdb -D_GNU_SOURCE -DDEBUG -DDEBUGDB -include "$(RESOURCE)/cc/RT_0.h" -I$(INCDIR)
+
+LINKFLAGS=-L$(LIBDIR) -L/usr/lib64 -L/usr/lib -l$(PROJECT)
# Import the rules. The dash prefix means to ignore include errors. This is
# required because the DEPFILE might not exist yet.
+include $(RESOURCE)/make/targets
-include $(DEPFILE)
-include $(RESOURCE)/makefile