martanne / abduco

abduco provides session management i.e. it allows programs to be run independently from its controlling terminal. That is programs can be detached - run in the background - and then later reattached. Together with dvtm it provides a simpler and cleaner alternative to tmux or screen.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Licensing

spotrh opened this issue · comments

It looks like there is code originally written in "dtach" included in abduco. (Analysis is here: https://bugs.debian.org/cgi-bin/bugreport.cgi?archive=no&bug=771102, I reproduced it locally and confirmed)

dtach (http://dtach.sourceforge.net/) is open source, licensed under the GPL, so this fact in and of itself is not an issue, but what is a problem is that neither the copyright notice of dtach nor the license for that code is included in abduco. Abduco is otherwise licensed ISC, a permissive license which is compatible with the GPL.

Your options for resolving this are:

  • Ask the dtach copyright holder for permission to use their code under the ISC license (and properly include the copyright notice for dtach in abduco).
  • Include dtach copyright notice and licensing in abduco as is. This would effectively change the license on dtach when compiled to be GPL, even if your unique code is still ISC (ISC + GPL = GPL)
  • Relicense abduco under the same license as dtach, GPL (and properly include the copyright notice for dtach in abduco).
  • You could purchase the copyrights for dtach. (I'm including this for completeness, i am not really suggesting this as a viable option)

Fedora currently includes abduco, and wishes to continue to do so, however, we also want to respect the copyright and license of dtach. Our hope is that you can resolve this to make the situation clear for everyone.

Hi, this has been brought up before (see #20). I still don't really agree with the presented analysis.

From my point of view the code similarities are mostly due to:

  • The wire protocol. Initially we attempted to keep it backwards compatible. This was later dropped and is irrelevant now.
  • Instructions to switch the terminal into raw mode. These are mostly constants (probably not copyrightable in the first place) and documented as such in the termios(3) man page which also gives the almost identical sequence as definition for the non-standard cfmakeraw(3) function.

Could you please show your detailed analysis (preferably against current git HEAD), such that individual claims can be analysed.

Thanks

I've looked into this again, and honestly, this is a gray area. Rerunning the analysis against the current git trees for each (and removing the places where the checker matches similar code within its own code base (e.g. abduco code matching other abduco code), leaves us with:

dtach/attach.c: line 206-214           |abduco/client.c: line 41-49        [80]
 cur_term.c_iflag &= ~(IXON|IXOFF);    | cur_term.c_iflag &= ~(IGNBRK|BRKINT|PA
 cur_term.c_oflag &= ~(OPOST);         | cur_term.c_oflag &= ~(OPOST);
 cur_term.c_lflag &= ~(ECHO|ECHONL|ICAN| cur_term.c_lflag &= ~(ECHO|ECHONL|ICAN
 cur_term.c_cflag &= ~(CSIZE|PARENB);  | cur_term.c_cflag &= ~(CSIZE|PARENB);
 cur_term.c_cflag |= CS8;              | cur_term.c_cflag |= CS8;
 cur_term.c_cc[VLNEXT] = VDISABLE;     | cur_term.c_cc[VLNEXT] = _POSIX_VDISABL
 cur_term.c_cc[VMIN] = 1;              | cur_term.c_cc[VMIN] = 1;
 cur_term.c_cc[VTIME] = 0;             | cur_term.c_cc[VTIME] = 0;
 tcsetattr(0, TCSADRAIN, &cur_term);   | tcsetattr(STDIN_FILENO, TCSANOW, &cur_term);

dtach/master.c: line 652-656           |abduco/abduco.c: line 505-508      [33]
  len = read(fd[0], buf, sizeof(buf)); |  ssize_t len = read_all(client_pipe[0]
  if (len > 0)                         |  if (len > 0) {
  {                                    |  write_all(STDERR_FILENO, errormsg, le
  write(2, buf, len);                  |  unlink(sockaddr.sun_path);
  kill(pid, SIGTERM);                  |

dtach/master.c: line 781-786           |abduco/forkpty-aix.c: line 79-83   [28]
  dup2(slave, 0);                      |  dup2(slave, 0);
  dup2(slave, 1);                      |  dup2(slave, 1);
  dup2(slave, 2);                      |  dup2(slave, 2);
                                       |  if (slave > 2)
  if (slave > 2)                       |  close(slave);
  close(slave);                        |

dtach/attach.c: line 341-343           |abduco/client.c: line 119-120      [26]
  len = read(0, pkt.u.buf, sizeof(pkt.u|  ssize_t len = read(STDIN_FILENO, pkt.
                                       |  if (len == -1 && errno != EAGAIN && e
  if (len == 0)                        |

dtach/master.c: line 756-761           |abduco/forkpty-aix.c: line 47-51   [26]
  fd = open("/dev/tty", O_RDWR|O_NOCTTY|  fd = open(_PATH_TTY, O_RDWR|O_NOCTTY)
  if (fd >= 0)                         |  if (fd >= 0) {
  {                                    |  ioctl(fd, TIOCNOTTY, NULL);
  ioctl(fd, TIOCNOTTY, NULL);          |  close(fd);
  close(fd);                           |  }
  }                                    |

dtach/master.c: line 672-676           |abduco/forkpty-aix.c: line 26-29   [25]
openpty(int *amaster, int *aslave, char|pid_t forkpty(int *master, char *name, 
 struct winsize *winp)                 |{
{                                      | int slave, fd;
 int master, slave;                    | char *path;
 char *buf;                            |

Looking at these six cases (in order):

  1. Abduco's code looks to be taken from the termios(3) man page, except for the variable naming, which is identical to dtach. The termios(3) man page uses "termios_p->c_iflag|oflag|lflag".

  2. This match, while similar, fails to take into account that it would likely be identical any code trying to do the same thing, as it is all external (and common) functions.

  3. This match, while similar, adopts standard naming and handling for forkpty functionality. I found identical code in https://opensource.apple.com/source/Libc/Libc-498/util/pty.c.

  4. doing a len call and checking the return value will look identical no matter who does it, but the variable naming is extremely similar dtach: "pkt.u.buf", abduco: "pkt.u.msg". That said, when we look at the structs used by each:

dtach
=====
struct packet
{
        unsigned char type;
        unsigned char len;
        union
        {
                unsigned char buf[sizeof(struct winsize)];
                struct winsize ws;
        } u;
};


abduco
=====
typedef struct {
        uint32_t type;
        uint32_t len;
        union {
                char msg[4096 - 2*sizeof(uint32_t)];
                struct {
                        uint16_t rows;
                        uint16_t cols;
                } ws;
                uint32_t i;
                uint64_t l;
        } u;
} Packet;

... these look like what one would expect if the struct was independently developed (and lazily named).

  1. This code would be identical if developed independently.

  2. "master"/"slave" naming conventions are extremely common.

So... conclusion: There is only one place that I see where the naming implies copying (case 1). Is that one case enough for copyright infringement?

Let's look at it deeper. That code came in with your initial commit: https://github.com/martanne/abduco/blob/89cbbb3aa6aea7ca7410096aeacc3316a3532344/abduco.c ( Feb 18, 2014 )
If we compare it to the current dtach code as of that time: https://github.com/crigler/dtach/blob/b5b466f9823b0ae30a85b08c5db54d7be9241b59/attach.c

They're 99% identical, especially in the places that go beyond what is given in the termios manpage. And the same variable naming. Do ~10 lines of termios handling copied make a derived work? That would be up to a court to decide, but given that the protocol requires these flags, it would not be possible or obvious to do it any other way, so I'd say no.

Given the lack of other evidence, once the false positives are removed, I don't see any reason to be concerned about infringement beyond this one possibility.

At the end of the day, only you really know if you copied those lines from dtach or not. It would ease my mind greatly if you stated openly and publicly that you did not, but that's entirely up to you.