Forums

Skip to content

Advanced search
  • Quick links
    • Unanswered topics
    • Active topics
    • Search
  • FAQ
  • Login
  • Register
  • Board index Assistance Portage & Programming
  • Search

small C program

Problems with emerge or ebuilds? Have a basic programming question about C, PHP, Perl, BASH or something else?
Post Reply
Advanced search
14 posts • Page 1 of 1
Author
Message
nizar
Apprentice
Apprentice
User avatar
Posts: 268
Joined: Fri Dec 19, 2003 10:01 pm
Location: localhost

small C program

  • Quote

Post by nizar » Mon Jun 21, 2004 7:13 pm

Hi,
I wrote a small C program (a long ago), Personally, i use it and thought to share it with you :wink:

Code: Select all

/*		sysinfo
		*-----*

25122003 - 120531
LICENSE: GPL

NAME
	sysinfo - print some user\system information

SYNOPSIS
	sysinfo

DESCRIPTION
	Show system information:
	1- $USER,$UID,$GID,$HOME,$SHELL,$GECOS.
	2- uptime (hours,minutes,seconds)
	3- load averagr (1,5 and 15 minutes)
	4- RAM (total,free and shared)
	5- Memory in buffers
	6- swap (total,used and free)
	7- procs

AUTHOR
	Written by Nizar Abed - nizar_AT_srcget.com

REPORTING BUGS
	Report bugs to <nizar\ AT\ srcget.com>

COPYRIGHT
	Copyright (c) 2003,2004 Nizar Abed.
	This is free software; see the source for copying conditions.  There is
	NO warranty; not even for MERCHANTABILITY or FITNESS FOR  A  PARTICULAR
	PURPOSE.

*/

#include <stdio.h>
#include <stdlib.h>
#include <linux/unistd.h>
#include <linux/kernel.h>
#include <sys/sysinfo.h>
#include <unistd.h>
#include <string.h>
#include <pwd.h>
#include <grp.h>
#include <utmp.h>
#include <time.h>
#include <sys/times.h>

/* some colors */
#define REDF "\033[31m"
#define REDB "\E[41m"
#define GREENF "\033[32m"
#define GREENB "\E[42m"
#define RSTF "\033[0m"
#define RESETB "\E[0m"
#define BOLD "\033[1m"

/* Version */
#define VERSION "0.2"

void CLS();

