Added code :D

This commit is contained in:
Quinn Evans 2015-09-26 23:52:34 -06:00
parent 818f88b329
commit 671b0cc8dd
6 changed files with 772 additions and 0 deletions

50
IRC-MSG.COB Normal file
View File

@ -0,0 +1,50 @@
IDENTIFICATION DIVISION.
PROGRAM-ID. "IRC-MSG".
DATA DIVISION.
WORKING-STORAGE SECTION.
01 PREFIX-WORK PIC X(96).
01 MSG-POINTER PIC 9(3).
LINKAGE SECTION.
01 BUFFER.
03 MSG-LENGTH PIC 9(3).
03 MSG-BODY PIC X(512).
03 MSG-BODY-1 REDEFINES MSG-BODY PIC X.
88 HAS-PREFIX VALUE ":".
01 IRC-MESSAGE.
03 PREFIX.
05 NICK PIC X(16).
05 IDENT PIC X(16).
05 HOST PIC X(64).
03 COMMAND PIC X(16).
03 PARAMETERS.
05 TARGET PIC X(50).
05 REST PIC X(480).
PROCEDURE DIVISION USING BUFFER, IRC-MESSAGE.
INITIALIZE IRC-MESSAGE, PREFIX-WORK, MSG-POINTER.
IF HAS-PREFIX THEN
PERFORM WITH-PREFIX
ELSE
MOVE 1 TO MSG-POINTER.
UNSTRING MSG-BODY,
DELIMITED BY SPACES,
INTO COMMAND, TARGET
WITH POINTER MSG-POINTER.
UNSTRING MSG-BODY,
DELIMITED BY " ",
INTO REST,
WITH POINTER MSG-POINTER.
WITH-PREFIX.
MOVE 2 TO MSG-POINTER.
UNSTRING MSG-BODY,
DELIMITED BY SPACES,
INTO PREFIX-WORK,
WITH POINTER MSG-POINTER.
UNSTRING PREFIX-WORK,
DELIMITED BY "!" OR "@",
INTO NICK,
IDENT,
HOST.

70
PRINTCNF.COB Normal file
View File

@ -0,0 +1,70 @@
IDENTIFICATION DIVISION.
PROGRAM-ID. "PRINT-CONFIG".
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT CONFIG
ORGANIZATION IS INDEXED
ACCESS MODE IS SEQUENTIAL
RECORD KEY IS CONFIG-KEY.
SELECT USERS
ORGANIZATION IS INDEXED
ACCESS MODE IS SEQUENTIAL
RECORD KEY IS USER-NAME.
SELECT CHANNELS
ORGANIZATION IS SEQUENTIAL.
DATA DIVISION.
FILE SECTION.
FD CONFIG.
01 CONFIG-RECORD.
03 CONFIG-KEY PIC X(16).
03 CONFIG-VALUE PIC X(64).
FD USERS.
01 USER-RECORD.
03 USER-NAME PIC X(16).
03 USER-LEVEL PIC 9(2).
FD CHANNELS.
01 CHANNEL-RECORD.
03 CHANNEL-NAME PIC X(50).
WORKING-STORAGE SECTION.
01 STATE PIC 9(2) VALUE 0.
88 DONE VALUE 10.
PROCEDURE DIVISION.
DISPLAY "CONFIGURATION ENTRIES:"
OPEN INPUT CONFIG.
PERFORM PRINT-CONFIG-ENTRY UNTIL DONE.
INITIALIZE STATE.
CLOSE CONFIG.
DISPLAY "USER ENTRIES:"
OPEN INPUT USERS.
PERFORM PRINT-USER-ENTRY UNTIL DONE.
INITIALIZE STATE.
CLOSE USERS.
DISPLAY "CHANNEL ENTRIES:"
OPEN INPUT CHANNELS.
PERFORM PRINT-CHANNEL-ENTRY UNTIL DONE.
INITIALIZE STATE.
CLOSE CHANNELS.
EXIT PROGRAM.
PRINT-CONFIG-ENTRY.
READ CONFIG NEXT RECORD
AT END MOVE 10 TO STATE.
IF NOT DONE THEN
DISPLAY CONFIG-RECORD.
PRINT-USER-ENTRY.
READ USERS NEXT RECORD
AT END MOVE 10 TO STATE.
IF NOT DONE THEN
DISPLAY USER-RECORD.
PRINT-CHANNEL-ENTRY.
READ CHANNELS NEXT RECORD
AT END MOVE 10 TO STATE.
IF NOT DONE THEN
DISPLAY CHANNEL-RECORD.

