Language C
(Linux kernel module)
Date: | 08/02/05 |
Author: | Stefan Scheler |
URL: | http://sts.synflood.de/ |
Comments: | 15 |
Info: | http://www.tldp.org/LDP/khg/HyperNews/get/khg.html |
Score: | (3.02 in 325 votes) |
/* The 99 Bottles of Beer Linux Kernel Module v1.1 * (supports multiple driver instances) * * by Stefan Scheler <sts[at]synflood[dot]de> * August 2nd, 2005 - Ernstthal, Germany * * Usage: * 1) compile the module * 2) create the device: mknod /dev/bottles c 240 0 * 3) load the module: insmod bottles.ko * 4) print the song with: cat /dev/bottles */ #include <linux/fs.h> #include <linux/version.h> #include <linux/module.h> #include <linux/init.h> #include <asm/uaccess.h> #define DRIVER_MAJOR 240 #define BUFFERSIZE 160 #define PLURALS(b) (b>1)?"s":"" MODULE_AUTHOR("Stefan Scheler <sts[at]synflood[dot]de>"); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("The 99 Bottles of Beer Linux Kernel Module"); MODULE_SUPPORTED_DEVICE("Bottle of Beer"); struct _instance_data { int bytes_avail, bytes_sent, bottles; char buf[BUFFERSIZE]; }; static void fill_buffer(char *buf, int b) { char line[BUFFERSIZE/2]; if (b>0) { sprintf(buf, "%d bottle%s of beer on the wall, %d bottle%s of beer.\n" \ "Take one down and pass it around, ", b, PLURALS(b), b, PLURALS(b)); if (b==1) strcat(buf, "no more bottles of beer on the wall.\n"); else { sprintf(line, "%d bottle%s of beer on the wall.\n", b-1, PLURALS(b-1)); strcat(buf, line); } } else { sprintf(buf, "No more bottles of beer on the wall, no more bottles of beer.\n" \ "Go to the store and buy some more, 99 bottles of beer on the wall.\n"); } } static ssize_t driver_read(struct file *instance, char *userbuffer, size_t count, loff_t *offset) { struct _instance_data *iptr = (struct _instance_data *)instance->private_data; int to_copy; int not_copied; refillbuffer: fill_buffer(iptr->buf, iptr->bottles); iptr->bytes_avail = strlen(iptr->buf)+1; to_copy = iptr->bytes_avail-iptr->bytes_sent; if (to_copy>0) { if (to_copy> count) to_copy=count; not_copied=copy_to_user(userbuffer, iptr->buf+iptr->bytes_sent, to_copy); iptr->bytes_sent += to_copy-not_copied; return (to_copy-not_copied); } if ((to_copy==0) && (iptr->bottles>0)) { iptr->bytes_sent=0; iptr->bottles--; goto refillbuffer; } return 0; } int driver_open(struct inode *devicefile, struct file *instance) { struct _instance_data *iptr; iptr = (struct _instance_data *)kmalloc(sizeof(struct _instance_data), GFP_KERNEL); if (!iptr) return -1; iptr->bytes_sent = 0; iptr->bottles = 99; instance->private_data = iptr; return 0; } int driver_close(struct inode *devicefile, struct file *instance) { if (instance->private_data) kfree(instance->private_data); return 0; } static struct file_operations fops = { .owner = THIS_MODULE, .open = driver_open, .release = driver_close, .read = driver_read, }; static int __init __init_module(void) { if(register_chrdev(DRIVER_MAJOR, "99 Bottles of Beer", &fops) == 0) return 0; return -EIO; } static void __exit __cleanup_module(void) { unregister_chrdev(DRIVER_MAJOR, "99 Bottles of Beer"); } module_init(__init_module); module_exit(__cleanup_module);
Download Source | Write Comment
Alternative Versions
Version | Author | Date | Comments | Rate |
---|---|---|---|---|
actually produces correct lyrics :P | Dustshine | 08/20/05 | 0 | |
Correct ANSI C containing no semicolons | Steve Checkoway | 01/15/09 | 0 | |
multithreaded version | Stefan Scheler | 05/11/05 | 4 | |
poor Style | Matteo Casati | 09/01/05 | 6 | |
standard version | Bill Wein | 04/20/05 | 4 |
Download Source | Write Comment
Add Comment
Please provide a value for the fields Name,
Comment and Security Code.
This is a gravatar-friendly website.
E-mail addresses will never be shown.
Enter your e-mail address to use your gravatar.
Please don't post large portions of code here! Use the form to submit new examples or updates instead!
Comments
Rune Berge said on 08/03/05 00:55:56
Ha ha! I love it. Great idea
blueaura said on 08/03/06 04:39:02
isn't there a bug in fill_buffer? if b=2, won't the code
if (b==1)
strcat(buf, "no more bottles of beer on the wall.\n"
else {
sprintf(line, "%d bottle%s of beer on the wall.\n", b-1, PLURALS);
strcat(buf, line);printk("size %d\n", sizeof(struct _instance_data *));
}
print
"1 bottles of beer on the wall."
since b=2, so b-1 = 1, but the PLURALS macro uses b.
Stefan Scheler said on 08/05/06 16:26:39
Yeah, you're right. That's a bug. Hopefully fixed now.
david said on 03/16/07 17:41:50
I have my own version (to prove anything can be written in a line of C (and then broken into several lines so it can be edited in a terminal (using pico, of course...)))
david said on 03/16/07 17:42:51
Sorry, that code should have been:
Vipul said on 04/24/07 05:35:39
Makefile for interested ppl :D (assuming your file is called beer.c)
<pre>
ifneq ($(KERNELRELEASE),)
obj-m := beer.o
else
KDIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
default:
$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules
endif
</pre>
Russell said on 09/10/07 03:17:42
Cool stuff!!!
MOSFET said on 04/20/08 15:43:24
I don't understand why people write comments to such an uncommon language... I thought C was a letter.
Don said on 04/26/08 00:23:19
Wow. And people say that Cobol is verbose!!
Matt said on 04/13/09 09:00:06
Uncommon language are you kidding?
partha said on 09/03/09 12:38:24
Nice Joke
C is an Uncommon language
ken dakin said on 11/13/09 13:46:08
This very verbose example could be replaced by a few lines of assembler much more efficiently (and clearly).
Ruslan said on 11/29/09 02:34:59
This couldn't be replaced by assembler because of portability.
This couldn't be much shorter because it's kernel module.
Romko said on 02/11/10 21:14:43
And it could be replaced by a few lines of C =)
Russian Perler said on 03/05/10 19:03:21
Nice program.
C is uncommon?! That is so wrong! :D
C will never die!