tvrzna / emptty

Dead simple CLI Display Manager on TTY
MIT License
696 stars 25 forks source link

Support \O in /etc/issue. #74

Closed amano-kenji closed 2 years ago

amano-kenji commented 2 years ago

On my system, /etc/issue contains \O. According to man agetty,

O
    Insert the DNS domainname of the machine.
tvrzna commented 2 years ago

Can you please review the result? I'm not on machine, that would have domain name and I would like to avoid to setting up whole environment.

amano-kenji commented 2 years ago

getDnsDomainName gets hostname instead of DNS domain name.

tvrzna commented 2 years ago

It should resolve the name from DNS, but "should" needs to be capitalized in this case. I'l try to setup the environment, but it will take some time to get to that. If I'm unable to solve this, maybe I'll consider to just output agetty --show-issue.

amano-kenji commented 2 years ago

You don't use emptty everyday?

tvrzna commented 2 years ago

I do, but I don't have enough free time to setup DNS.

amano-kenji commented 2 years ago

Here's how you set DNS domain.

For example, if your DNS domain is john.

/etc/resolv.conf

domain john
nameserver ...

/etc/hosts if your hostname is localhost

127.0.0.1 localhost.john localhost
::1 localhost.john localhost

/etc/hosts if your hostname is tmux

127.0.0.1 tmux tmux.john localhost
::1 tmux tmux.john localhost

According to my test, when there is no DNS domain, emptty displays hostname in place of DNS domain. When there is DNS domain, emptty displays it.

tvrzna commented 2 years ago

The results with this are inconsistent (tried on Void with dhcpcd and Arch with NetworkManager), it will take more time to configure system correctly to mimic agetty behaviour.

amano-kenji commented 2 years ago

You probably want to mimick the behavior of dnsdomainname from net-tools which also contains hostname executable.

amano-kenji commented 2 years ago

I just tested the latest commit. It works on my system, but I don't know whether it works on other kinds of setups.

amano-kenji commented 2 years ago

I just analyzed net-tools sourcecode and extracted the part that obtains dns domain.

#include <unistd.h>
#include <stdio.h>
#include <netdb.h>
#include <string.h>

int main() {
  char myname[512];
  gethostname(myname, sizeof(myname));
  char *dnsdomain = strchr(gethostbyname(myname)->h_name, '.')+1;
  printf("%s\n", dnsdomain);
  return 0;
}

man gethostbyname says gethostbyname is obsolete.

I think you should inspect every array element returned by net.LookupAddr. Your code just uses the first array element.

If hostname is tmux and dns domain is john, then /etc/hosts would look like

127.0.0.1 tmux tmux.johns localhost

I suspect net.LookupAddr returns tmux, tmux.johns, and localhost. I haven't used Go langauge before. You want to extract johns from tmux.johns by comparing the part before dot with hostname, tmux, and then extracting the part after dot.

This will probably extract dns domain, john, even if /etc/resolv.conf doesn't contain domain john. Don't use dhcpcd or NetworkManager to modify /etc/resolv.conf. Just modify /etc/hosts and /etc/resolv.conf by hand.

I don't know what net.LookupCNAME is supposed to do.

amano-kenji commented 2 years ago
char *dom = NULL;
char *host = xgethostname();
struct addrinfo hints, *info = NULL;
memset(&hints, 0, sizeof(hints));
hints.ai_flags = AI_CANONNAME;
if (host && getaddrinfo(host, NULL, &hints, &info) == 0 && info) {
  char *canon;
  if (info->ai_canonname &&
      (canon = strchr(info->ai_canonname, '.')))
    dom = canon + 1;
}
fputs(dom ? dom : "unknown_domain", ie->output);
if (info)
  freeaddrinfo(info);
free(host);

This is how agetty gets dns domain name. This is better than net-tools.

This gets hostname and passes hostname to getaddrinfo. canon name is looked up in the result returned by getaddrinfo. If canon name contains dot, the part after dot become DNS domain. Otherwise, unknown_domain becomes DNS domain.

I suspect net.LookupCNAME returns ai_canonname.

Thus, I think it's correct to eliminate net.LookupHost and net.LookupAddr in getDnsDomainName.

tvrzna commented 2 years ago

I've read the agetty code and that's the reason I used net.LookupCNAME. However with Void Linux with dhcpcd it wasn't working as expected, thus there's that fallback using net.LookupHost and net.LookupAddr until I find better way.

amano-kenji commented 2 years ago

Perhaps, you didn't configure dhcpcd to put domain xxx in /etc/resolv.conf?

tvrzna commented 2 years ago

I've used static domain_name=mydomain in /etc/dhcpcd/dhcpcd.conf and no matter how much time I've rebooted, the value persisted in /etc/resolv.conf. Agetty showed correct value, but net.LookupCNAME did not. But I see, I've edited the way how to set /etc/hosts, so I'll try that as soon as possible.

tvrzna commented 2 years ago

It starts to be more and more interesting.

On Arch Linux I'm still going through the net.LookupHost branch. But after changes in /etc/nsswitch.conf it started to work with LookupCNAME on Void Linux. It seems this particular thing is really tricky for each distro. I believe server-oriented distros (or correctly configured ones) may that have fine, however desktop-oriented distros may struggle with this.

At this point I consider to drop this feature, since it adds 20% size to built executable and the benefit is questionable due to the bugginess.

amano-kenji commented 2 years ago

Showing \O from /etc/issue is ugly. Even if you drop implementation of \O, isn't there a way to decrease ugliness of \O?

Or, you could just stick with LookupCNAME and show unknown_domain if LookupCNAME doesn't work out because that's what agetty does.

Edit: Maybe, it is a good idea to hide unimplemented flags.

tvrzna commented 2 years ago

I still don't know, what's different between Void and Arch in this case. Because even without working LookupCNAME in emptty, agetty in Void was able to get the domain name. I've checked sources of golang (Arch has 1.19, Void has 1.18) and there is nothing different. And I don't believe there is a change inside C libs. It still requires more investigation or even third party help.

I was also thinking about hiding unimplemented flags, but some of them are easy to implement and it's easier for user to spot a variable than missing value.

tvrzna commented 2 years ago

It looks like that the strange behaviour is just caused by its LookupCNAME implementation in Golang. Whole /etc/issue could be parsed by agetty, but this is something I'd like to avoid. Other solution could be to reimplement the way from agetty by using cgo, however it would just add more dependencies and the license issues would need to be handled. Since current solution works, I keep it.

I was thinking also about the additional size to the built executable and it's not that bad. If somebody would complain, there could be added new build flag, that would exclude it from a build.

amano-kenji commented 2 years ago

Great.