int main(int argc, char *argv[])
{
	CLS();

	struct sysinfo sinf;

	if( sysinfo(&sinf) != 0 )
		exit( EXIT_FAILURE );

	printf("\033[01;31msysinfo - %s\nLicense: GPL\033[00m\n\n",VERSION);

	struct passwd *user;
	uid_t uid = getuid();

	if( (user = getpwuid(uid)) == NULL )
		exit(EXIT_FAILURE);

	printf("$USER:%s%s%s\t",GREENF,user->pw_name,RSTF);
	printf("$UID:%s%d%s\t",GREENF,user->pw_uid,RSTF);
	printf("$GID:%s%d%s\t",GREENF,user->pw_gid,RSTF);
	printf("$HOME:%s%s%s\n",GREENF,user->pw_dir,RSTF);
	printf("$SHELL:%s%s%s\n",GREENF,user->pw_shell,RSTF);
	printf("$GECOS:%s%s%s\n\n",GREENF,*(user->pw_gecos)!='\0'?user->pw_gecos : "gecos EMPTY",RSTF);

	// uptime in seconds:
	// uptime / 86400 == days
	// ( uptime - (days * 86400) ) / 3600 == hours
	// ( uptime - (hours * 3600) ) / 60 == minutes
	// uptime - (days * 86400) - (hours * 3600) - (minutes * 60) == seconds
	// :)

	int days = sinf.uptime / 86400;
	int hours = ( sinf.uptime - (days * 86400 ) ) / 3600;
	int minutes = ( sinf.uptime - (days * 86400) -  (hours * 3600)  ) / 60 ;
	int seconds = sinf.uptime - (days * 86400) - (hours * 3600) - (minutes * 60);
	
	printf("Uptime:\n");
	printf("%s%.3d DAYS%s\n",GREENF,days,RSTF);
	printf("%s%.3d HOURS%s\n",GREENF,hours,RSTF);
	printf("%s%.3d MINUTES%s\n",GREENF,minutes,RSTF);
	printf("%s%.3d SECONDS%s\n\n",GREENF,seconds,RSTF);

	printf("Load:\n");
	printf("%s[1 min]  %.8d\n",GREENF,sinf.loads[0]);
	printf("[5 min]  %.8d\n",sinf.loads[1]);
	printf("[15 min] %.8d%s\n\n",sinf.loads[2],RSTF);

	int usedram = sinf.totalram - sinf.freeram;	
	printf("RAM:\n");
	printf("%s\tTotal\t:\t%d Bytes / %.2f MB\n",
		GREENF,sinf.totalram ,float(sinf.totalram / 1048576));
	
	printf("\tUsed\t:\t%d Bytes / %.2f MB / %.2f%\n",
		usedram, float(usedram / 1048576),
		(float(usedram) / sinf.totalram) * 100);
	
	printf("\tFree\t:\t%d Bytes / %.2f MB / %.2f%\n",
		sinf.freeram,float(sinf.freeram / 1048576),
		(float(sinf.freeram) / sinf.totalram) * 100);
	
	printf("\tShared\t:\t%d Bytes / %.2f MB%s\n\n",
		sinf.sharedram,float(sinf.sharedram / 1048576),RSTF);

	int usedswap = sinf.totalswap - sinf.freeswap;	
	printf("Memory in buffers:%s\n\t%d Bytes / %.2f MB%s\n\n",
		GREENF,sinf.bufferram,float(sinf.bufferram / 1048576),RSTF);

	printf("Swap:\n");
	printf("%s\tTotal\t:\t%d Bytes / %.2f MB\n",
		GREENF,sinf.totalswap,float(sinf.totalswap / 1048576));

	printf("\tUsed\t:\t%d Bytes / %.2f MB / %.2f%\n",
		usedswap,float( usedswap / 1048576 ),
		(float(usedswap) / sinf.totalswap) * 100);

	printf("\tFree\t:\t%d Bytes / %.2f MB / %.2f%\n\n%s",
		sinf.freeswap,float( sinf.freeswap / 1048576 ),
		(float(sinf.freeswap) / sinf.totalswap) * 100,RSTF);

	printf("procs: %s%d%s\n\n",GREENF,sinf.procs,RSTF);

	return EXIT_SUCCESS;

}

/*----------------------*/

/* clear screen */
void CLS() {

	printf("\033[2J\033[0;0H");

}
Top
drjimmy42
Guru
Guru
User avatar
Posts: 512
Joined: Mon Feb 03, 2003 10:24 pm
Location: Nashua, NH

  • Quote

Post by drjimmy42 » Mon Jun 21, 2004 8:24 pm

Thanks, but it doesn't compile...

Code: Select all

mendelssohn:~/test> gcc -ggdb -Wall -o /home/jorussel/test/sysinfo /home/jorussel/test/sysinfo.c
/home/jorussel/test/sysinfo.c: In function `main':
/home/jorussel/test/sysinfo.c:107: warning: int format, long unsigned int arg (arg 3)
/home/jorussel/test/sysinfo.c:108: warning: int format, long unsigned int arg (arg 2)
/home/jorussel/test/sysinfo.c:109: warning: int format, long unsigned int arg (arg 2)
/home/jorussel/test/sysinfo.c:113: error: syntax error before "float"
/home/jorussel/test/sysinfo.c:116: error: syntax error before "float"
/home/jorussel/test/sysinfo.c:120: error: syntax error before "float"
/home/jorussel/test/sysinfo.c:124: error: syntax error before "float"
/home/jorussel/test/sysinfo.c:128: error: syntax error before "float"
/home/jorussel/test/sysinfo.c:132: error: syntax error before "float"
/home/jorussel/test/sysinfo.c:135: error: syntax error before "float"
/home/jorussel/test/sysinfo.c:139: error: syntax error before "float"
Top
nizar
Apprentice
Apprentice
User avatar
Posts: 268
Joined: Fri Dec 19, 2003 10:01 pm
Location: localhost

  • Quote

Post by nizar » Mon Jun 21, 2004 8:38 pm

drjimmy42 wrote:Thanks, but it doesn't compile...

Code: Select all

mendelssohn:~/test> gcc -ggdb -Wall -o /home/jorussel/test/sysinfo /home/jorussel/test/sysinfo.c
/home/jorussel/test/sysinfo.c: In function `main':
/home/jorussel/test/sysinfo.c:107: warning: int format, long unsigned int arg (arg 3)
/home/jorussel/test/sysinfo.c:108: warning: int format, long unsigned int arg (arg 2)
/home/jorussel/test/sysinfo.c:109: warning: int format, long unsigned int arg (arg 2)
/home/jorussel/test/sysinfo.c:113: error: syntax error before "float"
/home/jorussel/test/sysinfo.c:116: error: syntax error before "float"
/home/jorussel/test/sysinfo.c:120: error: syntax error before "float"
/home/jorussel/test/sysinfo.c:124: error: syntax error before "float"
/home/jorussel/test/sysinfo.c:128: error: syntax error before "float"
/home/jorussel/test/sysinfo.c:132: error: syntax error before "float"
/home/jorussel/test/sysinfo.c:135: error: syntax error before "float"
/home/jorussel/test/sysinfo.c:139: error: syntax error before "float"