81
WOPO-CNF.COB Normal file
View File

@ -0,0 +1,81 @@
IDENTIFICATION DIVISION.
PROGRAM-ID. "WOPO-CNF".
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT CONFIG
ORGANIZATION IS INDEXED
ACCESS MODE IS RANDOM
RECORD KEY IS CONFIG-KEY.
SELECT USERS
ORGANIZATION IS INDEXED
ACCESS MODE IS RANDOM
RECORD KEY IS USER-NAME.
SELECT CHANNELS
ORGANIZATION IS SEQUENTIAL.
DATA DIVISION.
FILE SECTION.
FD CONFIG.
01 CONFIG-RECORD.
03 CONFIG-KEY PIC X(16).
03 CONFIG-VALUE PIC X(64).
FD USERS.
01 USER-RECORD.
03 USER-NAME PIC X(16).
03 USER-LEVEL PIC 9(2).
FD CHANNELS.
01 CHANNEL-RECORD.
03 CHANNEL-NAME PIC X(50).
WORKING-STORAGE SECTION.
01 STATE PIC 9(2) VALUE 0.
88 DONE VALUE 10.
PROCEDURE DIVISION.
DISPLAY "WOPO CONFIGURATION PROGRAM".
DISPLAY "BLANK ENTRY TO EXIT SECTION".
DISPLAY "WRITING CONFIGURATION ENTRIES:".
OPEN OUTPUT CONFIG.
PERFORM WRITE-CONFIG-ENTRY UNTIL DONE.
INITIALIZE STATE.
CLOSE CONFIG.
DISPLAY "WRITING USER ENTRIES:"
OPEN OUTPUT USERS.
PERFORM WRITE-USER-ENTRY UNTIL DONE.
INITIALIZE STATE.
CLOSE USERS.
OPEN OUTPUT CHANNELS.
DISPLAY "WRITING CHANNEL AUTOJOINS:"
PERFORM WRITE-CHANNEL-ENTRY UNTIL DONE.
INITIALIZE STATE.
CLOSE CHANNELS.
CALL "PRINT-CONFIG".
STOP RUN.
WRITE-CONFIG-ENTRY.
DISPLAY "KEY?"
ACCEPT CONFIG-KEY.
DISPLAY "VALUE?"
ACCEPT CONFIG-VALUE.
IF CONFIG-KEY EQUALS SPACES OR CONFIG-VALUE EQUALS SPACES
THEN MOVE 10 TO STATE
ELSE WRITE CONFIG-RECORD.
WRITE-USER-ENTRY.
DISPLAY "USER?"
ACCEPT USER-NAME.
DISPLAY "LEVEL?"
ACCEPT USER-LEVEL.
IF USER-NAME EQUALS SPACES OR USER-LEVEL EQUALS 0
THEN MOVE 10 TO STATE
ELSE WRITE USER-RECORD.
WRITE-CHANNEL-ENTRY.
DISPLAY "CHANNEL?"
ACCEPT CHANNEL-NAME.
IF CHANNEL-NAME EQUALS SPACES
THEN MOVE 10 TO STATE
ELSE WRITE CHANNEL-RECORD.

355
WOPO.COB Normal file
View File

