manoj@hpldsla.sid.hp.com (Manoj Joshi) (07/31/90)
Is there a way to get the name of a process anywhere inside the source? By name, I mean argv[0]. As an alternative, I can pass argv[0] as an extra parameter from main() to every function in the program, but I think it is inefficient. Also, I do not think I want to use a global and initialize it to argv[0] in body of main(), because I do not use globals! I know that getpid() and getppid() get me the process id and parent's process id. From this I can scan thru the proc table in proc.h, and get the process name as a string. But this may be non-portable C. Note that __FILE__ does not solve my problem, because it does not return the name of the final executable, but only the current source file. Anyone find out how to do this? Manoj.
guy@auspex.auspex.com (Guy Harris) (08/01/90)
>Also, I do not think I want to use a global and initialize it to >argv[0] in body of main(), because I do not use globals! Perhaps you should start doing so. The only portable alternatives are 1) use a global or 2) pass argv[0] all the way down. >I know that getpid() and getppid() get me the process id and parent's >process id. In effect, the process ID *is* a global, although in most UNIX implementations it's not accessible directly from user code. So if you're using "getpid()", you're already using a global; it just happens to be hidden inside a routine (a routine in the kernel, in most implementations). If globals really offend you, you might want to hide the global in question inside a function....
mpl@pegasus.ATT.COM (Michael P. Lindner) (08/01/90)
In article <9220003@hpldsla.sid.hp.com> manoj@hpldsla.sid.hp.com (Manoj Joshi) writes: >Is there a way to get the name of a process anywhere inside the source? deleted >think it is inefficient. Also, I do not think I want to use a global >and initialize it to argv[0] in body of main(), because I do not use >globals! deleted >process id. From this I can scan thru the proc table in proc.h, and >get the process name as a string. But this may be non-portable C. deleted >Manoj. No. There is no way to do this. I do not understand why you would rather write code to scan through the proc table (which, incidentally, will require a setuid or setgid for your program and introduce all sorts of security risks) than use a global. If you know your architecture, you can do a stack trace on your process from inside to get to argv, but that is non-portable and ugly, too (although I have a routine which does it - I like ugly things, sometimes :^) My recommendation: BREAK DOWN AND USE A GLOBAL. Mike Lindner attmail!mplindner
peter@ficc.ferranti.com (Peter da Silva) (08/02/90)
In article <9220003@hpldsla.sid.hp.com> manoj@hpldsla.sid.hp.com (Manoj Joshi) writes: > Is there a way to get the name of a process anywhere inside the source? > I do not think I want to use a global and initialize it to argv[0] in > body of main(), because I do not use globals! Why not? This is guaranteed global per-process static data. There is no reason not to use a global. > I know that getpid() and getppid() get me the process id and parent's > process id. From this I can scan thru the proc table in proc.h, and > get the process name as a string. But this may be non-portable C. All this to avoid using a global? Especially considering that this will not work unless you're running as root! -- Peter da Silva. `-_-' +1 713 274 5180. 'U` <peter@ficc.ferranti.com>
jonb@specialix.co.uk (Jon Brawn) (08/02/90)
Someone writes: >Also, I do not think I want to use a global and initialize it to >argv[0] in body of main(), because I do not use globals! Try this sort of thing: #include <stdio.h> /* for NULL and printf */ char *ProgName(); main( argc, argv ) char **argv; { ProgName( argv[0] ); /* ** Code of your choice entered here */ Funky1(); } Funky1() { printf("My name is '%s'\n",ProgName(NULL)); } /* ** ProgName - if passed a name will save a (private) handle to the name passed. ** Regardless, it will return a pointer to the current name stored. */ char *ProgName( pname ) char *pname; { static char *myname = NULL; if ( pname ) myname = pname; return myname; } No guarantees - no liability accepted. Have fun! --- Jon Brawn, Specialix, 3 Wintersells Road, Byfleet, Surrey, KT14 7LF, UK. Tel: +44(0)9323-54254, Fax:+44(0)9323-52781, jonb@specialix.co.uk or: {backbone}!mcsun!ukc!slxsys!jonb ``Once upon a time, not so very long ago, in a land, not so very far away'' -- Jon Brawn, Specialix, 3 Wintersells Road, Byfleet, Surrey, KT14 7LF, UK. Tel: +44(0)9323-54254, Fax:+44(0)9323-52781, jonb@specialix.co.uk or: {backbone}!mcsun!ukc!slxsys!jonb
jrw@mtune.ATT.COM (Jim Webb) (08/02/90)
In article <9220003@hpldsla.sid.hp.com>, manoj@hpldsla.sid.hp.com (Manoj Joshi) writes: > Is there a way to get the name of a process anywhere inside the source? > By name, I mean argv[0]. As an alternative, I can pass argv[0] as an > extra parameter from main() to every function in the program, but I > think it is inefficient. Also, I do not think I want to use a global > and initialize it to argv[0] in body of main(), because I do not use > globals! What's wrong with using a global? You'd be amazed what the routine that puts together main(argc,argv) in the first place does if the use of a global frightens you :-) > I know that getpid() and getppid() get me the process id and parent's > process id. From this I can scan thru the proc table in proc.h, and > get the process name as a string. But this may be non-portable C. In System V at least, the name of the process is not stored in the process table, but rather in the process's user block. Finding the user block can be quite machine specific. If you _really really really_ don't want to use a global, you have two options, in order of diminishing appeal: 1) run the ps command inside a pipe and read the result: char psbuf[64]; char command[15]; FILE *ps; /* I'm sure this could be done better in perl :-) */ sprintf(psbuf,"ps -p%d|awk '{/PID/ {next} { print $4 }'",getpid()); ps=popen(psbuf,"r"); fgets(command,15,ps); pclose(ps); command[strlen(command)-1]=NULL; /* chop off the \n */ 2) do what the ps command does yourself: get your process id via getpid(). #ifdef i386: run the sysi86(RDUBLK) system call to get the user block for your process and use u.u_comm. #ifdef u3b2: run the sys3b(RDUBLK) system call to get the user block for your process and use u.u_comm. #ifdef anyotherSysVbox: do a name search on /unix and get the addresses of the process (_proc) and variable (_v) tables, or, checking the dates of /unix and /etc/ps_data and using the addresses in the latter if it exists and is newer than /unix (gain wizard points if you use this approach, which is mucho faster than running nlist) open /dev/kmem and seek to _v and get the size of the process table from v.v_proc (gain some wizard points if you use v.ve_proc later on) seek to _proc and then read thru this structure v.v_proc times (or until you reach v.ve_proc) comparing proc.p_pid with your process id. if you don't find it, well, them's the breaks :-) when found, figure out how to find the user block for this process. hints are to look thru the process's page table to find where it thinks the ublock is (it is _virtually_ the same for each process). seek to that location and read in the ublock and use u.u_comm. obviously, this all must be done as a user that has read permissions on /dev/kmem.....normally group sys will suffice. ----- Note that these solutions are really wastes of time (especially after you throw in error checking) since the information desired is already available in the process. Later, -- Jim Webb "Out of Phase -- Get Help" att!mtune!jrw "I'm bored with this....Let's Dance!"
jjones@casca.cs.uiuc.edu (Joel Jones) (08/03/90)
One reason one may not be able to use a global is if the function that needs the process name may be a library that is linked in. One way of accomplishing the goal (though inefficient) is to do a getpid(2), and then do a popen(3) with an argument of "ps -p pid ..." Joel Jones jjones@uiuc.edu -- Joel Jones As the advertisment for an exhibition on Leonardo da Vinci said, jones@uiuc.edu "They called him a genius, a botanist, a demon, a philosopher, a practical joker, an eccentric, and a visionary. No wonder he was such a great engineer."
davecb@yunexus.YorkU.CA (David Collier-Brown) (08/04/90)
jonb@specialix.co.uk (Jon Brawn) writes: >Try this sort of thing: [function that saves argv[0] in a static] Er, that substitutes a globally callable function for a globally referable variable. Net gain? more code to do the same thing, value is read-only. Looks like a bad tradeoff unless you have an imposed religious requirement to avoid global variables... --dave -- David Collier-Brown, | davecb@Nexus.YorkU.CA, ...!yunexus!davecb or 72 Abitibi Ave., | {toronto area...}lethe!dave Willowdale, Ontario, | "And the next 8 man-months came up like CANADA. 416-223-8968 | thunder across the bay" --david kipling
scott@nbc1.ge.com (Scott Barman) (08/04/90)
In article <9220003@hpldsla.sid.hp.com> manoj@hpldsla.sid.hp.com (Manoj Joshi) writes: >Is there a way to get the name of a process anywhere inside the source? >By name, I mean argv[0]. As an alternative, I can pass argv[0] as an >extra parameter from main() to every function in the program, but I >think it is inefficient. Also, I do not think I want to use a global >and initialize it to argv[0] in body of main(), because I do not use >globals! I cannot think of one rational or even irrational reason *not* to use global variables. Can you explain this to us? Do yourself a favor, declare and global like: char *progname; and the first line in your program do: progname = argv[0]; and save yourself a lot of unnecessary problem--including the waste in CPU time and disk access trying to read the proc table for something that is just handed to you. Then again, if you are running a Cray... :-) -- scott barman NBC Systems Development scott@nbc1.ge.com 30 Rockerfeller Plaza, Room 1615W {philabs,crdgw1}!nbc1!scott New York, NY 10112 +1 212/664-2787 (This does not represent any [un]official opinions of NBC or its affiliates)
chris@mimsy.umd.edu (Chris Torek) (08/04/90)
>>... I do not think I want to use a global and initialize it to argv[0] >>in body of main(), because I do not use globals! This is misguided zeal: not *all* globals are bad.... In article <53103@iuvax.cs.indiana.edu> sahayman@iuvax.cs.indiana.edu (Steve Hayman) writes: >If you really are determined not to use a global variable for style reasons, >you can hide the information off in another module. [example deleted] This merely replaces the global variable with a, or in this case, two, global functions. So when are globals okay? In general, if the thing being manipulated has to last for the entire duration of the program, and the thing's structure is dictated entirely by the goal of the program (as opposed to some specifics of the program's implementation), then a global is probably reasonable. If the thing need only be known in one place, or just a few places, then a file-scope `static' is probably best. The real trick is finding the proper abstractions. In this case the goal is to print messages that include the program's name, so maybe the best thing is to make `print a message that includes the program's name' a function. This replaces one global (the program's name) with another (the function that prints messages), but in the process it reduces the overall complexity of the whole program: instead of fprintf(stderr, "%s: configuration file %s not readable: %s\n", progname, conffile, strerror(errno)); exit(EXIT_FAILURE); you might have something like bomb_out("configuration file %s not readable: %s\n", conffile, strerror(errno)); The (concrete) `print this to stderr; exit' sequence has been replaced with the (more abstract) `stop because of this error' sequence. -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163) Domain: chris@cs.umd.edu Path: uunet!mimsy!chris (New campus phone system, active sometime soon: +1 301 405 2750)
guy@auspex.auspex.com (Guy Harris) (08/05/90)
>One reason one may not be able to use a global is >if the function that needs the process name >may be a library that is linked in. One way of >accomplishing the goal (though inefficient) is >to do a getpid(2), and then do a popen(3) with >an argument of "ps -p pid ..." Which won't work if your "ps" doesn't support the "-p" option. Another way of accomplishing the goal is to change the library routine (your posting sure assumes the user is in a position to do that; if they can't change the library routine, they sure can't make it do the "getpid()" nor the "popen()") to either: 1) take the "process name" as an argument; 2) have another routine that the main program calls, with the "process name" as an argument, that sets some static variable; 3) assume a (horrors!) global. These require a change to the library interface, but hey, there's no such thing as a free lunch....
gwyn@smoke.BRL.MIL (Doug Gwyn) (08/06/90)
In article <1990Aug4.051827.16438@nbc1.ge.com> scott@nbc1.GE.COM (Scott Barman) writes: >I cannot think of one rational or even irrational reason *not* to use >global variables. Really? I thought this was commonly taught in structured software development courses.
jonb@specialix.co.uk (Jon Brawn) (08/06/90)
davecb@yunexus.YorkU.CA (David Collier-Brown) writes: >jonb@specialix.co.uk (Jon Brawn) writes: >>Try this sort of thing: >[function that saves argv[0] in a static] > Er, that substitutes a globally callable function for a globally >referable variable. Net gain? more code to do the same thing, value >is read-only. ^^^^^^^^^^ Course its read only! When was the last time you wanted to change the name that you where invoked as? Shouldn't be allowed! There are often occasions when I would like to be able to label something as read only (yeah, I could grock the MMU on my machine, create a page entry, set the appropriate flags and stuff, but its a hell of a chore!). Hiding data in statics within functions is a relatively easy way of achieving the same net effect. You can also use the same approach for controlling access to objects. Keep the actual data storage within one .c file as a static, and have functions within that file that can be callable from outside the file which do error checking on their arguments (wow! what a concept - error checking!) before asigning to the object in question. It also means that you can change the algorithm within the module at any time, change the shape of the data, and still maintain the same interface to the rest of the code. It would be perfectly possible to re-write the routine I posted so that it did scan the proc table for the program name, and still not have to change a single line of the main program. Or perhaps a line could be added to the function which only saved the last part of the programs name, stripping of any leading path. (e.g. store "myprog" rather than "/usr/jonb/ace_progs/myprog"). Or perhaps it could store the name in EBCDIC rather than ASCII (perhaps for efficiancy reasons?) > Looks like a bad tradeoff unless you have an imposed religious >requirement to avoid global variables... Hmm. I remember getting 0% for a piece of course work at college for using a GOTO statement in Pascal, because it wasn't the sort of thing one did in Pascal. Religious convictions? Possibly a more open outlook on future trends....maybe the global will go the same way as the goto (I can but hope). What if the original question had been about something somewhat larger than the program name? where would you stand then? Look at the streams routines - compare them with the routines for clists. Whereas the cblock manipulation was left mainly to the programmer (forming linked lists and all that) the streams interface has lots of little functions to do it for you. Nuff said? >--dave --Jon. -- Jon Brawn, Specialix, 3 Wintersells Road, Byfleet, Surrey, KT14 7LF, UK. Tel: +44(0)9323-54254, Fax:+44(0)9323-52781, jonb@specialix.co.uk or: {backbone}!mcsun!ukc!slxsys!jonb ``Once upon a time, not so very long ago, in a land, not so very far away''
richard@aiai.ed.ac.uk (Richard Tobin) (08/06/90)
In article <1990Aug2.143551.7104@specialix.co.uk> jonb@specialix.co.uk (Jon Brawn) writes: >>Also, I do not think I want to use a global and initialize it to >>argv[0] in body of main(), because I do not use globals! >Try this sort of thing: >char *ProgName( pname ) Why is a global function preferable than a global variable? -- Richard -- Richard Tobin, JANET: R.Tobin@uk.ac.ed AI Applications Institute, ARPA: R.Tobin%uk.ac.ed@nsfnet-relay.ac.uk Edinburgh University. UUCP: ...!ukc!ed.ac.uk!R.Tobin
tif@doorstop.austin.ibm.com (Paul Chamberlain) (08/07/90)
In article <1990Aug6.115204.20113@specialix.co.uk> jonb@specialix.co.uk (Jon Brawn) writes: >davecb@yunexus.YorkU.CA (David Collier-Brown) writes: >> Er, that substitutes a globally callable function for a globally >>referable variable. Net gain? more code to do the same thing, value >>is read-only. > ^^^^^^^^^^ >Course its read only! When was the last time you wanted to change the name >that you where invoked as? Shouldn't be allowed! Humorous mis-interpretation here. Try "the value of this is change is only visual." I agree that by using the function calls to save/retrieve the program name, you have eliminated the global. But this much effort for such a trivial function is IMNHO inappropriate for anything besides a class-room. The strict rules of a class-room have been discussed here many times. And IMNHO they teach important large-project habits using near-trivial examples due to the time limitations. I think they expect you to eventually forget these really really strict rules (for the small projects) but then remember them when they are really necessary for the large-project stuff. Is there a comp.edu group for the ensuing flames? Paul Chamberlain | I do NOT represent IBM tif@doorstop, sc30661@ausvm6 512/838-7008 | ...!cs.utexas.edu!ibmaus!auschs!doorstop.austin.ibm.com!tif
george@hls0.hls.oz (George Turczynski) (08/08/90)
In article <13491@smoke.BRL.MIL>, gwyn@smoke.BRL.MIL (Doug Gwyn) writes: > In article <1990Aug4.051827.16438@nbc1.ge.com> scott@nbc1.GE.COM (Scott Barman) writes: > >I cannot think of one rational or even irrational reason *not* to use > >global variables. > > Really? I thought this was commonly taught in structured software development > courses. Yes, it is, as a principle, to discourage people from using globals and no locals, as they might have gotten used to with such things as BASIC. It develops the ideas of information hiding and so on. The use of NO globals is however, only adopted by extremists. As has been pointed out by someone already, the information pertaining to the name of a process is GLOBAL BY DEFINITION, and cannot be accessed except by direct or indirect use of a global. No way around it. George P. J. Turczynski. | ACSnet: george@highland.oz | Phone: 61 48 683490 Computer Systems Engineer. | Fax: 61 48 683474 |---------------------- Highland Logic Pty. Ltd. | I can't speak for the Suite 1, 348-354 Argyle Street | company, I can barely Moss Vale. NSW. 2577 Australia | speak for myself...
jak@sactoh0.UUCP (Jay A. Konigsberg) (08/10/90)
In article <837@hls0.hls.oz> george@hls0.hls.oz (George Turczynski) writes: >In article <13491@smoke.BRL.MIL>, gwyn@smoke.BRL.MIL (Doug Gwyn) writes: >> In article <1990Aug4.051827.16438@nbc1.ge.com> scott@nbc1.GE.COM (Scott Barman) writes: >> >I cannot think of one rational or even irrational reason *not* to use >> >global variables. >> >> Really? I thought this was commonly taught in structured software development >> courses. > >Yes, it is, as a principle, to discourage people from using >globals and no locals, as they might have gotten used to with >such things as BASIC. It develops the ideas of information >hiding and so on. > >The use of NO globals is however, only adopted by extremists. > Yes, this is correct. In fact, there are some cases where the only way to do something is *with* globals - though these situtations are rare, they do exist. Also, there are times when you want something to be global to a set of functions. For example the getch() & ungetch() functions in K&R where the buf[] and bufp vars are shared. Another case where globals are required involves the use of a signal catcher() routine. If this routine needs information other than the signal number, the only way to get it there is via a global (when invoked by catching the signal that is). The case where I used this was returning from "raw" to "cooked" char mode. The catcher() routine had to reset ICANON and a couple of termio.??? values to their original form. Accucally, if things like globals and the neferious "goto" were really _that_ bad, they wouldn't be included in the language. The fact of the matter is though, sometimes they are needed. Just have good and supportable reasons for using them. -- ------------------------------------------------------------- Jay @ SAC-UNIX, Sacramento, Ca. UUCP=...pacbell!sactoh0!jak If something is worth doing, its worth doing correctly.
gt0178a@prism.gatech.EDU (BURNS,JIM) (08/11/90)
in various articles by (Jay A. Konigsberg),(George Turczynski),(Doug Gwyn), & (Scott Barman): >>> >I cannot think of one rational or even irrational reason *not* to use >>> >global variables. >>> Really? I thought this was commonly taught in structured software development >>> courses. >>Yes, it is, as a principle, to discourage people from using >>globals and no locals, as they might have gotten used to with >>such things as BASIC. It develops the ideas of information >>hiding and so on. >>The use of NO globals is however, only adopted by extremists. > Yes, this is correct. [Discussion in defense of globals in certain cases.] I understood the current emphasis was on not MODIFYING globals in subroutines, as this is a side-effect, and can be hard to debug for future code maintainers, unless the usage of globals is carefully documented in comments sections. It's much cleaner to pass a global as a parameter than to let subs modify them (& some say even to access them, since later programmers may say "Well, I'm using it anyway - Why can't i modify it?"), since it's more obvious you intended for the sub to have access to the variable. The only time it is critical that subs not reference globals (other than system globals such as errno) is in canned library packages, which can't 1) be dependent on the proper global environment being correctly setup, and 2) use global names internally that may collide with global names you have defined. Of course, the classic text-book example on using globals for information hiding is in writing massage routines for a small internal database. All you want to do is pass the data/key to be operated on, and the operation itself. You do NOT want to pass around the data structures for the database itself, so that the massagers will be free to change the implementation when database growth demands a reorganization of data or access method. (If you pass n arrays as the database in every call to the massage routines, you have to track down every one of those calls if the database structure changes.) '#include'-ing the appropriate set of global 'extern's in only the massage routines hides the database structure from the rest of the program. And then you have (SysV) Fortran programmers like me that are working on parent/child programs (some 78 in my system) where the only efficient solution to data sharing is some sort of IPC. I'm defining my COMMON to be in shared memory (HP-UX). -- BURNS,JIM Georgia Institute of Technology, Box 30178, Atlanta Georgia, 30332 uucp: ...!{decvax,hplabs,ncar,purdue,rutgers}!gatech!prism!gt0178a Internet: gt0178a@prism.gatech.edu