X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ian/git?p=ian-dotfiles.git;a=blobdiff_plain;f=from-cvs%2Fautotitle%2Fautotitle.c;fp=from-cvs%2Fautotitle%2Fautotitle.c;h=3ccf235eb885683eb0e28fb5d423633b3d615fbd;hp=0000000000000000000000000000000000000000;hb=4ed6df107b1db703ad86565447aa20b6385d3116;hpb=5f7cd9911c34368127da9819a3afc878976c02e5 diff --git a/from-cvs/autotitle/autotitle.c b/from-cvs/autotitle/autotitle.c new file mode 100644 index 0000000..3ccf235 --- /dev/null +++ b/from-cvs/autotitle/autotitle.c @@ -0,0 +1,609 @@ +/* + * Autotitle - copyright (C)1991 Ian Jackson (iwj10@phx.cam.ac.uk) + * + * Automatically set window titles, prompts etc. + * + * Will output the string in AUTOTITLE_STDOUT (in the environment) + * to standard output, eg for use in your prompt. + * If it can find your X server or your TERM is xterm it will + * set your icon name to AUTOTITLE_ICON and your window name + * to AUTOTITLE_WINDOW. + * + * Defaults are, respectively, + * "" (ie no output) + * "%h: %d2. %Y.[U..[U..[D./..%X.L]..R]./.." + * "%h - %d. %Y.[U..[U..[D./..%X.L]..R]./.. %U%?G(%G)%!" + * + * Environment configuration strings work a bit like printf etc: + * + * Conversion characters + * %x Left edge position of window (if WINDOWID and DISPLAY set). + * %y Top edge height. + * %X.p..q..r./.s. (pqrstrings)[ len(str)*ypos/(yscreen-ysize+1)+0.5 ] + * %Y.p..q..r./.s. Same for x,y. If window is off screen, is string s. + * The dots are delimiters - any char allowed, must + * be same at both ends of one string p, q or r etc. + * Number of strings may be 1..oo but /.string. is mandatory. + * %d***. Current directory; examples of ***'s: + * %d2. Last two components only + * %d~. Display home directory as ~ (as opposed to '' or ~) + * %de. Never use PWD environment variable even if it is correct. + * %dE. Always use PWD environment variable. + * %dU. Use home directory for uid from passwd file, not $HOME + * %d3~U. Combination of the above. + * %n Nice value + * %N.p..q..r./.s. Like %Y and %X only for nice value (range 0..39) + * %U Name of uid + * %u Numerical uid + * %G Name of gid + * %g Numerical gid + * %E***. Environment variable ***, or null string. + * %m Umask in numerical form (3 digits) (as set by umask) + * %M Umask in rwx--- form (shows perms of file opened 777) + * %h Hostname, but truncated to just the host, not FQDN + * %H Hostname - FQDN if available, otherwise just machine + * %?g***%! Do *** if gid != default for this uid + * %?G***%! Do *** if gid or group name != $GROUP (or uid's grp if no $GROUP) + * %?u***%! Do *** if uid != $USER (or $LOGNAME if no $USER) + * %?n***%! Do *** if nice value != 20 + * %?mXXX***%! Do *** if umask != XXX + * %?E###.***%! Do *** if ### is not an environment variable. + * + */ + +#ifndef NOXWINDOWS +#include +#include +#include +#endif +#ifndef NOSTDLIB +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifndef PATH_MAX +#define PATH_MAX 1024 +#endif + +#define forever for(;;) + +/* #define NOXWINDOWS /* Define this to remove the X handling code */ +/* #define NODETACH /* Define this to stop autotitle from forking ever */ +/* #define NOXTERM /* Define this to make autotitle not set xterm's titles */ +/* #define NOSTDOUT /* Define this to disable the stdout output */ +#define DEFAULTTITLE "%h - %d. %Y.[U..[U..[D./..%X.L]..R]./.. %U%?G(%G)%!" +#define DEFAULTICON "%h: %d2. %Y.[U..[U..[D./..%X.L]..R]./.." + +#define BUILDMAX 10000 +#define SMALLBUFMAX 100 +#define MAXSCALED 50 + +#ifndef __HPUX +static char lto_buf[20]; +char *ltoa(n) long n; { sprintf(lto_buf,"%ld",n); return lto_buf; } +char *ltoaoct(n) long n; { sprintf(lto_buf,"%lo",n); return lto_buf; } +#else +# define ltoaoct(n) ltostr((n),8) +#endif + +#ifndef NOXWINDOWS +struct geom { + int valid; + struct geom *child; + Window window, root; + int x,y; + unsigned w,h; +}; +void geom_force(); +struct geom wg, rg={0,&wg}; +void X_force(); +int X_error_handler(); +#endif /* !NOXWINDOWS */ + +char *user_name(), *user_nameonly(), *user_home(); +void user_force(); +gid_t user_gid(); +struct passwd *pwent; +void uid_force(); +uid_t uid; + +char *group_name(); +void group_force(); +struct group *grent; +void gid_force(); +gid_t gid; + +char *cwd_force(); +void cwd_setmode(); +int cwd_mode; + +void mkstring(); + +char build[BUILDMAX], *bp; +char *bp_end= build+BUILDMAX; +char *cp; +char *envuser=0; + +int umsk; + +#ifndef NOXWINDOWS +Display *display; +Window window; +#endif +int iflevel, ifskiplevel; + +void add_string(), add_number(), add_scaled(), add_currentdir(); +void add_umask(), detach(), add_envir(); +char *scaledstr_chop(); + +main(){ + char *controlstring, *termtype; + int child, newfd; + + umsk= umask(0); umask(umsk); + +#ifndef NOSTDOUT + mkstring(0,0, "AUTOTITLE_STDOUT",""); + if (*build) { + write(1,build,strlen(build)); + } +#endif /* !NOSTDOUT */ + +#ifndef NOXTERM + termtype= getenv("TERM"); + if (termtype && !strcmp(termtype,"xterm")) { +# if !defined(NODETACH) && !defined(NOEARLYDETACH) + newfd=dup(2); + detach(); + dup(newfd); + close(newfd); +# endif + mkstring("\033]2;","\007", "AUTOTITLE_WINDOW",DEFAULTTITLE); + write(2,build,strlen(build)); + mkstring("\033]1;","\007", "AUTOTITLE_ICON",DEFAULTICON); + write(2,build,strlen(build)); +# if !defined(NODETACH) && defined(NOEARLYDETACH) + detach(); +# endif + } else { +#endif /* !NOXTERM */ +#ifndef NOXWINDOWS +# ifndef NODETACH + detach(); +# endif /* !NODETACH */ + X_force(); + if (window) { + mkstring(0,0, "AUTOTITLE_WINDOW",DEFAULTTITLE); + XStoreName(display,window,build); + mkstring(0,0, "AUTOTITLE_ICON",DEFAULTICON); + XSetIconName(display,window,build); + XSync(display,0); + } +#endif /* ~ NOXWINDOWS */ +#ifndef NOXTERM + } +#endif + exit(0); +} + +void mkstring(initialstring,finalstring,controlenv,controlstring) + char *initialstring, *finalstring; + char *controlenv, *controlstring; +{ + static char *envuser=0, *envstring, *envgroup=0; + int inc, chkum, ifskipthis; + char smallbuffer[SMALLBUFMAX+1], *p; + + envstring= getenv(controlenv); + if (envstring) controlstring= envstring; + + bp= build; + ifskiplevel=0; iflevel=0; + cp=controlstring; + if (initialstring) add_string(initialstring); + forever { + char *pcp= strchr(cp,'%'); + if (!pcp) { + add_string(cp); + break; + } + *pcp= 0; + add_string(cp); + cp= pcp+1; + switch (*cp++) { +#ifndef NOXWINDOWS + case 'y': geom_force(&wg); add_number(wg.y); break; + case 'Y': geom_force(&rg); add_scaled(wg.y,rg.h-wg.h+1); break; + case 'x': geom_force(&wg); add_number(wg.x); break; + case 'X': geom_force(&rg); add_scaled(wg.x,rg.w-wg.w+1); break; +#else + case 'X': case 'Y': add_scaled(INT_MAX,0); /* skip scaled parameter */ + case 'x': case 'y': break; +#endif /* !NOXWINDOWS */ + case 'd': add_currentdir(); break; + case 'G': add_string(group_name()); break; + case 'g': gid_force(); add_number((long)gid); break; + case 'U': add_string(user_name()); break; + case 'u': uid_force(); add_number((long)uid); break; + case 'n': add_number(nice(0)); break; + case 'N': add_scaled(nice(0)+20,40); break; + case 'm': add_string(ltoaoct((long)umsk)); break; + case 'M': add_umask(umsk); break; + case 'E': add_envir(); break; + case 'h': case 'H': + if (!gethostname(smallbuffer,SMALLBUFMAX)) { + if (cp[-1] == 'h') { + p=strchr(smallbuffer,'.'); + if (p) *p=0; + } + add_string(smallbuffer); + } + break; + case '!': + if (iflevel>0) iflevel--; + if (ifskiplevel>0) ifskiplevel--; + break; + case '%': add_string("%%"); break; + case '?': + switch (*cp++) { + case 'E': + p= strchr(cp,'.'); + if (p) { + *p=0; + ifskipthis= 0!=getenv(cp); + cp= p+1; + } else ifskipthis=0; + break; + case 'g': gid_force(); ifskipthis= (gid==user_gid()); break; + case 'G': + gid_force(); + envgroup= envgroup?envgroup: getenv("GROUP"); + ifskipthis= + envgroup ? (gid==atol(envgroup) || !strcmp(group_name(),envgroup)) + : (gid==user_gid()); + break; + case 'u': + envuser= envuser?envuser: getenv("USER"); + envuser= envuser?envuser: getenv("LOGNAME"); + ifskipthis= (envuser && user_nameonly() && + !strcmp(envuser,user_nameonly())); + break; + case 'n': ifskipthis= (nice(0)==0); break; + case 'm': + if (sscanf(cp,"%3o%n",&chkum,&inc)==1) { + cp+=inc; + ifskipthis= umsk==chkum; + } + } /* switch() for if's */ + iflevel+=1; + ifskiplevel+= ifskiplevel ? 1 : ifskipthis; + break; + } /* switch for %'s */ + } + if (finalstring) add_string(finalstring); +} + +void add_envir() { + char *p, *e; + + p= strchr(cp,'.'); + if (p) { + *p=0; + e=getenv(cp); + cp=p+1; + if (e) add_string(e); + } +} + +void add_string(ns) + char *ns; +{ + char *nbp= bp+strlen(ns); + if (ifskiplevel || nbp > bp_end) return; + strcpy(bp,ns); + bp=nbp; +} + +void add_number(number) + long number; +{ + add_string(ltoa(number)); +} + +void add_scaled(num,denom) + int num,denom; +{ + char *sd, *sn[MAXSCALED]; + int n= 0; + double v; + + while (*cp && n1) { + add_string(sd); + } else { + add_string(sn[(int)(v*n)]); + } +} + +char *scaledstr_chop() { + char tc= *cp++; + char *rp= cp; + char *ep= strchr(cp,tc); + if (ep) { + cp= ep; + *cp++= 0; + } + return(rp); +} + +void add_umask(u) + int u; +{ + char buf[4], *bp; + int oi, h; + + if (ifskiplevel) return; + + for (oi=3; + oi; + oi--, u<<=3) { + strcpy(buf,"rwx"); + h= ((u>>6) & 7); + for (bp=buf; + bp1 && !strncmp(buf,homedir,len-1) && + (buf[len-1]=='/' || !(buf[len-1]))) { + strcpy(nbuf,homestring); + strcat(nbuf,buf+len); + buf= nbuf; + if (!strlen(buf)) buf="~"; + homeskip= strlen(homestring); + } + } + if (amdhome) { + len=strlen(amdhome); + if (amdhome[len-1] != '/') { + strcpy(nhome, amdhome); + strcat(nhome, "/"); + amdhome= nhome; + len++; + } + if (len>1 && !strncmp(buf,amdhome,len-1) && + (buf[len-1]=='/' || !(buf[len-1]))) { + strcpy(nbuf,homestring); + strcat(nbuf,buf+len); + buf= nbuf; + if (!strlen(buf)) buf="~"; + homeskip= strlen(homestring); + } + } + totalslashes=0; + for (p= buf+homeskip; *p; p++) + if (*p=='/') totalslashes++; + while (p>buf && p[-1]=='/') { *--p=0; totalslashes--; } + skipslashes= totalslashes-comps+1; + + for (p= buf+homeskip; + skipslashes>0; + p++) + if (*p=='/') skipslashes--; + if (p==buf+1 || p==buf+homeskip || p==buf+homeskip) p=buf; + + add_string(p); +} + +gid_t user_gid() { + user_force(); + return pwent? pwent->pw_gid: -1; +} + +char *user_nameonly() { + user_force(); + return pwent? pwent->pw_name: 0; +} + +char *user_home() { + user_force(); + return pwent? pwent->pw_dir: 0; +} + +char *user_name() { + user_force(); + if (pwent) return(pwent->pw_name); + return(ltoa((long)uid)); +} + +void uid_force() { + static int valid; + if (valid) return; + uid= getuid(); +} + +void user_force() { + static int valid; + if (valid) return; + uid_force(); + valid=1; + pwent= getpwuid(uid); +} + +char *group_name() { + group_force(); + if (grent) return(grent->gr_name); + return(ltoa((long)gid)); +} + +void group_force() { + static int valid; + if (valid) return; + gid_force(); + valid=1; + grent= getgrgid(gid); +} + +void gid_force() { + static int valid; + if (valid) return; + gid= getgid(); +} + +void cwd_setmode(mode) + int mode; +{ + cwd_mode=mode; /* 0= default, 1= 'e', 2= 'E' */ +} + +int different_files(a,b) + char *a, *b; +{ + struct stat staa, stab; + + return stat(a,&staa) || stat(b,&stab) || + staa.st_ino != stab.st_ino || staa.st_dev != stab.st_dev; +} + +char *cwd_force() { + static int valid=0, fail; + static char buffer[PATH_MAX+1]; + if (!valid) { + if (cwd_mode!=1 /* not 'e' */) { + char *result= getenv("PWD"); + if (result && (cwd_mode /* 'E' */ || !different_files(".",result))) { + strncpy(buffer,result,PATH_MAX); buffer[PATH_MAX]=0; + valid= 1; + } + } + if (!valid) { + valid= getcwd(buffer,PATH_MAX)!=0; + } + valid=1; + } + return buffer; +} + +#if (!defined(NOXWINDOWS) || !defined(NOXTERM)) && !defined(NODETACH) +void detach() { + close(0); close(1); close(2); if (fork()!=0) exit(0); +} +#endif /* !NODETACH */ + +#ifndef NOXWINDOWS + +void X_force() { + static valid; + char *widname, *dispname; + + if (valid) return; + window= (XID)0; display= (Display*)0; + XSetErrorHandler(X_error_handler); + + dispname= getenv("DISPLAY"); + if (!dispname) return; + display= XOpenDisplay(dispname); + if (!display) return; + + widname= getenv("WINDOWID"); + if (!widname) return; + window= (XID)(atol(widname)); + wg.window= window; +} + +int X_error_handler(edisp,eevent) + Display *edisp; + XErrorEvent *eevent; +{ + display= (Display*)0; + window= (XID)0; + wg.window= rg.window= window; + wg.x= wg.y= rg.x= rg.y= -1000; + return(0); +} + +void geom_force(g) + struct geom *g; +{ + unsigned dummyu; + int dummys; + Window dummyw; + + if (g->valid) return; + if (g->child) { + geom_force(g->child); + g->window= g->child->root; + } + X_force(); + if (g->window) { + XGetGeometry(display, + g->window,&g->root, + &dummys,&dummys,&g->w,&g->h, + &dummyu,&dummyu); + XTranslateCoordinates(display,g->window,g->root,0,0,&g->x,&g->y,&dummyw); + } else { + g->x= -1000; + g->y= -1000; + } + g->valid= 1; +} +#endif /* !NOXWINDOWS */