@ -0,0 +1,355 @@
IDENTIFICATION DIVISION.
PROGRAM-ID. "WOPO".
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT CONFIG
ORGANIZATION IS INDEXED
ACCESS MODE IS RANDOM
RECORD KEY IS CONFIG-KEY.
SELECT USERS
ORGANIZATION IS INDEXED
ACCESS MODE IS RANDOM
RECORD KEY IS USER-NAME.
SELECT CHANNELS
ORGANIZATION IS SEQUENTIAL.
DATA DIVISION.
FILE SECTION.
FD CONFIG.
01 CONFIG-RECORD.
03 CONFIG-KEY PIC X(16).
03 CONFIG-VALUE PIC X(64).
FD USERS.
01 USER-RECORD.
03 USER-NAME PIC X(16).
03 USER-LEVEL PIC 9(2).
FD CHANNELS.
01 CHANNEL-RECORD.
03 CHANNEL-NAME PIC X(50).
WORKING-STORAGE SECTION.
01 STATE PIC 9(2).
88 SUCCESS VALUE 0.
88 DONE VALUE 99.
01 BUFFER.
03 MSG-LENGTH PIC 9(3).
03 MSG-BODY PIC X(512).
01 IRC-MESSAGE.
03 PREFIX.
05 NICK PIC X(16).
05 IDENT PIC X(16).
05 HOST PIC X(64).
03 COMMAND PIC X(16).
88 PING VALUE "PING".
88 PRIVMSG VALUE "PRIVMSG".
03 PARAMETERS.
05 TARGET PIC X(50).
05 REST PIC X(480).
01 WAITING-COMMAND PIC X(16).
01 PARAMS.
03 WORK PIC X(50).
03 WORK-PREFIX REDEFINES WORK PIC X.
88 IS-COMMAND VALUE "$".
88 REST-PARAM VALUE ":".
03 PARAM PIC X(50) OCCURS 5 TIMES.
03 REG PIC X(50) OCCURS 5 TIMES.
PROCEDURE DIVISION.
DISPLAY "CONFIGURATION FOLLOWS:".
CALL "PRINT-CONFIG".
MOVE LENGTH OF MSG-BODY TO MSG-LENGTH.
CALL "CHANNEL-INIT"
USING BUFFER.
OPEN INPUT CONFIG.
MOVE "SERVER" TO CONFIG-KEY.
PERFORM READ-CONFIG-ENTRY.
MOVE 1 TO MSG-LENGTH.
STRING
CONFIG-VALUE, DELIMITED BY SPACE,
INTO MSG-BODY,
WITH POINTER MSG-LENGTH.
CALL "CHANNEL-OPEN", GIVING STATE.
IF NOT SUCCESS THEN DISPLAY MSG-BODY
GO TO DIE.
MOVE "NICK" TO CONFIG-KEY.
PERFORM READ-CONFIG-ENTRY.
MOVE 1 TO MSG-LENGTH.
INITIALIZE MSG-BODY.
STRING "NICK"
INTO MSG-BODY
WITH POINTER MSG-LENGTH.
ADD 1 TO MSG-LENGTH.
STRING CONFIG-VALUE DELIMITED BY SPACE,
INTO MSG-BODY
WITH POINTER MSG-LENGTH.
PERFORM SEND-LINE.
MOVE 1 TO MSG-LENGTH.
INITIALIZE MSG-BODY.
STRING "USER"
INTO MSG-BODY
WITH POINTER MSG-LENGTH.
ADD 1 TO MSG-LENGTH.
MOVE "IDENT" TO CONFIG-KEY.
PERFORM READ-CONFIG-ENTRY.
STRING CONFIG-VALUE DELIMITED BY SPACE,
INTO MSG-BODY
WITH POINTER MSG-LENGTH.
ADD 1 TO MSG-LENGTH.
MOVE "REAL-NAME" TO CONFIG-KEY.
PERFORM READ-CONFIG-ENTRY.
STRING "BOGUS HOST :" DELIMITED BY SIZE,
CONFIG-VALUE DELIMITED BY " ",
INTO MSG-BODY
WITH POINTER MSG-LENGTH.
PERFORM SEND-LINE.
MOVE "NICKSERV-PASSWORD" TO CONFIG-KEY.
READ CONFIG RECORD
INVALID KEY MOVE SPACES TO CONFIG-KEY.
IF CONFIG-KEY IS NOT EQUAL TO SPACES THEN
INITIALIZE MSG-BODY
MOVE 1 TO MSG-LENGTH
STRING "PRIVMSG NICKSERV :IDENTIFY " DELIMITED BY SIZE,
CONFIG-VALUE DELIMITED BY SPACE,
INTO MSG-BODY
WITH POINTER MSG-LENGTH
PERFORM SEND-LINE.
OPEN INPUT CHANNELS.
PERFORM AUTOJOIN-CHANNELS UNTIL DONE.
CLOSE CHANNELS.
OPEN I-O USERS.
PERFORM MAIN FOREVER.
DIE.
DISPLAY STATE.
STOP RUN.
AUTOJOIN-CHANNELS.
READ CHANNELS RECORD
AT END MOVE 99 TO STATE.
IF NOT DONE THEN
MOVE 1 TO MSG-LENGTH
STRING "JOIN " DELIMITED BY SIZE,
CHANNEL-NAME DELIMITED BY SPACES,
INTO MSG-BODY
WITH POINTER MSG-LENGTH
PERFORM SEND-LINE.
READ-CONFIG-ENTRY.
READ CONFIG RECORD
INVALID KEY DISPLAY "REQUIRED KEY UNSPECIFIED:"
DISPLAY CONFIG-KEY
GO TO DIE.
SEND-LINE.
CALL "CHANNEL-SEND" GIVING STATE.
IF NOT SUCCESS THEN DISPLAY MSG-BODY
GO TO DIE.
RECEIVE-LINE.
INITIALIZE MSG-BODY.
CALL "CHANNEL-RECV" GIVING STATE.
IF NOT SUCCESS THEN GO TO DIE.
CALL "IRC-MSG" USING BUFFER, IRC-MESSAGE.
WAIT-FOR-COMMAND.
PERFORM RECEIVE-LINE UNTIL COMMAND EQUALS WAITING-COMMAND.
GET-PARAMS.
UNSTRING REST DELIMITED BY SPACE INTO
PARAM(1)
PARAM(2)
PARAM(3)
PARAM(4)
PARAM(5).
MOVE PARAM(1) TO WORK.
IF REST-PARAM THEN
UNSTRING WORK DELIMITED BY ":" INTO PARAM(1), PARAM(1).
VALIDATE-USER.
MOVE NICK TO USER-NAME.
READ USERS RECORD
INVALID KEY MOVE 0 TO USER-LEVEL.
DISPLAY USER-RECORD.
IF USER-LEVEL IS GREATER THAN 0 THEN
INITIALIZE MSG-BODY
MOVE 1 TO MSG-LENGTH
STRING "PRIVMSG NICKSERV :ACC"
INTO MSG-BODY
WITH POINTER MSG-LENGTH
ADD 1 TO MSG-LENGTH
STRING NICK
INTO MSG-BODY
WITH POINTER MSG-LENGTH
PERFORM SEND-LINE
MOVE "NOTICE" TO WAITING-COMMAND
MOVE 0 TO STATE
PERFORM WAIT-FOR-ACC UNTIL DONE.
WAIT-FOR-ACC.
PERFORM WAIT-FOR-COMMAND.
PERFORM GET-PARAMS.
IF PARAM(1) EQUALS USER-NAME AND PARAM(2) EQUALS "ACC" THEN
MOVE 99 TO STATE
IF PARAM(3) IS NOT EQUAL TO "3" THEN
MOVE 0 TO USER-LEVEL
ELSE NEXT SENTENCE
ELSE INITIALIZE COMMAND.
MAIN.
PERFORM RECEIVE-LINE.
MOVE 1 TO MSG-LENGTH.
IF PING THEN
PERFORM PONG
ELSE IF PRIVMSG THEN
PERFORM HANDLE-PRIVMSG.
PONG.
DISPLAY "PONG".
STRING "PONG"
INTO MSG-BODY
WITH POINTER MSG-LENGTH.
PERFORM SEND-LINE.
HANDLE-PRIVMSG.
PERFORM GET-PARAMS.
MOVE PARAM(1) TO WORK.
IF IS-COMMAND THEN
UNSTRING WORK DELIMITED BY "$" INTO PARAM(1), PARAM(1)
IF PARAM(1) IS EQUAL TO "HELP" THEN
PERFORM HANDLE-HELP
ELSE IF PARAM(1) IS EQUAL TO "SOURCE" THEN
PERFORM HANDLE-SOURCE
ELSE IF PARAM(1) IS EQUAL TO "LEVEL" THEN
PERFORM HANDLE-LEVEL
ELSE IF PARAM(1) IS EQUAL TO "OP" THEN
PERFORM HANDLE-OP
ELSE IF PARAM(1) IS EQUAL TO "JOIN" THEN
PERFORM HANDLE-JOIN
ELSE IF PARAM(1) IS EQUAL TO "PART" THEN
PERFORM HANDLE-PART
ELSE IF PARAM(1) IS EQUAL TO "QUIT" THEN
PERFORM HANDLE-QUIT
ELSE IF PARAM(1) IS EQUAL TO "RELEVEL" THEN
PERFORM HANDLE-RELEVEL.
HANDLE-HELP.
INITIALIZE MSG-BODY.
MOVE 1 TO MSG-LENGTH.
STRING "PRIVMSG "
TARGET
INTO MSG-BODY
WITH POINTER MSG-LENGTH.
ADD 1 TO MSG-LENGTH.
STRING ":$HELP $LEVEL $OP $JOIN $PART $QUIT $RELEVEL"
INTO MSG-BODY
WITH POINTER MSG-LENGTH.
PERFORM SEND-LINE.
HANDLE-SOURCE.
INITIALIZE MSG-BODY.
MOVE 1 TO MSG-LENGTH.
STRING "PRIVMSG "
TARGET
INTO MSG-BODY
WITH POINTER MSG-LENGTH.
ADD 1 TO MSG-LENGTH.
STRING ":HTTPS://GITHUB.COM/HEDDWCH/WOPO"
INTO MSG-BODY
WITH POINTER MSG-LENGTH.
PERFORM SEND-LINE.
HANDLE-LEVEL.
IF PARAM(2) IS NOT EQUAL TO SPACES THEN
MOVE PARAM(2) TO USER-NAME
ELSE
MOVE NICK TO USER-NAME.
READ USERS RECORD
INVALID KEY MOVE 0 TO USER-LEVEL.
INITIALIZE MSG-BODY.
MOVE 1 TO MSG-LENGTH.
STRING USER-RECORD
INTO MSG-BODY
WITH POINTER MSG-LENGTH.
PERFORM SEND-LINE.
HANDLE-OP.
MOVE TARGET TO REG(1).
MOVE PARAM(2) TO REG(2).
IF REG(2) IS EQUAL TO SPACES THEN
MOVE NICK TO REG(2).
PERFORM VALIDATE-USER.
IF USER-LEVEL IS GREATER THAN 50 THEN
INITIALIZE MSG-BODY
MOVE 1 TO MSG-LENGTH
STRING "MODE " DELIMITED BY SIZE,
REG(1) DELIMITED BY SPACES
INTO MSG-BODY
WITH POINTER MSG-LENGTH
ADD 1 TO MSG-LENGTH
STRING "+O " DELIMITED BY SIZE,
REG(2) DELIMITED BY SPACES
INTO MSG-BODY
WITH POINTER MSG-LENGTH
PERFORM SEND-LINE.
HANDLE-JOIN.
MOVE PARAM(2) TO REG(1).
PERFORM VALIDATE-USER.
IF USER-LEVEL IS GREATER THAN 80 THEN
INITIALIZE MSG-BODY
MOVE 1 TO MSG-LENGTH
STRING "JOIN ", REG(1)
INTO MSG-BODY
WITH POINTER MSG-LENGTH
PERFORM SEND-LINE.
HANDLE-PART.
MOVE PARAM(2) TO REG(1).
IF REG(1) EQUALS SPACES THEN
MOVE TARGET TO REG(1).
PERFORM VALIDATE-USER.
IF USER-LEVEL IS GREATER THAN 80 THEN
INITIALIZE MSG-BODY
MOVE 1 TO MSG-LENGTH
STRING "PART ", REG(1)
INTO MSG-BODY
WITH POINTER MSG-LENGTH
PERFORM SEND-LINE.
HANDLE-QUIT.
MOVE "QUIT-MESSAGE" TO CONFIG-KEY.
READ CONFIG RECORD
INVALID KEY MOVE SPACES TO CONFIG-VALUE.
PERFORM VALIDATE-USER.
IF USER-LEVEL IS GREATER THAN 90 THEN
INITIALIZE MSG-BODY
MOVE 1 TO MSG-LENGTH
STRING "QUIT :", CONFIG-VALUE
INTO MSG-BODY
WITH POINTER MSG-LENGTH
PERFORM SEND-LINE
GO TO QUIT.
HANDLE-RELEVEL.
MOVE PARAM(2) TO USER-NAME.
MOVE PARAM(3) TO USER-LEVEL.
PERFORM VALIDATE-USER.
IF USER-LEVEL IS EQUAL TO 99 THEN
WRITE USER-RECORD.
READ USERS RECORD
INVALID KEY MOVE 0 TO USER-LEVEL.
INITIALIZE MSG-BODY.
MOVE 1 TO MSG-LENGTH.
STRING USER-RECORD
INTO MSG-BODY
WITH POINTER MSG-LENGTH.
PERFORM SEND-LINE.
QUIT.
CALL "CHANNEL-CLOSE".
CLOSE CONFIG.
CLOSE USERS.
STOP RUN.

