"Fossies" - the Fresh Open Source Software Archive

Member "astrocam-2.7.6/astrocam.c" (26 May 2009, 13714 Bytes) of package /linux/www/old/astrocam-2.7.6.tgz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "astrocam.c" see the Fossies "Dox" file reference documentation.

    1 /*
    2  * This is the AstroCam Sourcecode - http://www.wendzel.de/?sub=softw&ssub=acam
    3  *
    4  * Copyright (C) 2001-2009 Steffen Wendzel
    5  *       <steffen (at) ploetner-it (dot) de> - All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  *
   16  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   26  * SUCH DAMAGE.
   27  *
   28  */
   29 
   30 #ifndef VERSION
   31     #error "No VERSION macro defined."
   32 #endif
   33 #ifndef METAVERSION
   34     #error "No METAVERSION macro defined."
   35 #endif
   36 #ifndef PATCHLEVEL
   37     #error "No PATCHLEVEL macro defined."
   38 #endif
   39 
   40 float globver =  METAVERSION;
   41 
   42 /*#define AC_DEBUG*/
   43 
   44 #include <stdio.h>
   45 #include <stdlib.h>
   46 #include <unistd.h>
   47 #include <fcntl.h>
   48 #include <stddef.h>
   49 #include <errno.h>
   50 #include <signal.h>
   51 #include <sys/time.h>
   52 #include <sys/times.h>
   53 #include <syslog.h>
   54 #include <sys/types.h>
   55 #include <sys/ipc.h>
   56 #include <sys/msg.h>
   57 #include <sys/stat.h>
   58 #include <string.h>
   59 
   60 #ifdef __linux__
   61 #include <linux/version.h>
   62 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
   63 /* Linux 2.4 or newer */
   64 #include <sys/io.h>
   65 #else
   66 /* Linux 2.2.x (and older? hm.. didn't test older versions...) */
   67 #include <asm/io.h>
   68 #endif
   69 #endif
   70 
   71 #if defined(__NetBSD__) || defined(__OpenBSD__)
   72   #include <sys/types.h>
   73   #include <sys/syscall.h>
   74   #include <i386/sysarch.h>
   75   #include <i386/pio.h>
   76   #define BSD
   77 #endif
   78 
   79 #ifdef __FreeBSD__
   80   #include <sys/types.h>
   81   #include <sys/syscall.h>
   82   #include <machine/sysarch.h>
   83   #include <machine/cpufunc.h>
   84 #endif
   85 
   86 #define CONFIG_FILE "/etc/astrocam.conf"
   87 #define PIDFILE     "/var/log/acam_pid"
   88 #define PID_CHMOD   (S_IRUSR | S_IWUSR)
   89 
   90 #define MAX_MOT    3
   91 #define MAX_PHASEN 4
   92 
   93 #define PA_L 0
   94 #define PA_R 4
   95 #define PB_L 0
   96 #define PB_R 32
   97 
   98 #define CTRL_MOT_X 0
   99 #define CTRL_MOT_Y 64
  100 #define CTRL_MOT_Z 128
  101 
  102 /* some errors */
  103 #define ERROR_INIT  perror("AstroCamInit");
  104 #define ERROR_EXIT  perror("AstroCamShutdown");
  105 
  106 #ifdef __FreeBSD__
  107 int   devfd;
  108 #endif
  109 
  110 long  pos[MAX_MOT];
  111 int   mot_power[MAX_MOT],
  112       srvid;
  113 
  114 /* my syslog function */
  115 void logit(char *string);
  116 
  117 u_char mot_ctrl[MAX_MOT] =
  118 {
  119   CTRL_MOT_X,
  120   CTRL_MOT_Y,
  121   CTRL_MOT_Z
  122 };
  123 
  124 u_char phase[MAX_PHASEN] =
  125 {
  126   PA_L + PB_L,
  127   PA_R + PB_L,
  128   PA_R + PB_R,
  129   PA_L + PB_R
  130 };
  131 
  132 typedef struct
  133 {
  134   char var[100];
  135   char value[100];
  136 } entry;
  137 
  138 typedef struct
  139 {
  140   float conf_ver;
  141   int maxdreh,
  142       mindreh;
  143   int maxvdreh,
  144       minvdreh;
  145   int curpos,
  146       curvpos;
  147   int negation;
  148   unsigned int iobase;
  149   unsigned int ipckey;
  150 } astrocam_conf;
  151 astrocam_conf globconf;
  152 
  153 typedef struct
  154 {
  155   long mtyp;
  156   char data[10];
  157 } ipcrecv;
  158 
  159 void outportb(unsigned char b)
  160 {
  161   #ifdef linux
  162     outb(b, globconf.iobase);
  163     outb(0, globconf.iobase + 2);
  164     outb(1, globconf.iobase + 2);
  165   #endif
  166 
  167   #if defined(BSD) || defined(__FreeBSD__)
  168     outb(globconf.iobase, b);
  169     outb(globconf.iobase + 2, 0);
  170     outb(globconf.iobase + 2, 1);
  171   #endif
  172 }
  173 
  174 void AstroCam_Step(int mot, long n)
  175 {
  176   int i;
  177   unsigned char ctrl = mot_ctrl[mot];
  178 
  179   if(n>0){
  180     for(i=0; i<n; i++){
  181       pos[mot]++;
  182       outportb(ctrl + phase[pos[mot] % MAX_PHASEN]);
  183       usleep(100);
  184     }
  185   }else{
  186     for(i=0; i>n; i--){
  187       pos[mot]--;
  188       outportb(ctrl + phase[pos[mot] % MAX_PHASEN]);
  189       usleep(100);
  190       }
  191    }
  192 }
  193 
  194 #ifdef BSD
  195 void ioport()
  196 {
  197   u_long iomap[32];
  198   struct i386_set_ioperm_args ioperm;
  199 
  200   /* code part found in usenet */
  201   ioperm.iomap = iomap;
  202   syscall(SYS_sysarch, I386_GET_IOPERM, (char *) &ioperm);
  203   iomap[globconf.iobase >> 5] &= ~(1 << (globconf.iobase & 0x1f));
  204   syscall(SYS_sysarch, I386_SET_IOPERM, (char *) &ioperm);
  205 }
  206 #endif
  207 
  208 int AstroCamInit()
  209 {
  210   int i;
  211 
  212   #ifdef BSD
  213     if(getuid()==0){
  214        ioport(globconf.iobase);
  215        ioport(globconf.iobase + 1);
  216        ioport(globconf.iobase + 2);
  217     }else{
  218        fprintf(stderr, "AstroCamInit(): You need root-access to open an i/o-device directly.\n");
  219        fflush(stderr);
  220        exit(0);
  221       return -1;
  222     }
  223   #endif
  224 
  225   #ifdef linux
  226     if(ioperm(globconf.iobase, 3, 1)){
  227        ERROR_INIT
  228        fflush(stderr);
  229       return -1;
  230     }
  231   #endif
  232 
  233   #ifdef __FreeBSD__
  234     if((devfd=open("/dev/io", O_WRONLY))<0){
  235        ERROR_INIT
  236        fflush(stderr);
  237       return -1;
  238     }
  239   #endif
  240 
  241   for(i=0;i<MAX_MOT;i++){
  242      pos[i]=400000;
  243      mot_power[i]=-1;     
  244   }
  245   return 0;
  246 }
  247 
  248 int AstroCamShutdown()
  249 {
  250   #ifdef linux
  251     if(ioperm(globconf.iobase, 3, 0)){
  252        ERROR_EXIT
  253       return -1;
  254     }
  255   #endif
  256 
  257   #ifdef __FreeBSD__
  258     if(close(devfd)!=0){
  259        ERROR_EXIT
  260       return -1;
  261     }
  262   #endif
  263   return 0;
  264 }
  265 
  266 /* create the daemon */
  267 void dm(pid_t *mypid)
  268 {
  269   setsid();
  270   umask(0);
  271   *mypid=getpid();
  272 }
  273 
  274 void welcome()
  275 {
  276   printf("\n\x1B[32mAstroCam Daemon " VERSION PATCHLEVEL " \x1B[0m [ "
  277          "Written and Copyright 2001-2009 by Steffen Wendzel steffen "
  278          "(at) ploetner-it (dot) de ]\x1B[32m running...\x1B[0m\n");
  279 }
  280 
  281 void sighndl(int signo)
  282 {
  283   logit("signal response - shutdown now !");
  284 
  285   unlink(PIDFILE);
  286   if(AstroCamShutdown()<0)
  287      perror("AstroCamShutdown(): ");
  288   if(signo!=1000)
  289     if(msgctl(srvid, IPC_RMID, NULL)==-1)
  290       logit("msgctl (rmid) problem!");
  291   exit(1);
  292 }
  293 
  294 void logit(char *string)
  295 {
  296   openlog("astrocam", LOG_PID, LOG_DAEMON);
  297   syslog(LOG_DAEMON|LOG_ERR, "%s", string);
  298   closelog();
  299 }
  300 
  301 int chkrunstat()
  302 {
  303   int file;
  304 
  305   if((file = open(PIDFILE, O_RDONLY))<0)
  306      return 0;
  307   else{
  308      fprintf(stderr, "It seems that the astrocam daemon is already "
  309                      "running. Please wait while restarting...\n");
  310      return -1;
  311   }
  312 }
  313 
  314 int restartac(void)
  315 {
  316   int file;
  317   char buf[11] = { '\0' };
  318   struct stat s;
  319   int sec_sd = 0; /* security shutdown */
  320   pid_t pid;
  321 
  322   if((file=open(PIDFILE, O_RDONLY))<0)
  323      return -1;
  324 
  325   /* 2.6.5: needed for the next two steps */
  326   if(fstat(file, &s)==-1) {
  327      perror("fstat(" PIDFILE ")");
  328      exit(1);
  329   }
  330   /* 2.6.5: check if this file is writable by group/others and if this
  331    *        file is a symlink to prevent symlink hacks.
  332    */
  333   if(S_ISLNK(s.st_mode) || (S_IWOTH & s.st_mode) || (S_IWGRP &s.st_mode)) {
  334      fprintf(stderr, "File mode of " PIDFILE " has changed or file is a symlink!\n");
  335      sec_sd=1;
  336   }
  337   /* 2.6.5: check if owner isn't root */
  338   if(s.st_uid!=0) {
  339      fprintf(stderr, "Owner of " PIDFILE " is NOT uid zero (root)!\n");
  340      sec_sd=1;
  341   }
  342   if(sec_sd) {
  343      fprintf(stderr, "I will exit now. Please kill the running astrocam"
  344                  " process by hand and delete " PIDFILE " for security"
  345              " reasons.\n");
  346      exit(1);
  347   }
  348 
  349   if(read(file, buf, 10)<1)
  350      return -1;
  351   if((pid=atoi(buf))) {
  352      kill(pid, SIGTERM);
  353   }
  354 
  355   close(file);  
  356   unlink(PIDFILE);
  357   return 0;
  358 }
  359 
  360 astrocam_conf AC_ReadConf(void)
  361 {
  362   astrocam_conf acam_conf;
  363   FILE *file;
  364   entry aentry;
  365   
  366   bzero(&acam_conf, sizeof(astrocam_conf));
  367   
  368   if((file = fopen(CONFIG_FILE, "r"))==NULL){
  369     perror(CONFIG_FILE);
  370     exit(1);
  371   }
  372 
  373   while(fscanf(file, "%98s\t%98s\n", aentry.var, aentry.value)!=EOF)
  374   {
  375     printf("%14s: %s\n", aentry.var, aentry.value);
  376     if(strcmp(aentry.var, "version")==0)
  377       acam_conf.conf_ver = atof(aentry.value);
  378     else if(strcmp(aentry.var, "ipckey")==0)
  379       acam_conf.ipckey = atoi(aentry.value);
  380     else if(strcmp(aentry.var, "maxdreh")==0)
  381       acam_conf.maxdreh = atoi(aentry.value);
  382     else if(strcmp(aentry.var, "mindreh")==0)
  383       acam_conf.mindreh = atoi(aentry.value);
  384     else if(strcmp(aentry.var, "maxvdreh")==0)
  385       acam_conf.maxvdreh = atoi(aentry.value);
  386     else if(strcmp(aentry.var, "minvdreh")==0)
  387       acam_conf.minvdreh = atoi(aentry.value);
  388     else if(strcmp(aentry.var, "iobase")==0)
  389       acam_conf.iobase = atoi(aentry.value);
  390     else if(strcmp(aentry.var, "negation")==0) {
  391       if(aentry.value[1]=='n') /* on */
  392          acam_conf.negation = 1;
  393       else /* off */
  394          acam_conf.negation = 0;
  395     } else if(strcmp(aentry.var, "design")!=0
  396            && strcmp(aentry.var, "contenturl")!=0
  397            && strcmp(aentry.var, "picfile")!=0
  398            && strcmp(aentry.var, "refreshtime")!=0
  399            && strcmp(aentry.var, "imagesize-x")!=0
  400            && strcmp(aentry.var, "imagesize-y")!=0) {
  401       fprintf(stderr, CONFIG_FILE ": unsupported var found! "
  402             "name is '%s'\n", aentry.var);
  403       sighndl(0);
  404       exit(0);
  405     }
  406   }
  407   fclose(file);
  408   return acam_conf;
  409 }
  410 
  411 int main(void)
  412 {
  413   FILE *fdpid;
  414   pid_t mypid;
  415   char *buf;
  416   int j;
  417   ipcrecv recvdata;
  418   
  419   j=0x0;
  420   
  421   if(geteuid()!=0){
  422      logit("need root access!");
  423      fprintf(stderr, "it needs root-access to open the i/o-device directly!\n");
  424      return -1;
  425   }
  426   
  427   if(chkrunstat()<0)
  428      if(restartac()<0){
  429         fprintf(stderr, "--- Alert: Can't restart astrocam daemon!\n");
  430         return -1;
  431      }
  432   /* 2.7.2: In the past AC_ReadConf() was called after AstroCamInit()
  433    * was done.
  434    */
  435   globconf=AC_ReadConf();
  436   if(globconf.conf_ver!=globver){
  437      fprintf(stderr, "incompatible version in configuration file "
  438                      CONFIG_FILE "!\n");
  439      sighndl(1000);
  440      exit(1);
  441   }
  442   printf("using IO address 0x%x...\n", globconf.iobase);
  443   
  444   if(AstroCamInit()!=0){
  445      perror("AstroCamInit() returned zero. exiting.");
  446      sighndl(1000);
  447      return -1;
  448   }
  449  
  450   signal(SIGINT|SIGQUIT|SIGTERM, sighndl);
  451 
  452   /* default init position is 0 */
  453   globconf.curpos=0;
  454   globconf.curvpos=0;
  455   
  456   if((srvid=msgget(globconf.ipckey, S_IRWXU|S_IWGRP|S_IWOTH|IPC_CREAT))==-1){
  457     perror("msgget");
  458     sighndl(1000);
  459     return -1;
  460   }
  461 
  462   if((mypid=fork())<0){
  463      perror("fork() ");
  464      sighndl(0);
  465      return -1;
  466   }else if(mypid!=0){
  467      exit(1);
  468   }else{
  469      dm(&mypid);
  470      printf("\nstoring astrocam process-id in " PIDFILE "! [%d]", mypid);
  471   }
  472 
  473   if((buf=(char *)malloc(11*sizeof(char)))==NULL){
  474      perror("malloc ");
  475      sighndl(0);
  476      return -1;
  477   }
  478   snprintf(buf, 10, "%i", mypid);
  479   if((fdpid=fopen(PIDFILE, "w+"))==NULL){
  480      perror(PIDFILE);
  481      sighndl(0);
  482      return -1;
  483   }
  484   
  485   /* v. 2.6.3: secure file perm: -rw------- */
  486   /* (don't stop if chmod() fails, AC will run anyway) */
  487   if(fchmod(fileno(fdpid), PID_CHMOD)!=0) {
  488      perror(PIDFILE);
  489      return -1;
  490   }
  491     
  492   /* NOW write the content */
  493   if(fputs(buf, fdpid)<0) {
  494      perror("fputs");
  495      return -1;
  496   }
  497   fclose(fdpid);
  498 
  499   welcome();
  500   fflush(stdout);
  501   
  502   while(msgrcv(srvid, &recvdata, 10, 0, MSG_NOERROR)!=-1) {
  503     /* PHP sends on recvdata.data[5] and Perl on [0]. We need a
  504      * offset that is equal in both cases
  505      */
  506     if(recvdata.data[0]=='s') /* PHP-> Perl */
  507        recvdata.data[0]=recvdata.data[5];
  508 
  509 /* implemented with version 2.6.0 */
  510     if(globconf.negation==1) {
  511        if(recvdata.data[0]=='L') recvdata.data[0]='R';
  512        if(recvdata.data[0]=='l') recvdata.data[0]='r';
  513        if(recvdata.data[0]=='R') recvdata.data[0]='L';
  514        if(recvdata.data[0]=='r') recvdata.data[0]='l';
  515        /* do not implement this feature for the hor. movement
  516        if(recvdata.data[0]=='d') recvdata.data[0]='u';
  517        if(recvdata.data[0]=='u') recvdata.data[0]='d';*/
  518     }
  519 /* hpos stuff */
  520     if(recvdata.data[0]!='0')
  521     {
  522        j=0;
  523        if(recvdata.data[0]=='L'){
  524          if(globconf.mindreh<globconf.curpos-19)
  525            while(j<20){
  526          AstroCam_Step(3, 1);
  527          j++;
  528          globconf.curpos--;
  529        }
  530        }else if(recvdata.data[0]=='l'){
  531          if(globconf.mindreh<globconf.curpos-9)
  532            while(j<10){
  533          AstroCam_Step(3, 1);
  534          j++;
  535          globconf.curpos--;
  536        }
  537        }else if(recvdata.data[0]=='R'){
  538          if(globconf.maxdreh>globconf.curpos+19)
  539            while(j<20){
  540          AstroCam_Step(0, -1);
  541          j++;
  542          globconf.curpos++;
  543        }
  544        }else if(recvdata.data[0]=='r'){
  545          if(globconf.maxdreh>globconf.curpos+9)
  546        while(j<10){
  547          AstroCam_Step(0, -1);
  548          j++;
  549          globconf.curpos++;
  550        }
  551 /* vpos stuff */
  552        }else if(recvdata.data[0]=='u'){
  553          if(globconf.maxvdreh>globconf.curvpos+9)
  554            while(j<10){
  555          AstroCam_Step(1, 1);
  556          j++;
  557          globconf.curvpos++;
  558        }
  559        }else if(recvdata.data[0]=='d'){
  560          if(globconf.minvdreh<globconf.curvpos-9)
  561            while(j<10){
  562          AstroCam_Step(1, -1);
  563          j++;
  564          globconf.curvpos--;
  565        }
  566 /* error mngmnt */
  567        } else { /* simple error management. implemented with v. 2.5.2 */
  568           logit("error: recv bad char from webinterface");
  569        }
  570 #if defined AC_DEBUG
  571        printf("%s", recvdata.data);fflush(stdout);
  572        printf("\ncurpos: %i  (min: %i | max: %i)\n",
  573          globconf.curpos,
  574          globconf.mindreh,
  575          globconf.maxdreh);
  576 #endif
  577     }
  578   }
  579 
  580   logit("msgrcv-error in mainloop!");
  581   sighndl(0);
  582   free(buf);
  583   exit(0);
  584 }
  585