This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

Port from github, no history needed

+265
+20
README.md
··· 1 + # secret-santa 2 + Simple secret santa program in C, outputting a base64-encoded list of recievers that can be pasted to the corresponding givers. 3 + 4 + Using libb64's impl of encoding. 5 + 6 + ## Usage 7 + 8 + ```bash 9 + > gcc -o secret_santa main.c 10 + > echo "albert bobby colin" | ./secret_santa 11 + Seed: 12345 12 + colin: (base 64 encoding of the word bobby) 13 + albert: (base 64 encoding of the word colin) 14 + bobby: (base 64 encoding of the word albert) 15 + ``` 16 + 17 + ### Arguments 18 + `-s` seed, for replicability. 19 + `-d` decode/debug, leave the recipients as plaintext. 20 +
+245
main.c
··· 1 + #include <stdio.h> 2 + #include <stdlib.h> 3 + #include <string.h> 4 + #include <time.h> 5 + #include <stdbool.h> 6 + 7 + #define BUFFER_SIZE 4096 8 + #define MAX_NAMES 128 9 + 10 + #define BASE64_CENCODE_H 11 + 12 + typedef enum 13 + { 14 + step_A, step_B, step_C 15 + } base64_encodestep; 16 + 17 + typedef struct 18 + { 19 + base64_encodestep step; 20 + char result; 21 + int stepcount; 22 + } base64_encodestate; 23 + 24 + 25 + /* 26 + cencoder.c - c source to a base64 encoding algorithm implementation 27 + 28 + This is part of the libb64 project, and has been placed in the public domain. 29 + For details, see http://sourceforge.net/projects/libb64 30 + */ 31 + 32 + 33 + const int CHARS_PER_LINE = 72; 34 + 35 + void base64_init_encodestate(base64_encodestate* state_in) 36 + { 37 + state_in->step = step_A; 38 + state_in->result = 0; 39 + state_in->stepcount = 0; 40 + } 41 + 42 + char base64_encode_value(char value_in) 43 + { 44 + static const char* encoding = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 45 + if (value_in > 63) return '='; 46 + return encoding[(int)value_in]; 47 + } 48 + 49 + int base64_encode_block(const char* plaintext_in, int length_in, char* code_out, base64_encodestate* state_in) 50 + { 51 + const char* plainchar = plaintext_in; 52 + const char* const plaintextend = plaintext_in + length_in; 53 + char* codechar = code_out; 54 + char result; 55 + char fragment; 56 + 57 + result = state_in->result; 58 + 59 + switch (state_in->step) 60 + { 61 + while (1) 62 + { 63 + case step_A: 64 + if (plainchar == plaintextend) 65 + { 66 + state_in->result = result; 67 + state_in->step = step_A; 68 + return codechar - code_out; 69 + } 70 + fragment = *plainchar++; 71 + result = (fragment & 0x0fc) >> 2; 72 + *codechar++ = base64_encode_value(result); 73 + result = (fragment & 0x003) << 4; 74 + case step_B: 75 + if (plainchar == plaintextend) 76 + { 77 + state_in->result = result; 78 + state_in->step = step_B; 79 + return codechar - code_out; 80 + } 81 + fragment = *plainchar++; 82 + result |= (fragment & 0x0f0) >> 4; 83 + *codechar++ = base64_encode_value(result); 84 + result = (fragment & 0x00f) << 2; 85 + case step_C: 86 + if (plainchar == plaintextend) 87 + { 88 + state_in->result = result; 89 + state_in->step = step_C; 90 + return codechar - code_out; 91 + } 92 + fragment = *plainchar++; 93 + result |= (fragment & 0x0c0) >> 6; 94 + *codechar++ = base64_encode_value(result); 95 + result = (fragment & 0x03f) >> 0; 96 + *codechar++ = base64_encode_value(result); 97 + 98 + ++(state_in->stepcount); 99 + if (state_in->stepcount == CHARS_PER_LINE/4) 100 + { 101 + *codechar++ = '\n'; 102 + state_in->stepcount = 0; 103 + } 104 + } 105 + } 106 + /* control should not reach here */ 107 + return codechar - code_out; 108 + } 109 + 110 + int base64_encode_blockend(char* code_out, base64_encodestate* state_in) 111 + { 112 + char* codechar = code_out; 113 + 114 + switch (state_in->step) 115 + { 116 + case step_B: 117 + *codechar++ = base64_encode_value(state_in->result); 118 + *codechar++ = '='; 119 + *codechar++ = '='; 120 + break; 121 + case step_C: 122 + *codechar++ = base64_encode_value(state_in->result); 123 + *codechar++ = '='; 124 + break; 125 + case step_A: 126 + break; 127 + } 128 + *codechar++ = '\n'; 129 + 130 + return codechar - code_out; 131 + } 132 + 133 + char* encode(const char* input) 134 + { 135 + /* set up a destination buffer large enough to hold the encoded data */ 136 + char* output = (char*)malloc(BUFFER_SIZE); 137 + /* keep track of our encoded position */ 138 + char* c = output; 139 + /* store the number of bytes encoded by a single call */ 140 + int cnt = 0; 141 + /* we need an encoder state */ 142 + base64_encodestate s; 143 + 144 + /*---------- START ENCODING ----------*/ 145 + /* initialise the encoder state */ 146 + base64_init_encodestate(&s); 147 + /* gather data from the input and send it to the output */ 148 + cnt = base64_encode_block(input, strlen(input), c, &s); 149 + c += cnt; 150 + /* since we have encoded the entire input string, we know that 151 + there is no more input data; finalise the encoding */ 152 + cnt = base64_encode_blockend(c, &s); 153 + c += cnt; 154 + /*---------- STOP ENCODING ----------*/ 155 + 156 + /* we want to print the encoded data, so null-terminate it: */ 157 + *c = 0; 158 + 159 + return output; 160 + } 161 + 162 + void shuffle(int *array, int size, unsigned int seed) { 163 + srand(seed); 164 + for (int i = size - 1; i > 0; i--) { 165 + int j = rand() % (i + 1); 166 + int temp = array[i]; 167 + array[i] = array[j]; 168 + array[j] = temp; 169 + } 170 + } 171 + 172 + int main(int argc, char *argv[]) { 173 + char buffer[BUFFER_SIZE]; 174 + char *names[MAX_NAMES]; 175 + int indices[MAX_NAMES]; 176 + int name_count = 0; 177 + unsigned int seed; 178 + bool seed_provided = false; 179 + bool encode_partner = true; 180 + 181 + for (int i = 1; i < argc; i++) { 182 + if (strcmp(argv[i], "-s") == 0 && i + 1 < argc) { 183 + seed = (unsigned int)strtoul(argv[i + 1], NULL, 10); 184 + seed_provided = true; 185 + } 186 + if (strcmp(argv[i], "-d") == 0) { 187 + encode_partner = false; 188 + } 189 + } 190 + 191 + if (!seed_provided) { 192 + seed = (unsigned int)time(NULL); 193 + } 194 + 195 + printf("Seed: %u\n", seed); 196 + 197 + if (fgets(buffer, sizeof(buffer), stdin) == NULL) { 198 + perror("Error reading input"); 199 + return 1; 200 + } 201 + 202 + size_t len = strlen(buffer); 203 + if (len > 0 && buffer[len - 1] == '\n') { 204 + buffer[len - 1] = '\0'; 205 + } 206 + 207 + char *token = strtok(buffer, " "); 208 + while (token != NULL) { 209 + if (name_count >= MAX_NAMES) { 210 + fprintf(stderr, "Too many names (max %d)\n", MAX_NAMES); 211 + return 1; 212 + } 213 + names[name_count] = strdup(token); 214 + indices[name_count] = name_count; 215 + name_count++; 216 + token = strtok(NULL, " "); 217 + } 218 + 219 + if (name_count < 2) { 220 + fprintf(stderr, "Need at least two names for Secret Santa\n"); 221 + return 1; 222 + } 223 + 224 + shuffle(indices, name_count, seed); 225 + 226 + int offset = seed; 227 + if (offset % name_count == 0) { 228 + offset = 1; 229 + } 230 + for (int i = 0; i < name_count; i++) { 231 + int giver = indices[i]; 232 + int receiver = indices[(i + offset) % name_count]; 233 + if (encode_partner) { 234 + printf("%s: %s\n", names[giver], encode(names[receiver])); 235 + } else { 236 + printf("%s: %s\n", names[giver], names[receiver]); 237 + } 238 + } 239 + 240 + for (int i = 0; i < name_count; i++) { 241 + free(names[i]); 242 + } 243 + 244 + return 0; 245 + }