211
channel.c Normal file
View File

@ -0,0 +1,211 @@
#include <sys/types.h>
#include <sys/socket.h>
#include <ctype.h>
#include <errno.h>
#include <limits.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define LENGTH_DIGITS 3
#define DEFAULT_PORT "6667"
#define RECV_BUF_SIZE 1024
/*
* 01 BUFFER
* 03 MSG-LENGTH PIC 9(LENGTH_DIGITS)
* 03 MSG-BODY PIC X(x)
*/
#define BODY(buf) (char *)(buf + LENGTH_DIGITS)
// 01 CHANNEL-STATUS PIC 9(2)
#define EBADDEST 10
#define EOPENFAIL 20
#define EHUP 30
#define ESERV 40
char *msg_length, *msg_body;
int msg_body_len;
int sockfd;
char recv_buf[RECV_BUF_SIZE];
size_t recv_buf_pos = 0;
int channel_message_length(void)
{
char c_length[LENGTH_DIGITS + 1];
memcpy(c_length, msg_length, LENGTH_DIGITS);
c_length[LENGTH_DIGITS] = '\0';
return (int)strtol(c_length, NULL, 10) - 1;
}
void channel_from_cobol(void)
{
int message_length = channel_message_length();
memset(msg_body + message_length, 0, msg_body_len - message_length);
for(char *c = msg_body; *c; c++) {
*c = tolower(*c);
}
return;
}
void channel_to_cobol(void)
{
char *c;
for(c = msg_body; *c; c++) {
*c = toupper(*c);
}
memset(c, ' ', msg_body_len - strlen(msg_body));
return;
}
void channel_string_to_cobol(const char *s)
{
strncpy(msg_body, s, msg_body_len - 2);
msg_body[msg_body_len - 1] = '\0';
channel_to_cobol();
return;
}
/*
* MOVE LENGTH OF MSG-BODY OF BUFFER TO MSG-LENGTH OF BUFFER.
* CALL "CHANNEL-INIT" USING BUFFER.
*/
void CHANNEL__INIT(char *buffer)
{
msg_length = buffer;
msg_body = BODY(buffer);
msg_body_len = channel_message_length();
return;
}
/*
* STRING "HOST[:PORT]"
* INTO MSG-BODY
* WITH POINTER MSG-LENGTH.
* CALL "CHANNEL-OPEN" GIVING CHANNEL-STATUS.
*/
int CHANNEL__OPEN(void)
{
channel_from_cobol();
printf("Connecting to: %s\n", msg_body);
if(!strlen(msg_body)) {
channel_string_to_cobol("No host specified");
return EBADDEST;
}
char *port = strchr(msg_body, ':');
if(port) {
*port = '\0';
port++;
if(!strlen(port)) {
channel_string_to_cobol("Port separator specified, but not port");
return EBADDEST;
}
} else {
port = DEFAULT_PORT;
}
struct addrinfo hints, *res;
int status;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_ADDRCONFIG;
if((status = getaddrinfo(msg_body, port, &hints, &res))) {
channel_string_to_cobol(gai_strerror(status));
return EBADDEST;
}
struct addrinfo *curr_addr;
for(curr_addr = res; curr_addr; curr_addr = curr_addr->ai_next) {
sockfd = socket(curr_addr->ai_family, curr_addr->ai_socktype, curr_addr->ai_protocol);
if(sockfd == -1) {
perror("socket");
continue;
}
if(connect(sockfd, curr_addr->ai_addr, curr_addr->ai_addrlen) == -1) {
perror("connect");
close(sockfd);
continue;
}
break;
}
if(!curr_addr) {
channel_string_to_cobol("Unable to connect to host");
return EOPENFAIL;
}
return 0;
}
int CHANNEL__SEND(void)
{
char *msg;
int sent, total;
channel_from_cobol();
printf("Sending: %s\n", msg_body);
sent = 0;
total = strlen(msg_body);
msg_body[total++] = '\n';
while(sent < total) {
int status = send(sockfd, msg_body + sent, total - sent, 0);
if(status == -1) {
perror("send");
close(sockfd);
channel_string_to_cobol("Hung up");
return EHUP;
}
sent += status;
}
return 0;
}
int CHANNEL__RECV(void)
{
char *message_end;
get_buffered:
message_end = memchr(recv_buf, '\n', recv_buf_pos);
if(message_end) {
size_t message_size = message_end - recv_buf;
if (message_size > msg_body_len) {
channel_string_to_cobol("Server sent too-long message");
return ESERV;
}
memcpy(msg_body, recv_buf, message_size);
msg_body[message_size - 1] = '\0';
recv_buf_pos -= message_size + 1;
message_end++;
for(size_t i = 0; i < recv_buf_pos; i++) {
recv_buf[i] = message_end[i];
}
printf("Received: %s\n", msg_body);
channel_to_cobol();
return 0;
}
if(recv_buf_pos < RECV_BUF_SIZE - 1) {
ssize_t received = recv(sockfd, recv_buf + recv_buf_pos, RECV_BUF_SIZE - recv_buf_pos, 0);
if(received != -1) {
recv_buf_pos += received;
goto get_buffered;
}
perror("recv");
channel_string_to_cobol("Hung up");
return EHUP;
}
channel_string_to_cobol("Server failed to send newline");
return ESERV;
}
void CHANNEL__CLOSE(void)
{
close(sockfd);
return;
}

5
gnu-cobol.sh Normal file
View File

@ -0,0 +1,5 @@
#!/bin/sh
${CC:-cc} -o channel.o -c channel.c
${COBC:-cobc} -x WOPO-CNF.COB PRINTCNF.COB
${COBC:-cobc} -x WOPO.COB IRC-MSG.COB PRINTCNF.COB channel.o