Ports with arbitrary control procedures are created with make-input-port and make-output-port:
The getc argument is a procedure that takes no arguments and returns the next input character from the port. When no more charaters are available from the port, getc returns eof. (If a non-character and non-eof value is returned, the exn:i/o:user-port exception is raised.)
The char-ready? argument is a procedure that takes no arguments and returns a true value if a character (or eof) is ready to be read, #f otherwise.
The close argument is a procedure of no arguments; it is called when the port is closed.
The write argument is a procedure that takes a string and writes it. (The write procedure can safely store or mutate this string.)
The close argument is a procedure of no arguments; it is called when the port is closed.
Ports created by make-input-port and make-output-port are immediately open for reading or writing. If the close procedure does not have any side-effects, then the custom port does not need to be explicitly closed.