MC logo

CSc 232 Assignment 2

^  CSc 232 Ruby Assignments

90 pts

Services Lookup

Due: Mar 3

The Services File

On the Internet, the various services provided by computers on the network are associated with different port numbers. These port numbers are used by clients to request a particular kind of service on from another host. For instance, standard HTTP connections are made on port 80; FTP connections are made on port 21. Under Unix, the list of these assignments is given in a plain text file, /etc/services. This project involves writing a utility to read this file and look up the port number for any service. Even though this program uses a Unix configuration file, you don't need a whole Unix system to solve it; just a copy of the file. It's publicly readable, so you may download /etc/services file from Sandbox to your PC and work with the local copy. (This does, of course, require that you have the -s option working. See below.)

Here is a portion of that file on Sandbox, showing its format:

# Example /etc/services lines
finger          79/tcp
finger          79/udp
http            80/tcp          www www-http    # WorldWideWeb HTTP
http            80/udp          www www-http    # HyperText Transfer Protocol
kerberos        88/tcp          kerberos5 krb5  # Kerberos v5
kerberos        88/udp          kerberos5 krb5  # Kerberos v5
supdup          95/tcp
supdup          95/udp
hostname        101/tcp         hostnames       # usually from sri-nic
hostname        101/udp         hostnames       # usually from sri-nic
The # character denotes a comment. The comment continues to the end of a line. A comment may follow real data on the line. Data on each line is separated by white space. Blank lines are allowed, and are ignored. Each line containing data describes one service. The first field is the standard name for the service, the second describes the port number and the low-level protocol, separated by a slash. Then may appear zero or more additional fields specifying alias names for the same service. For more details, run man services on Sandbox.


Your script should take a command line of the following form:
ruby [ -s file ] service[/protocol] . . .
That is, it should take a list of services, optionally preceded by a specification of file to read. Each service may have an optional protocol, which is tcp or udp. If there is no protocol specified, show information for each protocol which actually occurs in the file. If -s file does not appear, read from /etc/services

For each service on the command line, print several lines of output. Place a blank line between the output for each service. Print the following.

If some service is specified on the command line with a protocol as xxx/ppp, and is not in the file, print:

xxx/ppp: No such service
If a service is requested without a protocol, as xxx. and does not appear with any protocol, print:
xxx: No such service
For each service which is found, print something of the following form. If a service is specified on the command line without a protocol, print one entry for each protocol found (there will be two at most).
xxx/ppp: NNN
xxx/ppp: Alias for yyy
xxx/ppp: [Other] Aliases: ...
xxx/ppp: # ...
The first line is printed for any match. The NNN is the port number. The second line is printed only when the name matches an alias rather than a standard name. The yyy is the standard name for the service. The third line shows alias names for the service. If the name on the command line was the standard name, this output line should read "Aliases" and give all the aliases. If there are no aliases, this line should not appear. If the command line name is an alias, this third output line should read "Other Aliases" and show only those aliases other than the one from the command line. If there are no additional aliases, this line should not appear. Finally, the comment line should show the comment at the end of the line where the service is described. If there is no comment, or if the comment contains no non-blank characters other than the leading #, this line should not appear.

For instance, on Sandbox, the execution of

ruby fred/barney kerberos5 hostnames bogus finger kerberos/tcp auth
would be:
fred/barney: No such service.

kerberos5/tcp: 88
kerberos5/tcp: Alias for kerberos
kerberos5/tcp: Other Aliases: krb5
kerberos5/tcp: # Kerberos v5

kerberos5/udp: 88
kerberos5/udp: Alias for kerberos
kerberos5/udp: Other Aliases: krb5
kerberos5/udp: # Kerberos v5

hostnames/tcp: 101
hostnames/tcp: Alias for hostname
hostnames/tcp: # usually from sri-nic

hostnames/udp: 101
hostnames/udp: Alias for hostname
hostnames/udp: # usually from sri-nic

bogus: No such service.

finger/tcp: 79

finger/udp: 79

kerberos/tcp: 88
kerberos/tcp: Aliases: kerberos5 krb5
kerberos/tcp: # Kerberos v5

auth/tcp: 113
auth/tcp: Aliases: authentication tap ident

auth/udp: 113
auth/udp: Aliases: authentication tap ident


The command line parameters are given the Ruby script in a pre-defined array called ARGV. If a -s option is given, you will see -s in ARGV[0] and the file name in ARGV[1]. Before processing service names, see if ARGV[0] is -s. If so, off the -s and the file name, and record the latter in some appropriate variable. Then you can continue processing from ARGV[0] without worrying about the option.

After dispensing with option, you must essentially compare each command-line item with each line in the file. For this you will need a double loop. You can loop through through each argument (using while() or foreach or something similar) and scan the file for each one. Alternatively, you can scan through the file once, at each line running through the argument list to see if you have a match. (The latter is more efficient, but the former produces output in the same order as the command line, which seems more natural.) Open file objects have a rewind method which returns to the start of the file.

After reading each line, you may want to start by removing the comment and saving it somewhere. The simplest way to decide if a line matches the command-line specification is probably to break the line into fields and examine the fields. You can break it up using split, or by matching it and using $n variables. It is also possible to use the command-line item to build a pattern which will match only lines you want, but be careful about matching the prefix of some actual service name by accident.


When your program works, is well-commented, and properly indented, submit it here.