Code: Select all

g++ sysinfo.c -o sysinfo
Top
Genone
Retired Dev
Retired Dev
User avatar
Posts: 9657
Joined: Fri Mar 14, 2003 6:02 pm
Location: beyond the rim

  • Quote

Post by Genone » Mon Jun 21, 2004 11:09 pm

So it's a C++ program (just without classes).
Top
Sleeper
l33t
l33t
User avatar
Posts: 667
Joined: Tue Nov 12, 2002 3:40 pm
Contact:
Contact Sleeper
Website

  • Quote

Post by Sleeper » Tue Jun 22, 2004 6:56 am

Well , every program should compile with -Wall flags, regardless of the language :

Code: Select all

$ g++ -Wall -o sysinfo sysinfo.c 
sysinfo.c: In function `int main(int, char **)':
sysinfo.c:107: warning: int format, long int arg (arg 3)
sysinfo.c:108: warning: int format, long int arg (arg 2)
sysinfo.c:109: warning: int format, long int arg (arg 2)
sysinfo.c:114: warning: int format, long int arg (arg 3)
sysinfo.c:118: warning: unknown conversion type character 0xa in format
sysinfo.c:122: warning: int format, long int arg (arg 2)
sysinfo.c:122: warning: unknown conversion type character 0xa in format
sysinfo.c:125: warning: int format, long int arg (arg 2)
sysinfo.c:129: warning: int format, long int arg (arg 3)
sysinfo.c:133: warning: int format, long int arg (arg 3)
sysinfo.c:137: warning: unknown conversion type character 0xa in format
sysinfo.c:141: warning: int format, long int arg (arg 2)
sysinfo.c:141: warning: unknown conversion type character 0xa in format
$ 
Moreover, it could be a C program, if the comments where C (/* .. */ instead of //), even if C-99 allows for such comments ...

my .2 $ ;)
Top
nizar
Apprentice
Apprentice
User avatar
Posts: 268
Joined: Fri Dec 19, 2003 10:01 pm
Location: localhost

  • Quote

Post by nizar » Tue Jun 22, 2004 10:42 am

Sleeper wrote:Well , every program should compile with -Wall flags, regardless of the language :
Why?
Sleeper wrote: ...
Moreover, it could be a C program, if the comments where C (/* .. */ instead of //), even if C-99 allows for such comments ...

my .2 $ ;)
What is the problem with

Code: Select all

g++ sysinfo.c -o sysinfo
without -Wall?

The beauty of sharing... :)
Top
Mr_Maniac
Guru
Guru
User avatar
Posts: 546
Joined: Thu Jun 10, 2004 2:33 pm
Contact:
Contact Mr_Maniac
Website

  • Quote

Post by Mr_Maniac » Tue Jun 22, 2004 11:01 am

Code: Select all

bash-2.05b$ g++ -wall -o sysinfo sysinfo.c
g++: nicht erkannte Option »-wall«
sysinfo.c: In function `int main(int, char**)':
sysinfo.c:100: error: `seconds' undeclared (first use this function)
sysinfo.c:100: error: (Each undeclared identifier is reported only once for
   each function it appears in.)
sysinfo.c:100: error: Fehler beim Parsen before `int'
sysinfo.c:101: error: `days' undeclared (first use this function)
bash-2.05b$
Am I missing something?
What are the dependencies?
AMD Ryzen 5900X
64 GB DDR4 RAM
GeForce RTX 3080
Gentoo Linux (most recent stable kernel - amd64)
Windows 11 x64
Top
nizar
Apprentice
Apprentice
User avatar
Posts: 268
Joined: Fri Dec 19, 2003 10:01 pm
Location: localhost

  • Quote

Post by nizar » Tue Jun 22, 2004 12:06 pm

Seems that there was a problem with casting. :?

Code: Select all

/*		sysinfo
		*-----*

25122003 - 120531
LICENSE: GPL

NAME
	sysinfo - print some user\system information

SYNOPSIS
	sysinfo

DESCRIPTION
	Show system information:
	1- $USER,$UID,$GID,$HOME,$SHELL,$GECOS.
	2- uptime (hours,minutes,seconds)
	3- load averagr (1,5 and 15 minutes)
	4- RAM (total,free and shared)
	5- Memory in buffers
	6- swap (total,used and free)
	7- procs

AUTHOR
	Written by Nizar Abed - nizar_AT_srcget.com

REPORTING BUGS
	Report bugs to <nizar\ AT\ srcget.com>

COPYRIGHT
	Copyright (c) 2003,2004 Nizar Abed.
	This is free software; see the source for copying conditions.  There is
	NO warranty; not even for MERCHANTABILITY or FITNESS FOR  A  PARTICULAR
	PURPOSE.

*/

#include <stdio.h>
#include <stdlib.h>
#include <sys/sysinfo.h>
#include <unistd.h>
#include <string.h>
#include <pwd.h>

/* some colors */
#define REDF "\033[31m"
#define REDB "\E[41m"
#define GREENF "\033[32m"
#define GREENB "\E[42m"
#define RSTF "\033[0m"
#define RESETB "\E[0m"
#define BOLD "\033[1m"

/* Version */
#define VERSION "0.2"

void CLS();

int main(int argc, char *argv[])
{
	CLS();

	struct sysinfo sinf;

	if( sysinfo(&sinf) != 0 )
		exit( EXIT_FAILURE );

	printf("\033[01;31msysinfo - %s\nLicense: GPL\033[00m\n\n",VERSION);

	struct passwd *user;
	uid_t uid = getuid();

	if( (user = getpwuid(uid)) == NULL )
		exit(EXIT_FAILURE);

	printf("$USER:%s%s%s\t",GREENF,user->pw_name,RSTF);
	printf("$UID:%s%d%s\t",GREENF,user->pw_uid,RSTF);
	printf("$GID:%s%d%s\t",GREENF,user->pw_gid,RSTF);
	printf("$HOME:%s%s%s\n",GREENF,user->pw_dir,RSTF);
	printf("$SHELL:%s%s%s\n",GREENF,user->pw_shell,RSTF);
	printf("$GECOS:%s%s%s\n\n",GREENF,*(user->pw_gecos)!='\0'?user->pw_gecos : "gecos EMPTY",RSTF);

	// uptime in seconds:
	// uptime / 86400 == days
	// ( uptime - (days * 86400) ) / 3600 == hours
	// ( uptime - (hours * 3600) ) / 60 == minutes
	// uptime - (days * 86400) - (hours * 3600) - (minutes * 60) == seconds
	// :)

	int days = (int)(sinf.uptime / 86400);
	int hours = ( sinf.uptime - (days * 86400 ) ) / 3600;
	int minutes = ( sinf.uptime - (days * 86400) -  (hours * 3600)  ) / 60 ;
	int seconds = sinf.uptime - (days * 86400) - (hours * 3600) - (minutes * 60);
	
	printf("Uptime:\n");
	printf("%s%.3d DAYS%s\n",GREENF,days,RSTF);
	printf("%s%.3d HOURS%s\n",GREENF,hours,RSTF);
	printf("%s%.3d MINUTES%s\n",GREENF,minutes,RSTF);
	printf("%s%.3d SECONDS%s\n\n",GREENF,seconds,RSTF);

	printf("Load:\n");
	printf("%s[1 min]  %.8ld\n",GREENF,sinf.loads[0]);
	printf("[5 min]  %.8ld\n",sinf.loads[1]);
	printf("[15 min] %.8ld%s\n\n",sinf.loads[2],RSTF);

	int usedram = sinf.totalram - sinf.freeram;
	printf("RAM:\n");
	printf("%s\tTotal\t:\t%ld Bytes / %.2f MB\n",
		GREENF,sinf.totalram,(float)(sinf.totalram / 1048576));
	
	printf("\tUsed\t:\t%d Bytes / %.2f MB / %.2f PERCENT\n",
		usedram, (float)(usedram / 1048576),
		((float)(usedram) / sinf.totalram) * 100);
	
	printf("\tFree\t:\t%ld Bytes / %.2f MB / %.2f PERCENT\n",
		sinf.freeram,(float)(sinf.freeram / 1048576),
		((float)(sinf.freeram)) / sinf.totalram * 100);
	
	printf("\tShared\t:\t%ld Bytes / %.2f MB%s\n\n",
		sinf.sharedram,((float)(sinf.sharedram)) / 1048576,RSTF);

	int usedswap = sinf.totalswap - sinf.freeswap;	
	printf("Memory in buffers:%s\n\t%ld Bytes / %.2f MB%s\n\n",
		GREENF,sinf.bufferram,((float)(sinf.bufferram) / 1048576),RSTF);

	printf("Swap:\n");
	printf("%s\tTotal\t:\t%ld Bytes / %.2f MB\n",
		GREENF,sinf.totalswap,(float)(sinf.totalswap / 1048576));

	printf("\tUsed\t:\t%d Bytes / %.2lf MB / %.2f PERCENT\n",
		usedswap,(float)(usedswap / 1048576),
		((float)(usedswap) / sinf.totalswap) * 100);

	printf("\tFree\t:\t%ld Bytes / %.2f MB / %.2f PERCENT \n\n%s",
		sinf.freeswap,(float)(sinf.freeswap / 1048576),
		((float)(sinf.freeswap) / sinf.totalswap) * 100,RSTF);

	printf("procs: %s%d%s\n\n",GREENF,sinf.procs,RSTF);

	return EXIT_SUCCESS;

}

/*----------------------*/

/* clear screen */
void CLS() {

	printf("\033[2J\033[0;0H");

}
Compilation:

Code: Select all

g++ sysinfo.c -o sysinfo
OR
g++ -Wall sysinfo.c -o sysinfo
I hope it's O.K now. :oops:
Top
Sleeper
l33t
l33t
User avatar
Posts: 667
Joined: Tue Nov 12, 2002 3:40 pm
Contact:
Contact Sleeper
Website

  • Quote

Post by Sleeper » Tue Jun 22, 2004 12:10 pm

nizar wrote:
Sleeper wrote:Well , every program should compile with -Wall flags, regardless of the language :
Why?
Simply because it helps removing some of the bugs a program can have ...

What is the problem with

Code: Select all

g++ sysinfo.c -o sysinfo
without -Wall?

The beauty of sharing... :)
There's no problem except that correcting warning would help you to have a safer program ;)
If you look at

Code: Select all

sysinfo.c:107: warning: int format, long int arg (arg 3) 
for example, it means that you intend to print an int (with a %d) for example, but what your giving to printf is a long .. Although there's no problem on 32 bits arch, it becomes a problem when using 64 bits arch, where a long is 64 bits, and you're asking to print only 32 bits ...

Thus correcting these little warnings (nothing functional), would help for example to port your app on other arch...
However it's a very positive way of thinking to share code, and I dunno want to diminish your task .. I'm just a little bit picky ;)
Top
Sleeper
l33t
l33t
User avatar
Posts: 667
Joined: Tue Nov 12, 2002 3:40 pm
Contact:
Contact Sleeper
Website

  • Quote

Post by Sleeper » Tue Jun 22, 2004 12:11 pm

nizar wrote: [/code]
Compilation:

Code: Select all

g++ sysinfo.c -o sysinfo
OR
g++ -Wall sysinfo.c -o sysinfo
I hope it's O.K now. :oops:
Cool .. ;)
Top
nizar
Apprentice
Apprentice
User avatar
Posts: 268
Joined: Fri Dec 19, 2003 10:01 pm
Location: localhost

  • Quote

Post by nizar » Wed Jun 23, 2004 4:26 pm

Sleeper wrote:
nizar wrote: [/code]
Compilation:

Code: Select all

g++ sysinfo.c -o sysinfo
OR
g++ -Wall sysinfo.c -o sysinfo
I hope it's O.K now. :oops:
Cool .. ;)
Thanks 8)
Top
sysnine
n00b
n00b
User avatar
Posts: 17
Joined: Fri Mar 04, 2005 11:08 pm
Contact:
Contact sysnine
Website

  • Quote

Post by sysnine » Tue Apr 05, 2005 4:05 pm

Woot! cool app. says my system's running lean and mean, in all its outdated glory. hehehe....

it says im not even using any of my swap space (better not be, im only flying 2.6 and fluxbox@256M)

i wish i had some DDR, or, a CPU that isnt either a) a Duron or b)under 1GHz

im gonna start a "help system fund"

good work with the app, though...ill be adding it to my bin directorys
Libra: today is a good day to make important life decisions based on arbitrary nonsense written by an anonymous stranger in a newspaper.
Top
Halcy0n
Developer
Developer
User avatar
Posts: 1682
Joined: Wed Sep 17, 2003 5:09 am
Location: Freehold, NJ
Contact:
Contact Halcy0n
Website

  • Quote

Post by Halcy0n » Tue Apr 05, 2005 5:40 pm

Sleeper wrote:
nizar wrote:
Sleeper wrote:Well , every program should compile with -Wall flags, regardless of the language :
Why?
Simply because it helps removing some of the bugs a program can have ...
There's a difference between fixing the warning to get rid of the warning, and actually fixing a possible problem with the code that the warning is trying to report. Remember, warnings are warnings for a reason, the compiler can't tell if there will be an actual problem. Of course it is better to eliminate the warning, but this is not always possible.
Mark Loeser
http://www.halcy0n.com
Top
Sleeper
l33t
l33t
User avatar
Posts: 667
Joined: Tue Nov 12, 2002 3:40 pm
Contact:
Contact Sleeper
Website

  • Quote

Post by Sleeper » Tue Apr 05, 2005 9:14 pm

Halcy0n wrote: Of course it is better to eliminate the warning, but this is not always possible.
Do you have any example ? ... AFAIR, I never have seen a warning that is not solvable.. Sometimes it just mean to instruct more the compiler about what's you're doing.
I'm really interested in an example to eventually refresh my failing memory ;)
Top
Post Reply

14 posts • Page 1 of 1

Return to “Portage & Programming”

Jump to
  • Assistance
  • ↳   News & Announcements
  • ↳   Frequently Asked Questions
  • ↳   Installing Gentoo
  • ↳   Multimedia
  • ↳   Desktop Environments
  • ↳   Networking & Security
  • ↳   Kernel & Hardware
  • ↳   Portage & Programming
  • ↳   Gamers & Players
  • ↳   Other Things Gentoo
  • ↳   Unsupported Software
  • Discussion & Documentation
  • ↳   Documentation, Tips & Tricks
  • ↳   Gentoo Chat
  • ↳   Gentoo Forums Feedback
  • ↳   Duplicate Threads
  • International Gentoo Users
  • ↳   中文 (Chinese)
  • ↳   Dutch
  • ↳   Finnish
  • ↳   French
  • ↳   Deutsches Forum (German)
  • ↳   Diskussionsforum
  • ↳   Deutsche Dokumentation
  • ↳   Greek
  • ↳   Forum italiano (Italian)
  • ↳   Forum di discussione italiano
  • ↳   Risorse italiane (documentazione e tools)
  • ↳   Polskie forum (Polish)
  • ↳   Instalacja i sprzęt
  • ↳   Polish OTW
  • ↳   Portuguese
  • ↳   Documentação, Ferramentas e Dicas
  • ↳   Russian
  • ↳   Scandinavian
  • ↳   Spanish
  • ↳   Other Languages
  • Architectures & Platforms
  • ↳   Gentoo on ARM
  • ↳   Gentoo on PPC
  • ↳   Gentoo on Sparc
  • ↳   Gentoo on Alternative Architectures
  • ↳   Gentoo on AMD64
  • ↳   Gentoo for Mac OS X (Portage for Mac OS X)
  • Board index
  • All times are UTC
  • Delete cookies

© 2001–2026 Gentoo Foundation, Inc.

Powered by phpBB® Forum Software © phpBB Limited

Privacy Policy

 

 

magic